vendor: github.com/moby/swarmkit/v2 v2.0.0-20230808164555-1983e41a9fff

notable changes:

- Free unused volumes in more cases
- Convert BasicKeyRequest to KeyRequest to use cloudflare/cfssl 1.x.x
- reduce direct imports of logrus

diffs:

- github.com/cloudflare/cfssl v1.6.4; full diff: https://github.com/cloudflare/cfssl/compare/5d63dbd981b5...v1.6.4
- github.com/moby/swarmkit/v2; full diff: https://github.com/moby/swarmkit/compare/bc71908479e5...60421a63a7f148ba1ec7d35c55e4cf9ac03d6b78

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
Sebastiaan van Stijn 2023-08-10 13:50:29 +02:00
parent 7b66ae1531
commit b9d9504df5
No known key found for this signature in database
GPG key ID: 76698F39D527CE8C
385 changed files with 49935 additions and 316 deletions

View file

@ -969,7 +969,7 @@ func (s *DockerSwarmSuite) TestSwarmRepeatedRootRotation(c *testing.T) {
if i%2 != 0 {
cert, _, key, err = initca.New(&csr.CertificateRequest{
CN: "newRoot",
KeyRequest: csr.NewBasicKeyRequest(),
KeyRequest: csr.NewKeyRequest(),
CA: &csr.CAConfig{Expiry: ca.RootCAExpiration},
})
assert.NilError(c, err)

View file

@ -23,7 +23,7 @@ require (
github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs v1.15.17
github.com/aws/smithy-go v1.13.5
github.com/bsphere/le_go v0.0.0-20200109081728-fc06dab2caa8
github.com/cloudflare/cfssl v0.0.0-20180323000720-5d63dbd981b5
github.com/cloudflare/cfssl v1.6.4
github.com/container-orchestrated-devices/container-device-interface v0.6.0
github.com/containerd/cgroups/v3 v3.0.2
github.com/containerd/containerd v1.6.22
@ -65,7 +65,7 @@ require (
github.com/moby/locker v1.0.1
github.com/moby/patternmatcher v0.5.0
github.com/moby/pubsub v1.0.0
github.com/moby/swarmkit/v2 v2.0.0-20230713153928-bc71908479e5
github.com/moby/swarmkit/v2 v2.0.0-20230814163642-60421a63a7f1
github.com/moby/sys/mount v0.3.3
github.com/moby/sys/mountinfo v0.6.2
github.com/moby/sys/sequential v0.5.0
@ -158,6 +158,7 @@ require (
github.com/hashicorp/golang-lru v0.5.4 // indirect
github.com/in-toto/in-toto-golang v0.5.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/jmoiron/sqlx v1.3.3 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
github.com/mitchellh/hashstructure/v2 v2.0.2 // indirect
github.com/mitchellh/reflectwalk v1.0.2 // indirect
@ -176,6 +177,9 @@ require (
github.com/tonistiigi/fsutil v0.0.0-20230629203738-36ef4d8c0dbb // indirect
github.com/tonistiigi/go-actions-cache v0.0.0-20220404170428-0bdeb6e1eac7 // indirect
github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea // indirect
github.com/weppos/publicsuffix-go v0.15.1-0.20210511084619-b1f36a2d6c0b // indirect
github.com/zmap/zcrypto v0.0.0-20210511125630-18f1e0152cfc // indirect
github.com/zmap/zlint/v3 v3.1.0 // indirect
go.etcd.io/etcd/client/pkg/v3 v3.5.6 // indirect
go.etcd.io/etcd/pkg/v3 v3.5.6 // indirect
go.etcd.io/etcd/raft/v3 v3.5.6 // indirect

View file

@ -293,8 +293,8 @@ github.com/cilium/ebpf v0.9.1/go.mod h1:+OhNOIXx/Fnu1IE8bJz2dzOA+VSfyTfdNUVdlQnx
github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag=
github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cloudflare/cfssl v0.0.0-20180323000720-5d63dbd981b5 h1:PqZ3bA4yzwywivzk7PBQWngJp2/PAS0bWRZerKteicY=
github.com/cloudflare/cfssl v0.0.0-20180323000720-5d63dbd981b5/go.mod h1:yMWuSON2oQp+43nFtAV/uvKQIFpSPerB57DCt9t8sSA=
github.com/cloudflare/cfssl v1.6.4 h1:NMOvfrEjFfC63K3SGXgAnFdsgkmiq4kATme5BfcqrO8=
github.com/cloudflare/cfssl v1.6.4/go.mod h1:8b3CQMxfWPAeom3zBnGJ6sd+G1NkL5TXqmDXacb+1J0=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI=
@ -895,6 +895,8 @@ github.com/jmespath/go-jmespath v0.3.0/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeY
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
github.com/jmoiron/sqlx v1.2.1-0.20190826204134-d7d95172beb5/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks=
github.com/jmoiron/sqlx v1.3.3 h1:j82X0bf7oQ27XeqxicSZsTU5suPwKElg3oyxNn43iTk=
github.com/jmoiron/sqlx v1.3.3/go.mod h1:2BljVx/86SuTyjE+aPYlHCTNvZrnJXghYGpNiXLBMCQ=
github.com/joefitzgerald/rainbow-reporter v0.1.0/go.mod h1:481CNgqmVHQZzdIbN52CupLJyoVwB10FQ/IQlF1pdL8=
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
@ -975,6 +977,7 @@ github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vq
github.com/mattn/go-shellwords v1.0.6/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o=
github.com/mattn/go-shellwords v1.0.10/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y=
github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/mattn/go-zglob v0.0.1/go.mod h1:9fxibJccNxU2cnpIKLRRFA7zX7qhkJIQWBb449FYHOo=
github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
@ -1022,8 +1025,8 @@ github.com/moby/patternmatcher v0.5.0 h1:YCZgJOeULcxLw1Q+sVR636pmS7sPEn1Qo2iAN6M
github.com/moby/patternmatcher v0.5.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc=
github.com/moby/pubsub v1.0.0 h1:jkp/imWsmJz2f6LyFsk7EkVeN2HxR/HTTOY8kHrsxfA=
github.com/moby/pubsub v1.0.0/go.mod h1:bXSO+3h5MNXXCaEG+6/NlAIk7MMZbySZlnB+cUQhKKc=
github.com/moby/swarmkit/v2 v2.0.0-20230713153928-bc71908479e5 h1:o6x+wIX1vKD0kJlEqe8M9TLIe0SK8lnGcA6XoJtaFqg=
github.com/moby/swarmkit/v2 v2.0.0-20230713153928-bc71908479e5/go.mod h1:XUMlwIIC+wrwBDMUjxEvk5Z8FPoIPM8LdBw7w/Zu1rg=
github.com/moby/swarmkit/v2 v2.0.0-20230814163642-60421a63a7f1 h1:B/mrXLRdSVXXJvwVNatNe+Yf+9WMS/TT7+mYKFMbgF0=
github.com/moby/swarmkit/v2 v2.0.0-20230814163642-60421a63a7f1/go.mod h1:qYvjIScIddAio4DaXFZUyNuRxcHhm2Srm6GIrA/G/5c=
github.com/moby/sys/mount v0.1.0/go.mod h1:FVQFLDRWwyBjDTBNQXDlWnSFREqOo3OKX9aqhmeoo74=
github.com/moby/sys/mount v0.1.1/go.mod h1:FVQFLDRWwyBjDTBNQXDlWnSFREqOo3OKX9aqhmeoo74=
github.com/moby/sys/mount v0.3.3 h1:fX1SVkXFJ47XWDoeFW4Sq7PdQJnV2QIDZAqjNqgEjUs=
@ -1054,6 +1057,7 @@ github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
github.com/mozilla/tls-observatory v0.0.0-20190404164649-a3c1b6cfecfd/go.mod h1:SrKMQvPiws7F7iqYp8/TX+IhxCYhzr6N/1yb8cwHsGk=
github.com/mozilla/tls-observatory v0.0.0-20200317151703-4fa42e1c2dee/go.mod h1:SrKMQvPiws7F7iqYp8/TX+IhxCYhzr6N/1yb8cwHsGk=
github.com/mreiferson/go-httpclient v0.0.0-20160630210159-31f0106b4474/go.mod h1:OQA4XLvDbMgS8P0CevmM4m9Q3Jq4phKUzcocxuGJ5m8=
github.com/mrunalp/fileutils v0.0.0-20200520151820-abd8a0e76976/go.mod h1:x8F1gnqOkIEiO4rqoeEEEqQbo7HjGMTvyoq3gej4iT0=
github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ=
github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
@ -1264,6 +1268,7 @@ github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeV
github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.3.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
@ -1395,6 +1400,9 @@ github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1
github.com/vishvananda/netns v0.0.2 h1:Cn05BRLm+iRP/DZxyVSsfVyrzgjDbwHwkVt38qvXnNI=
github.com/vishvananda/netns v0.0.2/go.mod h1:yitZXdAVI+yPFSb4QUe+VW3vOVl4PZPNcBgbPxAtJxw=
github.com/vmware/govmomi v0.20.3/go.mod h1:URlwyTFZX72RmxtxuaFL2Uj3fD1JTvZdx59bHWk6aFU=
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/willf/bitset v1.1.11-0.20200630133818-d5bec3311243/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4=
github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr3+MjI=
github.com/xanzy/go-gitlab v0.31.0/go.mod h1:sPLojNBn68fMUWSxIJtdVVIP8uSBYqesTfDUseX11Ug=
@ -1418,6 +1426,13 @@ github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5t
github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs=
github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA=
github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg=
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=
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
@ -1525,6 +1540,7 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201117144127-c1f2f97bffc9/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20201124201722-c8d3bf9c5392/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
@ -1735,6 +1751,7 @@ golang.org/x/sys v0.0.0-20201013081832-0aaa2718063a/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20201112073958-5cba982894dd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201117170446-d9b008d0a637/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-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201202213521-69691e467435/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=

View file

@ -3,7 +3,7 @@ package api
import (
"encoding/json"
"io/ioutil"
"io"
"net/http"
"github.com/cloudflare/cfssl/errors"
@ -92,7 +92,7 @@ func (h HTTPHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
func readRequestBlob(r *http.Request) (map[string]string, error) {
var blob map[string]string
body, err := ioutil.ReadAll(r.Body)
body, err := io.ReadAll(r.Body)
if err != nil {
return nil, err
}
@ -176,7 +176,7 @@ type Response struct {
Messages []ResponseMessage `json:"messages"`
}
// NewSuccessResponse is a shortcut for creating new successul API
// NewSuccessResponse is a shortcut for creating new successful API
// responses.
func NewSuccessResponse(result interface{}) Response {
return Response{

View file

@ -10,7 +10,6 @@ import (
"crypto/sha256"
"encoding/hex"
"fmt"
"io/ioutil"
"os"
"strings"
)
@ -52,11 +51,11 @@ func New(key string, ad []byte) (*Standard, error) {
case "env":
key = os.Getenv(splitKey[1])
case "file":
data, err := ioutil.ReadFile(splitKey[1])
data, err := os.ReadFile(splitKey[1])
if err != nil {
return nil, err
}
key = string(data)
key = strings.TrimSpace(string(data))
default:
return nil, fmt.Errorf("unknown key prefix: %s", splitKey[0])
}

View file

@ -27,11 +27,11 @@ Currently supported:
### Use goose to start and terminate a MySQL DB
To start a MySQL using goose:
goose -path $GOPATH/src/github.com/cloudflare/cfssl/certdb/mysql up
goose -path certdb/mysql up
To tear down a MySQL DB using goose
goose -path $GOPATH/src/github.com/cloudflare/cfssl/certdb/mysql down
goose -path certdb/mysql down
Note: the administration of MySQL DB is not included. We assume
the databases being connected to are already created and access control
@ -40,11 +40,11 @@ is properly handled.
### Use goose to start and terminate a PostgreSQL DB
To start a PostgreSQL using goose:
goose -path $GOPATH/src/github.com/cloudflare/cfssl/certdb/pg up
goose -path certdb/pg up
To tear down a PostgreSQL DB using goose
goose -path $GOPATH/src/github.com/cloudflare/cfssl/certdb/pg down
goose -path certdb/pg down
Note: the administration of PostgreSQL DB is not included. We assume
the databases being connected to are already created and access control
@ -53,11 +53,11 @@ is properly handled.
### Use goose to start and terminate a SQLite DB
To start a SQLite DB using goose:
goose -path $GOPATH/src/github.com/cloudflare/cfssl/certdb/sqlite up
goose -path certdb/sqlite up
To tear down a SQLite DB using goose
goose -path $GOPATH/src/github.com/cloudflare/cfssl/certdb/sqlite down
goose -path certdb/sqlite down
## CFSSL Configuration

View file

@ -1,7 +1,11 @@
package certdb
import (
"database/sql"
"encoding/json"
"time"
"github.com/jmoiron/sqlx/types"
)
// CertificateRecord encodes a certificate and its metadata
@ -15,6 +19,46 @@ type CertificateRecord struct {
Expiry time.Time `db:"expiry"`
RevokedAt time.Time `db:"revoked_at"`
PEM string `db:"pem"`
// the following fields will be empty for data inserted before migrate 002 has been run.
IssuedAt *time.Time `db:"issued_at"`
NotBefore *time.Time `db:"not_before"`
MetadataJSON types.JSONText `db:"metadata"`
SANsJSON types.JSONText `db:"sans"`
CommonName sql.NullString `db:"common_name"`
}
// SetMetadata sets the metadata json
func (c *CertificateRecord) SetMetadata(meta map[string]interface{}) error {
marshaled, err := json.Marshal(meta)
if err != nil {
return err
}
c.MetadataJSON = types.JSONText(marshaled)
return nil
}
// GetMetadata returns the json metadata
func (c *CertificateRecord) GetMetadata() (map[string]interface{}, error) {
var meta map[string]interface{}
err := c.MetadataJSON.Unmarshal(&meta)
return meta, err
}
// SetSANs sets the list of sans
func (c *CertificateRecord) SetSANs(meta []string) error {
marshaled, err := json.Marshal(meta)
if err != nil {
return err
}
c.SANsJSON = types.JSONText(marshaled)
return nil
}
// GetSANs returns the json SANs
func (c *CertificateRecord) GetSANs() ([]string, error) {
var sans []string
err := c.SANsJSON.Unmarshal(&sans)
return sans, err
}
// OCSPRecord encodes a OCSP response body and its metadata
@ -32,7 +76,9 @@ type Accessor interface {
GetCertificate(serial, aki string) ([]CertificateRecord, error)
GetUnexpiredCertificates() ([]CertificateRecord, error)
GetRevokedAndUnexpiredCertificates() ([]CertificateRecord, error)
GetUnexpiredCertificatesByLabel(labels []string) (crs []CertificateRecord, err error)
GetRevokedAndUnexpiredCertificatesByLabel(label string) ([]CertificateRecord, error)
GetRevokedAndUnexpiredCertificatesByLabelSelectColumns(label string) ([]CertificateRecord, error)
RevokeCertificate(serial, aki string, reasonCode int) error
InsertOCSP(rr OCSPRecord) error
GetOCSP(serial, aki string) ([]OCSPRecord, error)

View file

@ -8,7 +8,7 @@ import (
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"os"
"regexp"
"strconv"
"strings"
@ -19,6 +19,9 @@ import (
"github.com/cloudflare/cfssl/helpers"
"github.com/cloudflare/cfssl/log"
ocspConfig "github.com/cloudflare/cfssl/ocsp/config"
// empty import of zlint/v3 required to have lints registered.
_ "github.com/zmap/zlint/v3"
"github.com/zmap/zlint/v3/lint"
)
// A CSRWhitelist stores booleans for fields in the CSR. If a CSRWhitelist is
@ -32,7 +35,7 @@ import (
// mechanism.
type CSRWhitelist struct {
Subject, PublicKeyAlgorithm, PublicKey, SignatureAlgorithm bool
DNSNames, IPAddresses, EmailAddresses bool
DNSNames, IPAddresses, EmailAddresses, URIs bool
}
// OID is our own version of asn1's ObjectIdentifier, so we can define a custom
@ -81,6 +84,8 @@ type SigningProfile struct {
ExpiryString string `json:"expiry"`
BackdateString string `json:"backdate"`
AuthKeyName string `json:"auth_key"`
CopyExtensions bool `json:"copy_extensions"`
PrevAuthKeyName string `json:"prev_auth_key"` // to support key rotation
RemoteName string `json:"remote"`
NotBefore time.Time `json:"not_before"`
NotAfter time.Time `json:"not_after"`
@ -89,11 +94,26 @@ type SigningProfile struct {
CTLogServers []string `json:"ct_log_servers"`
AllowedExtensions []OID `json:"allowed_extensions"`
CertStore string `json:"cert_store"`
// LintErrLevel controls preissuance linting for the signing profile.
// 0 = no linting is performed [default]
// 2..3 = reserved
// 3 = all lint results except pass are considered errors
// 4 = all lint results except pass and notice are considered errors
// 5 = all lint results except pass, notice and warn are considered errors
// 6 = all lint results except pass, notice, warn and error are considered errors.
// 7 = lint is performed, no lint results are treated as errors.
LintErrLevel lint.LintStatus `json:"lint_error_level"`
// ExcludeLints lists ZLint lint names to exclude from preissuance linting.
ExcludeLints []string `json:"ignored_lints"`
// ExcludeLintSources lists ZLint lint sources to exclude from preissuance
// linting.
ExcludeLintSources []string `json:"ignored_lint_sources"`
Policies []CertificatePolicy
Expiry time.Duration
Backdate time.Duration
Provider auth.Provider
PrevProvider auth.Provider // to suppport key rotation
RemoteProvider auth.Provider
RemoteServer string
RemoteCAs *x509.CertPool
@ -102,6 +122,11 @@ type SigningProfile struct {
NameWhitelist *regexp.Regexp
ExtensionWhitelist map[string]bool
ClientProvidesSerialNumbers bool
// LintRegistry is the collection of lints that should be used if
// LintErrLevel is configured. By default all ZLint lints are used. If
// ExcludeLints or ExcludeLintSources are set then this registry will be
// filtered in populate() to exclude the named lints and lint sources.
LintRegistry lint.Registry
}
// UnmarshalJSON unmarshals a JSON string into an OID.
@ -229,7 +254,7 @@ func (p *SigningProfile) populate(cfg *Config) error {
if p.AuthKeyName != "" {
log.Debug("match auth key in profile to auth_keys section")
if key, ok := cfg.AuthKeys[p.AuthKeyName]; ok == true {
if key, ok := cfg.AuthKeys[p.AuthKeyName]; ok {
if key.Type == "standard" {
p.Provider, err = auth.New(key.Key, nil)
if err != nil {
@ -248,6 +273,27 @@ func (p *SigningProfile) populate(cfg *Config) error {
}
}
if p.PrevAuthKeyName != "" {
log.Debug("match previous auth key in profile to auth_keys section")
if key, ok := cfg.AuthKeys[p.PrevAuthKeyName]; ok {
if key.Type == "standard" {
p.PrevProvider, err = auth.New(key.Key, nil)
if err != nil {
log.Debugf("failed to create new standard auth provider: %v", err)
return cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy,
errors.New("failed to create new standard auth provider"))
}
} else {
log.Debugf("unknown authentication type %v", key.Type)
return cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy,
errors.New("unknown authentication type"))
}
} else {
return cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy,
errors.New("failed to find prev_auth_key in auth_keys section"))
}
}
if p.AuthRemote.AuthKeyName != "" {
log.Debug("match auth remote key in profile to auth_keys section")
if key, ok := cfg.AuthKeys[p.AuthRemote.AuthKeyName]; ok == true {
@ -284,6 +330,40 @@ func (p *SigningProfile) populate(cfg *Config) error {
p.ExtensionWhitelist[asn1.ObjectIdentifier(oid).String()] = true
}
// By default perform any required preissuance linting with all ZLint lints.
p.LintRegistry = lint.GlobalRegistry()
// If ExcludeLintSources are present in config build a lint.SourceList while
// validating that no unknown sources were specified.
var excludedSources lint.SourceList
if len(p.ExcludeLintSources) > 0 {
for _, sourceName := range p.ExcludeLintSources {
var lintSource lint.LintSource
lintSource.FromString(sourceName)
if lintSource == lint.UnknownLintSource {
return cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy,
fmt.Errorf("failed to build excluded lint source list: unknown source %q",
sourceName))
}
excludedSources = append(excludedSources, lintSource)
}
}
opts := lint.FilterOptions{
ExcludeNames: p.ExcludeLints,
ExcludeSources: excludedSources,
}
if !opts.Empty() {
// If ExcludeLints or ExcludeLintSources were not empty then filter out the
// lints we don't want to use for preissuance linting with this profile.
filteredRegistry, err := p.LintRegistry.Filter(opts)
if err != nil {
return cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy,
fmt.Errorf("failed to build filtered lint registry: %v", err))
}
p.LintRegistry = filteredRegistry
}
return nil
}
@ -404,7 +484,8 @@ func (p *SigningProfile) Usages() (ku x509.KeyUsage, eku []x509.ExtKeyUsage, unk
// valid local default profile has defined at least a default expiration.
// A valid remote profile (default or not) has remote signer initialized.
// In addition, a remote profile must has a valid auth provider if auth
// key defined.
// key defined. A valid profile must not include a lint_error_level outside of
// [0,8).
func (p *SigningProfile) validProfile(isDefault bool) bool {
if p == nil {
return false
@ -461,6 +542,11 @@ func (p *SigningProfile) validProfile(isDefault bool) bool {
}
}
if p.LintErrLevel < 0 || p.LintErrLevel >= 8 {
log.Debugf("invalid profile: lint_error_level outside of range [0,8)")
return false
}
log.Debugf("profile is valid")
return true
}
@ -613,7 +699,7 @@ func LoadFile(path string) (*Config, error) {
return nil, cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy, errors.New("invalid path"))
}
body, err := ioutil.ReadFile(path)
body, err := os.ReadFile(path)
if err != nil {
return nil, cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy, errors.New("could not read configuration file"))
}

View file

@ -3,17 +3,17 @@
// to PKCS #7 format from another encoding such as PEM conforms to this implementation.
// reference: https://www.openssl.org/docs/man1.1.0/apps/crl2pkcs7.html
//
// PKCS #7 Data type, reference: https://tools.ietf.org/html/rfc2315
// PKCS #7 Data type, reference: https://tools.ietf.org/html/rfc2315
//
// The full pkcs#7 cryptographic message syntax allows for cryptographic enhancements,
// for example data can be encrypted and signed and then packaged through pkcs#7 to be
// sent over a network and then verified and decrypted. It is asn1, and the type of
// PKCS #7 ContentInfo, which comprises the PKCS #7 structure, is:
//
// ContentInfo ::= SEQUENCE {
// contentType ContentType,
// content [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL
// }
// ContentInfo ::= SEQUENCE {
// contentType ContentType,
// content [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL
// }
//
// There are 6 possible ContentTypes, data, signedData, envelopedData,
// signedAndEnvelopedData, digestedData, and encryptedData. Here signedData, Data, and encrypted
@ -22,15 +22,14 @@
// formats.
// The ContentType signedData has the form:
//
//
// signedData ::= SEQUENCE {
// version Version,
// digestAlgorithms DigestAlgorithmIdentifiers,
// contentInfo ContentInfo,
// certificates [0] IMPLICIT ExtendedCertificatesAndCertificates OPTIONAL
// crls [1] IMPLICIT CertificateRevocationLists OPTIONAL,
// signerInfos SignerInfos
// }
// signedData ::= SEQUENCE {
// version Version,
// digestAlgorithms DigestAlgorithmIdentifiers,
// contentInfo ContentInfo,
// certificates [0] IMPLICIT ExtendedCertificatesAndCertificates OPTIONAL
// crls [1] IMPLICIT CertificateRevocationLists OPTIONAL,
// signerInfos SignerInfos
// }
//
// As of yet signerInfos and digestAlgorithms are not parsed, as they are not relevant to
// this system's use of PKCS #7 data. Version is an integer type, note that PKCS #7 is

View file

@ -12,8 +12,11 @@ import (
"encoding/asn1"
"encoding/pem"
"errors"
"fmt"
"net"
"net/mail"
"net/url"
"strconv"
"strings"
cferr "github.com/cloudflare/cfssl/errors"
@ -29,46 +32,40 @@ const (
// A Name contains the SubjectInfo fields.
type Name struct {
C string // Country
ST string // State
L string // Locality
O string // OrganisationName
OU string // OrganisationalUnitName
SerialNumber string
C string `json:"C,omitempty" yaml:"C,omitempty"` // Country
ST string `json:"ST,omitempty" yaml:"ST,omitempty"` // State
L string `json:"L,omitempty" yaml:"L,omitempty"` // Locality
O string `json:"O,omitempty" yaml:"O,omitempty"` // OrganisationName
OU string `json:"OU,omitempty" yaml:"OU,omitempty"` // OrganisationalUnitName
E string `json:"E,omitempty" yaml:"E,omitempty"`
SerialNumber string `json:"SerialNumber,omitempty" yaml:"SerialNumber,omitempty"`
OID map[string]string `json:"OID,omitempty", yaml:"OID,omitempty"`
}
// A KeyRequest is a generic request for a new key.
type KeyRequest interface {
Algo() string
Size() int
Generate() (crypto.PrivateKey, error)
SigAlgo() x509.SignatureAlgorithm
}
// A BasicKeyRequest contains the algorithm and key size for a new private key.
type BasicKeyRequest struct {
// A KeyRequest contains the algorithm and key size for a new private key.
type KeyRequest struct {
A string `json:"algo" yaml:"algo"`
S int `json:"size" yaml:"size"`
}
// NewBasicKeyRequest returns a default BasicKeyRequest.
func NewBasicKeyRequest() *BasicKeyRequest {
return &BasicKeyRequest{"ecdsa", curveP256}
// NewKeyRequest returns a default KeyRequest.
func NewKeyRequest() *KeyRequest {
return &KeyRequest{"ecdsa", curveP256}
}
// Algo returns the requested key algorithm represented as a string.
func (kr *BasicKeyRequest) Algo() string {
func (kr *KeyRequest) Algo() string {
return kr.A
}
// Size returns the requested key size.
func (kr *BasicKeyRequest) Size() int {
func (kr *KeyRequest) Size() int {
return kr.S
}
// Generate generates a key as specified in the request. Currently,
// only ECDSA and RSA are supported.
func (kr *BasicKeyRequest) Generate() (crypto.PrivateKey, error) {
func (kr *KeyRequest) Generate() (crypto.PrivateKey, error) {
log.Debugf("generate key from request: algo=%s, size=%d", kr.Algo(), kr.Size())
switch kr.Algo() {
case "rsa":
@ -99,7 +96,7 @@ func (kr *BasicKeyRequest) Generate() (crypto.PrivateKey, error) {
// SigAlgo returns an appropriate X.509 signature algorithm given the
// key request's type and size.
func (kr *BasicKeyRequest) SigAlgo() x509.SignatureAlgorithm {
func (kr *KeyRequest) SigAlgo() x509.SignatureAlgorithm {
switch kr.Algo() {
case "rsa":
switch {
@ -139,19 +136,22 @@ type CAConfig struct {
// A CertificateRequest encapsulates the API interface to the
// certificate request functionality.
type CertificateRequest struct {
CN string
Names []Name `json:"names" yaml:"names"`
Hosts []string `json:"hosts" yaml:"hosts"`
KeyRequest KeyRequest `json:"key,omitempty" yaml:"key,omitempty"`
CA *CAConfig `json:"ca,omitempty" yaml:"ca,omitempty"`
SerialNumber string `json:"serialnumber,omitempty" yaml:"serialnumber,omitempty"`
CN string `json:"CN" yaml:"CN"`
Names []Name `json:"names" yaml:"names"`
Hosts []string `json:"hosts" yaml:"hosts"`
KeyRequest *KeyRequest `json:"key,omitempty" yaml:"key,omitempty"`
CA *CAConfig `json:"ca,omitempty" yaml:"ca,omitempty"`
SerialNumber string `json:"serialnumber,omitempty" yaml:"serialnumber,omitempty"`
DelegationEnabled bool `json:"delegation_enabled,omitempty" yaml:"delegation_enabled,omitempty"`
Extensions []pkix.Extension `json:"extensions,omitempty" yaml:"extensions,omitempty"`
CRL string `json:"crl_url,omitempty" yaml:"crl_url,omitempty"`
}
// New returns a new, empty CertificateRequest with a
// BasicKeyRequest.
// KeyRequest.
func New() *CertificateRequest {
return &CertificateRequest{
KeyRequest: NewBasicKeyRequest(),
KeyRequest: NewKeyRequest(),
}
}
@ -162,8 +162,25 @@ func appendIf(s string, a *[]string) {
}
}
// OIDFromString creates an ASN1 ObjectIdentifier from its string representation
func OIDFromString(s string) (asn1.ObjectIdentifier, error) {
var oid []int
parts := strings.Split(s, ".")
if len(parts) < 1 {
return oid, fmt.Errorf("invalid OID string: %s", s)
}
for _, p := range parts {
i, err := strconv.Atoi(p)
if err != nil {
return nil, fmt.Errorf("invalid OID part %s", p)
}
oid = append(oid, i)
}
return oid, nil
}
// Name returns the PKIX name for the request.
func (cr *CertificateRequest) Name() pkix.Name {
func (cr *CertificateRequest) Name() (pkix.Name, error) {
var name pkix.Name
name.CommonName = cr.CN
@ -173,9 +190,19 @@ func (cr *CertificateRequest) Name() pkix.Name {
appendIf(n.L, &name.Locality)
appendIf(n.O, &name.Organization)
appendIf(n.OU, &name.OrganizationalUnit)
for k, v := range n.OID {
oid, err := OIDFromString(k)
if err != nil {
return name, err
}
name.ExtraNames = append(name.ExtraNames, pkix.AttributeTypeAndValue{Type: oid, Value: v})
}
if n.E != "" {
name.ExtraNames = append(name.ExtraNames, pkix.AttributeTypeAndValue{Type: asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 1}, Value: n.E})
}
}
name.SerialNumber = cr.SerialNumber
return name
return name, nil
}
// BasicConstraints CSR information RFC 5280, 4.2.1.9
@ -193,7 +220,7 @@ type BasicConstraints struct {
func ParseRequest(req *CertificateRequest) (csr, key []byte, err error) {
log.Info("received CSR")
if req.KeyRequest == nil {
req.KeyRequest = NewBasicKeyRequest()
req.KeyRequest = NewKeyRequest()
}
log.Infof("generating key: %s-%d", req.KeyRequest.Algo(), req.KeyRequest.Size())
@ -268,14 +295,17 @@ func getHosts(cert *x509.Certificate) []string {
for _, email := range cert.EmailAddresses {
hosts = append(hosts, email)
}
for _, uri := range cert.URIs {
hosts = append(hosts, uri.String())
}
return hosts
}
// getNames returns an array of Names from the certificate
// It onnly cares about Country, Organization, OrganizationalUnit, Locality, Province
// It only cares about Country, Organization, OrganizationalUnit, Locality, Province
func getNames(sub pkix.Name) []Name {
// anonymous func for finding the max of a list of interger
// anonymous func for finding the max of a list of integer
max := func(v1 int, vn ...int) (max int) {
max = v1
for i := 0; i < len(vn); i++ {
@ -369,8 +399,13 @@ func Generate(priv crypto.Signer, req *CertificateRequest) (csr []byte, err erro
return nil, cferr.New(cferr.PrivateKeyError, cferr.Unavailable)
}
subj, err := req.Name()
if err != nil {
return nil, err
}
var tpl = x509.CertificateRequest{
Subject: req.Name(),
Subject: subj,
SignatureAlgorithm: sigAlgo,
}
@ -379,11 +414,15 @@ func Generate(priv crypto.Signer, req *CertificateRequest) (csr []byte, err erro
tpl.IPAddresses = append(tpl.IPAddresses, ip)
} else if email, err := mail.ParseAddress(req.Hosts[i]); err == nil && email != nil {
tpl.EmailAddresses = append(tpl.EmailAddresses, email.Address)
} else if uri, err := url.ParseRequestURI(req.Hosts[i]); err == nil && uri != nil {
tpl.URIs = append(tpl.URIs, uri)
} else {
tpl.DNSNames = append(tpl.DNSNames, req.Hosts[i])
}
}
tpl.ExtraExtensions = []pkix.Extension{}
if req.CA != nil {
err = appendCAInfoToCSR(req.CA, &tpl)
if err != nil {
@ -392,6 +431,18 @@ func Generate(priv crypto.Signer, req *CertificateRequest) (csr []byte, err erro
}
}
if req.DelegationEnabled {
tpl.ExtraExtensions = append(tpl.Extensions, helpers.DelegationExtension)
}
if req.Extensions != nil {
err = appendExtensionsToCSR(req.Extensions, &tpl)
if err != nil {
err = cferr.Wrap(cferr.CSRError, cferr.GenerationFailed, err)
return
}
}
csr, err = x509.CreateCertificateRequest(rand.Reader, &tpl, priv)
if err != nil {
log.Errorf("failed to generate a CSR: %v", err)
@ -420,13 +471,19 @@ func appendCAInfoToCSR(reqConf *CAConfig, csr *x509.CertificateRequest) error {
return err
}
csr.ExtraExtensions = []pkix.Extension{
{
Id: asn1.ObjectIdentifier{2, 5, 29, 19},
Value: val,
Critical: true,
},
}
csr.ExtraExtensions = append(csr.ExtraExtensions, pkix.Extension{
Id: asn1.ObjectIdentifier{2, 5, 29, 19},
Value: val,
Critical: true,
})
return nil
}
// appendCAInfoToCSR appends user-defined extension to a CSR
func appendExtensionsToCSR(extensions []pkix.Extension, csr *x509.CertificateRequest) error {
for _, extension := range extensions {
csr.ExtraExtensions = append(csr.ExtraExtensions, extension)
}
return nil
}

View file

@ -7,6 +7,7 @@ It formats to a json object that consists of an error message and a 4-digit code
Example: {"code":1002, "message": "Failed to decode certificate"}
The index of codes are listed below:
1XXX: CertificateError
1000: Unknown
1001: ReadFailed

View file

@ -5,14 +5,15 @@ package derhelpers
import (
"crypto"
"crypto/ecdsa"
"crypto/ed25519"
"crypto/rsa"
"crypto/x509"
cferr "github.com/cloudflare/cfssl/errors"
)
// ParsePrivateKeyDER parses a PKCS #1, PKCS #8, or elliptic curve
// DER-encoded private key. The key must not be in PEM format.
// ParsePrivateKeyDER parses a PKCS #1, PKCS #8, ECDSA, or Ed25519 DER-encoded
// private key. The key must not be in PEM format.
func ParsePrivateKeyDER(keyDER []byte) (key crypto.Signer, err error) {
generalKey, err := x509.ParsePKCS8PrivateKey(keyDER)
if err != nil {
@ -20,12 +21,15 @@ func ParsePrivateKeyDER(keyDER []byte) (key crypto.Signer, err error) {
if err != nil {
generalKey, err = x509.ParseECPrivateKey(keyDER)
if err != nil {
// We don't include the actual error into
// the final error. The reason might be
// we don't want to leak any info about
// the private key.
return nil, cferr.New(cferr.PrivateKeyError,
cferr.ParseFailed)
generalKey, err = ParseEd25519PrivateKey(keyDER)
if err != nil {
// We don't include the actual error into
// the final error. The reason might be
// we don't want to leak any info about
// the private key.
return nil, cferr.New(cferr.PrivateKeyError,
cferr.ParseFailed)
}
}
}
}
@ -35,6 +39,8 @@ func ParsePrivateKeyDER(keyDER []byte) (key crypto.Signer, err error) {
return generalKey.(*rsa.PrivateKey), nil
case *ecdsa.PrivateKey:
return generalKey.(*ecdsa.PrivateKey), nil
case ed25519.PrivateKey:
return generalKey.(ed25519.PrivateKey), nil
}
// should never reach here

View file

@ -0,0 +1,132 @@
package derhelpers
import (
"crypto"
"crypto/ed25519"
"crypto/x509/pkix"
"encoding/asn1"
"errors"
)
var errEd25519WrongID = errors.New("incorrect object identifier")
var errEd25519WrongKeyType = errors.New("incorrect key type")
// ed25519OID is the OID for the Ed25519 signature scheme: see
// https://datatracker.ietf.org/doc/draft-ietf-curdle-pkix-04.
var ed25519OID = asn1.ObjectIdentifier{1, 3, 101, 112}
// subjectPublicKeyInfo reflects the ASN.1 object defined in the X.509 standard.
//
// This is defined in crypto/x509 as "publicKeyInfo".
type subjectPublicKeyInfo struct {
Algorithm pkix.AlgorithmIdentifier
PublicKey asn1.BitString
}
// MarshalEd25519PublicKey creates a DER-encoded SubjectPublicKeyInfo for an
// ed25519 public key, as defined in
// https://tools.ietf.org/html/draft-ietf-curdle-pkix-04. This is analogous to
// MarshalPKIXPublicKey in crypto/x509, which doesn't currently support Ed25519.
func MarshalEd25519PublicKey(pk crypto.PublicKey) ([]byte, error) {
pub, ok := pk.(ed25519.PublicKey)
if !ok {
return nil, errEd25519WrongKeyType
}
spki := subjectPublicKeyInfo{
Algorithm: pkix.AlgorithmIdentifier{
Algorithm: ed25519OID,
},
PublicKey: asn1.BitString{
BitLength: len(pub) * 8,
Bytes: pub,
},
}
return asn1.Marshal(spki)
}
// ParseEd25519PublicKey returns the Ed25519 public key encoded by the input.
func ParseEd25519PublicKey(der []byte) (crypto.PublicKey, error) {
var spki subjectPublicKeyInfo
if rest, err := asn1.Unmarshal(der, &spki); err != nil {
return nil, err
} else if len(rest) > 0 {
return nil, errors.New("SubjectPublicKeyInfo too long")
}
if !spki.Algorithm.Algorithm.Equal(ed25519OID) {
return nil, errEd25519WrongID
}
if spki.PublicKey.BitLength != ed25519.PublicKeySize*8 {
return nil, errors.New("SubjectPublicKeyInfo PublicKey length mismatch")
}
return ed25519.PublicKey(spki.PublicKey.Bytes), nil
}
// oneAsymmetricKey reflects the ASN.1 structure for storing private keys in
// https://tools.ietf.org/html/draft-ietf-curdle-pkix-04, excluding the optional
// fields, which we don't use here.
//
// This is identical to pkcs8 in crypto/x509.
type oneAsymmetricKey struct {
Version int
Algorithm pkix.AlgorithmIdentifier
PrivateKey []byte
}
// curvePrivateKey is the innter type of the PrivateKey field of
// oneAsymmetricKey.
type curvePrivateKey []byte
// MarshalEd25519PrivateKey returns a DER encoding of the input private key as
// specified in https://tools.ietf.org/html/draft-ietf-curdle-pkix-04.
func MarshalEd25519PrivateKey(sk crypto.PrivateKey) ([]byte, error) {
priv, ok := sk.(ed25519.PrivateKey)
if !ok {
return nil, errEd25519WrongKeyType
}
// Marshal the innter CurvePrivateKey.
curvePrivateKey, err := asn1.Marshal(priv.Seed())
if err != nil {
return nil, err
}
// Marshal the OneAsymmetricKey.
asym := oneAsymmetricKey{
Version: 0,
Algorithm: pkix.AlgorithmIdentifier{
Algorithm: ed25519OID,
},
PrivateKey: curvePrivateKey,
}
return asn1.Marshal(asym)
}
// ParseEd25519PrivateKey returns the Ed25519 private key encoded by the input.
func ParseEd25519PrivateKey(der []byte) (crypto.PrivateKey, error) {
asym := new(oneAsymmetricKey)
if rest, err := asn1.Unmarshal(der, asym); err != nil {
return nil, err
} else if len(rest) > 0 {
return nil, errors.New("OneAsymmetricKey too long")
}
// Check that the key type is correct.
if !asym.Algorithm.Algorithm.Equal(ed25519OID) {
return nil, errEd25519WrongID
}
// Unmarshal the inner CurvePrivateKey.
seed := new(curvePrivateKey)
if rest, err := asn1.Unmarshal(asym.PrivateKey, seed); err != nil {
return nil, err
} else if len(rest) > 0 {
return nil, errors.New("CurvePrivateKey too long")
}
return ed25519.NewKeyFromSeed(*seed), nil
}

View file

@ -15,14 +15,7 @@ import (
"encoding/pem"
"errors"
"fmt"
"io/ioutil"
"os"
"github.com/google/certificate-transparency-go"
cttls "github.com/google/certificate-transparency-go/tls"
ctx509 "github.com/google/certificate-transparency-go/x509"
"golang.org/x/crypto/ocsp"
"strings"
"time"
@ -30,6 +23,11 @@ import (
cferr "github.com/cloudflare/cfssl/errors"
"github.com/cloudflare/cfssl/helpers/derhelpers"
"github.com/cloudflare/cfssl/log"
ct "github.com/google/certificate-transparency-go"
cttls "github.com/google/certificate-transparency-go/tls"
ctx509 "github.com/google/certificate-transparency-go/x509"
"golang.org/x/crypto/ocsp"
"golang.org/x/crypto/pkcs12"
)
@ -39,6 +37,16 @@ const OneYear = 8760 * time.Hour
// OneDay is a time.Duration representing a day's worth of seconds.
const OneDay = 24 * time.Hour
// DelegationUsage is the OID for the DelegationUseage extensions
var DelegationUsage = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 44363, 44}
// DelegationExtension
var DelegationExtension = pkix.Extension{
Id: DelegationUsage,
Critical: false,
Value: []byte{0x05, 0x00}, // ASN.1 NULL
}
// InclusiveDate returns the time.Time representation of a date - 1
// nanosecond. This allows time.After to be used inclusively.
func InclusiveDate(year int, month time.Month, day int) time.Time {
@ -184,6 +192,19 @@ func HashAlgoString(alg x509.SignatureAlgorithm) string {
}
}
// StringTLSVersion returns underlying enum values from human names for TLS
// versions, defaults to current golang default of TLS 1.0
func StringTLSVersion(version string) uint16 {
switch version {
case "1.2":
return tls.VersionTLS12
case "1.1":
return tls.VersionTLS11
default:
return tls.VersionTLS10
}
}
// EncodeCertificatesPEM encodes a number of x509 certificates to PEM
func EncodeCertificatesPEM(certs []*x509.Certificate) []byte {
var buffer bytes.Buffer
@ -322,7 +343,7 @@ func LoadPEMCertPool(certsFile string) (*x509.CertPool, error) {
if certsFile == "" {
return nil, nil
}
pemCerts, err := ioutil.ReadFile(certsFile)
pemCerts, err := os.ReadFile(certsFile)
if err != nil {
return nil, err
}
@ -365,7 +386,15 @@ func ParsePrivateKeyPEMWithPassword(keyPEM []byte, password []byte) (key crypto.
// GetKeyDERFromPEM parses a PEM-encoded private key and returns DER-format key bytes.
func GetKeyDERFromPEM(in []byte, password []byte) ([]byte, error) {
keyDER, _ := pem.Decode(in)
// Ignore any EC PARAMETERS blocks when looking for a key (openssl includes
// them by default).
var keyDER *pem.Block
for {
keyDER, in = pem.Decode(in)
if keyDER == nil || keyDER.Type != "EC PARAMETERS" {
break
}
}
if keyDER != nil {
if procType, ok := keyDER.Headers["Proc-Type"]; ok {
if strings.Contains(procType, "ENCRYPTED") {
@ -460,7 +489,7 @@ func LoadClientCertificate(certFile string, keyFile string) (*tls.Certificate, e
if certFile != "" && keyFile != "" {
cert, err := tls.LoadX509KeyPair(certFile, keyFile)
if err != nil {
log.Critical("Unable to read client certificate from file: %s or key from file: %s", certFile, keyFile)
log.Criticalf("Unable to read client certificate from file: %s or key from file: %s", certFile, keyFile)
return nil, err
}
log.Debug("Client certificate loaded ")
@ -560,13 +589,13 @@ func SCTListFromOCSPResponse(response *ocsp.Response) ([]ct.SignedCertificateTim
func ReadBytes(valFile string) ([]byte, error) {
switch splitVal := strings.SplitN(valFile, ":", 2); len(splitVal) {
case 1:
return ioutil.ReadFile(valFile)
return os.ReadFile(valFile)
case 2:
switch splitVal[0] {
case "env":
return []byte(os.Getenv(splitVal[1])), nil
case "file":
return ioutil.ReadFile(splitVal[1])
return os.ReadFile(splitVal[1])
default:
return nil, fmt.Errorf("unknown prefix: %s", splitVal[0])
}

View file

@ -69,6 +69,10 @@ func New(req *csr.CertificateRequest) (cert, csrPEM, key []byte, err error) {
}
}
if req.CRL != "" {
policy.Default.CRL = req.CRL
}
g := &csr.Generator{Validator: validator}
csrPEM, key, err = g.ProcessRequest(req)
if err != nil {

View file

@ -3,20 +3,27 @@ package local
import (
"bytes"
"context"
"crypto"
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"crypto/x509"
"crypto/x509/pkix"
"database/sql"
"encoding/asn1"
"encoding/hex"
"encoding/pem"
"errors"
"fmt"
"io"
"math/big"
"net"
"net/http"
"net/mail"
"net/url"
"os"
"time"
"github.com/cloudflare/cfssl/certdb"
"github.com/cloudflare/cfssl/config"
@ -25,17 +32,23 @@ import (
"github.com/cloudflare/cfssl/info"
"github.com/cloudflare/cfssl/log"
"github.com/cloudflare/cfssl/signer"
"github.com/google/certificate-transparency-go"
ct "github.com/google/certificate-transparency-go"
"github.com/google/certificate-transparency-go/client"
"github.com/google/certificate-transparency-go/jsonclient"
"golang.org/x/net/context"
zx509 "github.com/zmap/zcrypto/x509"
"github.com/zmap/zlint/v3"
"github.com/zmap/zlint/v3/lint"
)
// Signer contains a signer that uses the standard library to
// support both ECDSA and RSA CA keys.
type Signer struct {
ca *x509.Certificate
priv crypto.Signer
ca *x509.Certificate
priv crypto.Signer
// lintPriv is generated randomly when pre-issuance linting is configured and
// used to sign TBSCertificates for linting.
lintPriv crypto.Signer
policy *config.Signing
sigAlgo x509.SignatureAlgorithm
dbAccessor certdb.Accessor
@ -54,11 +67,30 @@ func NewSigner(priv crypto.Signer, cert *x509.Certificate, sigAlgo x509.Signatur
return nil, cferr.New(cferr.PolicyError, cferr.InvalidPolicy)
}
var lintPriv crypto.Signer
// If there is at least one profile (including the default) that configures
// pre-issuance linting then generate the one-off lintPriv key.
for _, profile := range policy.Profiles {
if profile.LintErrLevel > 0 || policy.Default.LintErrLevel > 0 {
// In the future there may be demand for specifying the type of signer used
// for pre-issuance linting in configuration. For now we assume that signing
// with a randomly generated P-256 ECDSA private key is acceptable for all cases
// where linting is requested.
k, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
if err != nil {
return nil, cferr.New(cferr.PrivateKeyError, cferr.GenerationFailed)
}
lintPriv = k
break
}
}
return &Signer{
ca: cert,
priv: priv,
sigAlgo: sigAlgo,
policy: policy,
ca: cert,
priv: priv,
lintPriv: lintPriv,
sigAlgo: sigAlgo,
policy: policy,
}, nil
}
@ -89,14 +121,75 @@ func NewSignerFromFile(caFile, caKeyFile string, policy *config.Signing) (*Signe
priv, err := helpers.ParsePrivateKeyPEMWithPassword(cakey, password)
if err != nil {
log.Debug("Malformed private key %v", err)
log.Debugf("Malformed private key %v", err)
return nil, err
}
return NewSigner(priv, parsedCa, signer.DefaultSigAlgo(priv), policy)
}
func (s *Signer) sign(template *x509.Certificate) (cert []byte, err error) {
// LintError is an error type returned when pre-issuance linting is configured
// in a signing profile and a TBS Certificate fails linting. It wraps the
// concrete zlint LintResults so that callers can further inspect the cause of
// the failing lints.
type LintError struct {
ErrorResults map[string]lint.LintResult
}
func (e *LintError) Error() string {
return fmt.Sprintf("pre-issuance linting found %d error results",
len(e.ErrorResults))
}
// lint performs pre-issuance linting of a given TBS certificate template when
// the provided errLevel is > 0. Note that the template is provided by-value and
// not by-reference. This is important as the lint function needs to mutate the
// template's signature algorithm to match the lintPriv.
func (s *Signer) lint(template x509.Certificate, errLevel lint.LintStatus, lintRegistry lint.Registry) error {
// Always return nil when linting is disabled (lint.Reserved == 0).
if errLevel == lint.Reserved {
return nil
}
// without a lintPriv key to use to sign the tbsCertificate we can't lint it.
if s.lintPriv == nil {
return cferr.New(cferr.PrivateKeyError, cferr.Unavailable)
}
// The template's SignatureAlgorithm must be mutated to match the lintPriv or
// x509.CreateCertificate will error because of the mismatch. At the time of
// writing s.lintPriv is always an ECDSA private key. This switch will need to
// be expanded if the lint key type is made configurable.
switch s.lintPriv.(type) {
case *ecdsa.PrivateKey:
template.SignatureAlgorithm = x509.ECDSAWithSHA256
default:
return cferr.New(cferr.PrivateKeyError, cferr.KeyMismatch)
}
prelintBytes, err := x509.CreateCertificate(rand.Reader, &template, s.ca, template.PublicKey, s.lintPriv)
if err != nil {
return cferr.Wrap(cferr.CertificateError, cferr.Unknown, err)
}
prelintCert, err := zx509.ParseCertificate(prelintBytes)
if err != nil {
return cferr.Wrap(cferr.CertificateError, cferr.ParseFailed, err)
}
errorResults := map[string]lint.LintResult{}
results := zlint.LintCertificateEx(prelintCert, lintRegistry)
for name, res := range results.Results {
if res.Status > errLevel {
errorResults[name] = *res
}
}
if len(errorResults) > 0 {
return &LintError{
ErrorResults: errorResults,
}
}
return nil
}
func (s *Signer) sign(template *x509.Certificate, lintErrLevel lint.LintStatus, lintRegistry lint.Registry) (cert []byte, err error) {
var initRoot bool
if s.ca == nil {
if !template.IsCA {
@ -105,10 +198,15 @@ func (s *Signer) sign(template *x509.Certificate) (cert []byte, err error) {
}
template.DNSNames = nil
template.EmailAddresses = nil
template.URIs = nil
s.ca = template
initRoot = true
}
if err := s.lint(*template, lintErrLevel, lintRegistry); err != nil {
return nil, err
}
derBytes, err := x509.CreateCertificate(rand.Reader, template, s.ca, template.PublicKey, s.priv)
if err != nil {
return nil, cferr.Wrap(cferr.CertificateError, cferr.Unknown, err)
@ -159,13 +257,14 @@ func PopulateSubjectFromCSR(s *signer.Subject, req pkix.Name) pkix.Name {
return name
}
// OverrideHosts fills template's IPAddresses, EmailAddresses, and DNSNames with the
// OverrideHosts fills template's IPAddresses, EmailAddresses, DNSNames, and URIs with the
// content of hosts, if it is not nil.
func OverrideHosts(template *x509.Certificate, hosts []string) {
if hosts != nil {
template.IPAddresses = []net.IP{}
template.EmailAddresses = []string{}
template.DNSNames = []string{}
template.URIs = []*url.URL{}
}
for i := range hosts {
@ -173,6 +272,8 @@ func OverrideHosts(template *x509.Certificate, hosts []string) {
template.IPAddresses = append(template.IPAddresses, ip)
} else if email, err := mail.ParseAddress(hosts[i]); err == nil && email != nil {
template.EmailAddresses = append(template.EmailAddresses, email.Address)
} else if uri, err := url.ParseRequestURI(hosts[i]); err == nil && uri != nil {
template.URIs = append(template.URIs, uri)
} else {
template.DNSNames = append(template.DNSNames, hosts[i])
}
@ -199,7 +300,7 @@ func (s *Signer) Sign(req signer.SignRequest) (cert []byte, err error) {
cferr.BadRequest, errors.New("not a csr"))
}
csrTemplate, err := signer.ParseCertificateRequest(s, block.Bytes)
csrTemplate, err := signer.ParseCertificateRequest(s, profile, block.Bytes)
if err != nil {
return nil, err
}
@ -232,6 +333,9 @@ func (s *Signer) Sign(req signer.SignRequest) (cert []byte, err error) {
if profile.CSRWhitelist.EmailAddresses {
safeTemplate.EmailAddresses = csrTemplate.EmailAddresses
}
if profile.CSRWhitelist.URIs {
safeTemplate.URIs = csrTemplate.URIs
}
}
if req.CRLOverride != "" {
@ -277,6 +381,11 @@ func (s *Signer) Sign(req signer.SignRequest) (cert []byte, err error) {
return nil, cferr.New(cferr.PolicyError, cferr.UnmatchedWhitelist)
}
}
for _, name := range safeTemplate.URIs {
if profile.NameWhitelist.Find([]byte(name.String())) == nil {
return nil, cferr.New(cferr.PolicyError, cferr.UnmatchedWhitelist)
}
}
}
if profile.ClientProvidesSerialNumbers {
@ -342,7 +451,7 @@ func (s *Signer) Sign(req signer.SignRequest) (cert []byte, err error) {
var poisonExtension = pkix.Extension{Id: signer.CTPoisonOID, Critical: true, Value: []byte{0x05, 0x00}}
var poisonedPreCert = certTBS
poisonedPreCert.ExtraExtensions = append(safeTemplate.ExtraExtensions, poisonExtension)
cert, err = s.sign(&poisonedPreCert)
cert, err = s.sign(&poisonedPreCert, profile.LintErrLevel, profile.LintRegistry)
if err != nil {
return
}
@ -385,8 +494,9 @@ func (s *Signer) Sign(req signer.SignRequest) (cert []byte, err error) {
var SCTListExtension = pkix.Extension{Id: signer.SCTListOID, Critical: false, Value: serializedSCTList}
certTBS.ExtraExtensions = append(certTBS.ExtraExtensions, SCTListExtension)
}
var signedCert []byte
signedCert, err = s.sign(&certTBS)
signedCert, err = s.sign(&certTBS, profile.LintErrLevel, profile.LintRegistry)
if err != nil {
return nil, err
}
@ -397,19 +507,29 @@ func (s *Signer) Sign(req signer.SignRequest) (cert []byte, err error) {
parsedCert, _ := helpers.ParseCertificatePEM(signedCert)
if s.dbAccessor != nil {
now := time.Now()
var certRecord = certdb.CertificateRecord{
Serial: certTBS.SerialNumber.String(),
// this relies on the specific behavior of x509.CreateCertificate
// which sets the AuthorityKeyId from the signer's SubjectKeyId
AKI: hex.EncodeToString(parsedCert.AuthorityKeyId),
CALabel: req.Label,
Status: "good",
Expiry: certTBS.NotAfter,
PEM: string(signedCert),
AKI: hex.EncodeToString(parsedCert.AuthorityKeyId),
CALabel: req.Label,
Status: "good",
Expiry: certTBS.NotAfter,
PEM: string(signedCert),
IssuedAt: &now,
NotBefore: &certTBS.NotBefore,
CommonName: sql.NullString{String: certTBS.Subject.CommonName, Valid: true},
}
err = s.dbAccessor.InsertCertificate(certRecord)
if err != nil {
if err := certRecord.SetMetadata(req.Metadata); err != nil {
return nil, err
}
if err := certRecord.SetSANs(certTBS.DNSNames); err != nil {
return nil, err
}
if err := s.dbAccessor.InsertCertificate(certRecord); err != nil {
return nil, err
}
log.Debug("saved certificate with serial number ", certTBS.SerialNumber)
@ -424,7 +544,9 @@ func (s *Signer) Sign(req signer.SignRequest) (cert []byte, err error) {
// except for the removal of the poison extension and the addition of the SCT list
// extension. SignFromPrecert does not verify that the contents of the certificate
// still match the signing profile of the signer, it only requires that the precert
// was previously signed by the Signers CA.
// was previously signed by the Signers CA. Similarly, any linting configured
// by the profile used to sign the precert will not be re-applied to the final
// cert and must be done separately by the caller.
func (s *Signer) SignFromPrecert(precert *x509.Certificate, scts []ct.SignedCertificateTimestamp) ([]byte, error) {
// Verify certificate was signed by s.ca
if err := precert.CheckSignatureFrom(s.ca); err != nil {
@ -467,17 +589,17 @@ func (s *Signer) SignFromPrecert(precert *x509.Certificate, scts []ct.SignedCert
// Create the new tbsCert from precert. Do explicit copies of any slices so that we don't
// use memory that may be altered by us or the caller at a later stage.
tbsCert := x509.Certificate{
SignatureAlgorithm: precert.SignatureAlgorithm,
PublicKeyAlgorithm: precert.PublicKeyAlgorithm,
PublicKey: precert.PublicKey,
Version: precert.Version,
SerialNumber: precert.SerialNumber,
Issuer: precert.Issuer,
Subject: precert.Subject,
NotBefore: precert.NotBefore,
NotAfter: precert.NotAfter,
KeyUsage: precert.KeyUsage,
BasicConstraintsValid: precert.BasicConstraintsValid,
SignatureAlgorithm: precert.SignatureAlgorithm,
PublicKeyAlgorithm: precert.PublicKeyAlgorithm,
PublicKey: precert.PublicKey,
Version: precert.Version,
SerialNumber: precert.SerialNumber,
Issuer: precert.Issuer,
Subject: precert.Subject,
NotBefore: precert.NotBefore,
NotAfter: precert.NotAfter,
KeyUsage: precert.KeyUsage,
BasicConstraintsValid: precert.BasicConstraintsValid,
IsCA: precert.IsCA,
MaxPathLen: precert.MaxPathLen,
MaxPathLenZero: precert.MaxPathLenZero,
@ -493,8 +615,10 @@ func (s *Signer) SignFromPrecert(precert *x509.Certificate, scts []ct.SignedCert
// Insert the SCT list extension
tbsCert.ExtraExtensions = append(tbsCert.ExtraExtensions, sctExt)
// Sign the tbsCert
return s.sign(&tbsCert)
// Sign the tbsCert. Linting is always disabled because there is no way for
// this API to know the correct lint settings to use because there is no
// reference to the signing profile of the precert available.
return s.sign(&tbsCert, 0, nil)
}
// Info return a populated info.Resp struct or an error.

View file

@ -20,6 +20,7 @@ import (
"github.com/cloudflare/cfssl/config"
"github.com/cloudflare/cfssl/csr"
cferr "github.com/cloudflare/cfssl/errors"
"github.com/cloudflare/cfssl/helpers"
"github.com/cloudflare/cfssl/info"
)
@ -45,7 +46,7 @@ type Extension struct {
// Extensions provided in the signRequest are copied into the certificate, as
// long as they are in the ExtensionWhitelist for the signer's policy.
// Extensions requested in the CSR are ignored, except for those processed by
// ParseCertificateRequest (mainly subjectAltName).
// ParseCertificateRequest (mainly subjectAltName) and DelegationUsage.
type SignRequest struct {
Hosts []string `json:"hosts"`
Request string `json:"certificate_request"`
@ -70,6 +71,9 @@ type SignRequest struct {
// be passed to SignFromPrecert with the SCTs in order to create a
// valid certificate.
ReturnPrecert bool
// Arbitrary metadata to be stored in certdb.
Metadata map[string]interface{} `json:"metadata"`
}
// appendIf appends to a if s is not an empty string.
@ -169,15 +173,38 @@ func DefaultSigAlgo(priv crypto.Signer) x509.SignatureAlgorithm {
}
}
func isCommonAttr(t []int) bool {
return (len(t) == 4 && t[0] == 2 && t[1] == 5 && t[2] == 4 && (t[3] == 3 || (t[3] >= 5 && t[3] <= 11) || t[3] == 17))
}
// ParseCertificateRequest takes an incoming certificate request and
// builds a certificate template from it.
func ParseCertificateRequest(s Signer, csrBytes []byte) (template *x509.Certificate, err error) {
func ParseCertificateRequest(s Signer, p *config.SigningProfile, csrBytes []byte) (template *x509.Certificate, err error) {
csrv, err := x509.ParseCertificateRequest(csrBytes)
if err != nil {
err = cferr.Wrap(cferr.CSRError, cferr.ParseFailed, err)
return
}
var r pkix.RDNSequence
_, err = asn1.Unmarshal(csrv.RawSubject, &r)
if err != nil {
err = cferr.Wrap(cferr.CSRError, cferr.ParseFailed, err)
return
}
var subject pkix.Name
subject.FillFromRDNSequence(&r)
for _, v := range r {
for _, vv := range v {
if !isCommonAttr(vv.Type) {
subject.ExtraNames = append(subject.ExtraNames, vv)
}
}
}
err = csrv.CheckSignature()
if err != nil {
err = cferr.Wrap(cferr.CSRError, cferr.KeyMismatch, err)
@ -185,13 +212,16 @@ func ParseCertificateRequest(s Signer, csrBytes []byte) (template *x509.Certific
}
template = &x509.Certificate{
Subject: csrv.Subject,
Subject: subject,
PublicKeyAlgorithm: csrv.PublicKeyAlgorithm,
PublicKey: csrv.PublicKey,
SignatureAlgorithm: s.SigAlgo(),
DNSNames: csrv.DNSNames,
IPAddresses: csrv.IPAddresses,
EmailAddresses: csrv.EmailAddresses,
URIs: csrv.URIs,
Extensions: csrv.Extensions,
ExtraExtensions: []pkix.Extension{},
}
for _, val := range csrv.Extensions {
@ -211,6 +241,13 @@ func ParseCertificateRequest(s Signer, csrBytes []byte) (template *x509.Certific
template.IsCA = constraints.IsCA
template.MaxPathLen = constraints.MaxPathLen
template.MaxPathLenZero = template.MaxPathLen == 0
} else if val.Id.Equal(helpers.DelegationUsage) {
template.ExtraExtensions = append(template.ExtraExtensions, val)
} else {
// If the profile has 'copy_extensions' to true then lets add it
if p.CopyExtensions {
template.ExtraExtensions = append(template.ExtraExtensions, val)
}
}
}
@ -320,6 +357,7 @@ func FillTemplate(template *x509.Certificate, defaultProfile, profile *config.Si
}
template.DNSNames = nil
template.EmailAddresses = nil
template.URIs = nil
}
template.SubjectKeyId = ski

23
vendor/github.com/jmoiron/sqlx/LICENSE generated vendored Normal file
View file

@ -0,0 +1,23 @@
Copyright (c) 2013, Jason Moiron
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.

5
vendor/github.com/jmoiron/sqlx/types/README.md generated vendored Normal file
View file

@ -0,0 +1,5 @@
# types
The types package provides some useful types which implement the `sql.Scanner`
and `driver.Valuer` interfaces, suitable for use as scan and value targets with
database/sql.

172
vendor/github.com/jmoiron/sqlx/types/types.go generated vendored Normal file
View file

@ -0,0 +1,172 @@
package types
import (
"bytes"
"compress/gzip"
"database/sql/driver"
"encoding/json"
"errors"
"io/ioutil"
)
// GzippedText is a []byte which transparently gzips data being submitted to
// a database and ungzips data being Scanned from a database.
type GzippedText []byte
// Value implements the driver.Valuer interface, gzipping the raw value of
// this GzippedText.
func (g GzippedText) Value() (driver.Value, error) {
b := make([]byte, 0, len(g))
buf := bytes.NewBuffer(b)
w := gzip.NewWriter(buf)
w.Write(g)
w.Close()
return buf.Bytes(), nil
}
// Scan implements the sql.Scanner interface, ungzipping the value coming off
// the wire and storing the raw result in the GzippedText.
func (g *GzippedText) Scan(src interface{}) error {
var source []byte
switch src := src.(type) {
case string:
source = []byte(src)
case []byte:
source = src
default:
return errors.New("Incompatible type for GzippedText")
}
reader, err := gzip.NewReader(bytes.NewReader(source))
if err != nil {
return err
}
defer reader.Close()
b, err := ioutil.ReadAll(reader)
if err != nil {
return err
}
*g = GzippedText(b)
return nil
}
// JSONText is a json.RawMessage, which is a []byte underneath.
// Value() validates the json format in the source, and returns an error if
// the json is not valid. Scan does no validation. JSONText additionally
// implements `Unmarshal`, which unmarshals the json within to an interface{}
type JSONText json.RawMessage
var emptyJSON = JSONText("{}")
// MarshalJSON returns the *j as the JSON encoding of j.
func (j JSONText) MarshalJSON() ([]byte, error) {
if len(j) == 0 {
return emptyJSON, nil
}
return j, nil
}
// UnmarshalJSON sets *j to a copy of data
func (j *JSONText) UnmarshalJSON(data []byte) error {
if j == nil {
return errors.New("JSONText: UnmarshalJSON on nil pointer")
}
*j = append((*j)[0:0], data...)
return nil
}
// Value returns j as a value. This does a validating unmarshal into another
// RawMessage. If j is invalid json, it returns an error.
func (j JSONText) Value() (driver.Value, error) {
var m json.RawMessage
var err = j.Unmarshal(&m)
if err != nil {
return []byte{}, err
}
return []byte(j), nil
}
// Scan stores the src in *j. No validation is done.
func (j *JSONText) Scan(src interface{}) error {
var source []byte
switch t := src.(type) {
case string:
source = []byte(t)
case []byte:
if len(t) == 0 {
source = emptyJSON
} else {
source = t
}
case nil:
*j = emptyJSON
default:
return errors.New("Incompatible type for JSONText")
}
*j = append((*j)[0:0], source...)
return nil
}
// Unmarshal unmarshal's the json in j to v, as in json.Unmarshal.
func (j *JSONText) Unmarshal(v interface{}) error {
if len(*j) == 0 {
*j = emptyJSON
}
return json.Unmarshal([]byte(*j), v)
}
// String supports pretty printing for JSONText types.
func (j JSONText) String() string {
return string(j)
}
// NullJSONText represents a JSONText that may be null.
// NullJSONText implements the scanner interface so
// it can be used as a scan destination, similar to NullString.
type NullJSONText struct {
JSONText
Valid bool // Valid is true if JSONText is not NULL
}
// Scan implements the Scanner interface.
func (n *NullJSONText) Scan(value interface{}) error {
if value == nil {
n.JSONText, n.Valid = emptyJSON, false
return nil
}
n.Valid = true
return n.JSONText.Scan(value)
}
// Value implements the driver Valuer interface.
func (n NullJSONText) Value() (driver.Value, error) {
if !n.Valid {
return nil, nil
}
return n.JSONText.Value()
}
// BitBool is an implementation of a bool for the MySQL type BIT(1).
// This type allows you to avoid wasting an entire byte for MySQL's boolean type TINYINT.
type BitBool bool
// Value implements the driver.Valuer interface,
// and turns the BitBool into a bitfield (BIT(1)) for MySQL storage.
func (b BitBool) Value() (driver.Value, error) {
if b {
return []byte{1}, nil
}
return []byte{0}, nil
}
// Scan implements the sql.Scanner interface,
// and turns the bitfield incoming from MySQL into a BitBool
func (b *BitBool) Scan(src interface{}) error {
v, ok := src.([]byte)
if !ok {
return errors.New("bad []byte type assertion")
}
*b = v[0] == 1
return nil
}

View file

@ -6,8 +6,6 @@ import (
"sync"
"time"
"github.com/sirupsen/logrus"
"github.com/docker/docker/pkg/plugingetter"
"github.com/moby/swarmkit/v2/agent/csi/plugin"
@ -65,7 +63,7 @@ func (r *volumes) retryVolumes() {
for {
vid, attempt := r.pendingVolumes.Wait()
dctx := log.WithFields(ctx, logrus.Fields{
dctx := log.WithFields(ctx, log.Fields{
"volume.id": vid,
"attempt": fmt.Sprintf("%d", attempt),
})

View file

@ -10,7 +10,6 @@ import (
"github.com/moby/swarmkit/v2/log"
"github.com/moby/swarmkit/v2/protobuf/ptypes"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
)
// Controller controls execution of a task.
@ -348,11 +347,10 @@ func Do(ctx context.Context, task *api.Task, ctlr Controller) (*api.TaskStatus,
func logStateChange(ctx context.Context, desired, previous, next api.TaskState) {
if previous != next {
fields := logrus.Fields{
log.G(ctx).WithFields(log.Fields{
"state.transition": fmt.Sprintf("%v->%v", previous, next),
"state.desired": desired,
}
log.G(ctx).WithFields(fields).Debug("state changed")
}).Debug("state changed")
}
}

View file

@ -10,7 +10,6 @@ import (
"github.com/moby/swarmkit/v2/api"
"github.com/moby/swarmkit/v2/connectionbroker"
"github.com/moby/swarmkit/v2/log"
"github.com/sirupsen/logrus"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
@ -180,7 +179,7 @@ func (s *session) heartbeat(ctx context.Context) error {
heartbeat := time.NewTimer(1) // send out a heartbeat right away
defer heartbeat.Stop()
fields := logrus.Fields{
fields := log.Fields{
"sessionID": s.sessionID,
"method": "(*session).heartbeat",
}
@ -243,8 +242,8 @@ func (s *session) handleSessionMessage(ctx context.Context, msg *api.SessionMess
}
func (s *session) logSubscriptions(ctx context.Context) error {
log := log.G(ctx).WithFields(logrus.Fields{"method": "(*session).logSubscriptions"})
log.Debugf("")
logger := log.G(ctx).WithFields(log.Fields{"method": "(*session).logSubscriptions"})
logger.Debugf("")
client := api.NewLogBrokerClient(s.conn.ClientConn)
subscriptions, err := client.ListenSubscriptions(ctx, &api.ListenSubscriptionsRequest{})
@ -257,7 +256,7 @@ func (s *session) logSubscriptions(ctx context.Context) error {
resp, err := subscriptions.Recv()
st, _ := status.FromError(err)
if st.Code() == codes.Unimplemented {
log.Warning("manager does not support log subscriptions")
logger.Warning("manager does not support log subscriptions")
// Don't return, because returning would bounce the session
select {
case <-s.closed:
@ -281,8 +280,8 @@ func (s *session) logSubscriptions(ctx context.Context) error {
}
func (s *session) watch(ctx context.Context) error {
log := log.G(ctx).WithFields(logrus.Fields{"method": "(*session).watch"})
log.Debugf("")
logger := log.G(ctx).WithFields(log.Fields{"method": "(*session).watch"})
logger.Debugf("")
var (
resp *api.AssignmentsMessage
assignmentWatch api.Dispatcher_AssignmentsClient
@ -313,7 +312,7 @@ func (s *session) watch(ctx context.Context) error {
}
tasksFallback = true
assignmentWatch = nil
log.WithError(err).Infof("falling back to Tasks")
logger.WithError(err).Infof("falling back to Tasks")
}
}

View file

@ -8,7 +8,6 @@ import (
"github.com/moby/swarmkit/v2/api"
"github.com/moby/swarmkit/v2/log"
"github.com/moby/swarmkit/v2/watch"
"github.com/sirupsen/logrus"
bolt "go.etcd.io/bbolt"
)
@ -135,7 +134,7 @@ func (w *worker) Assign(ctx context.Context, assignments []*api.AssignmentChange
return ErrClosed
}
log.G(ctx).WithFields(logrus.Fields{
log.G(ctx).WithFields(log.Fields{
"len(assignments)": len(assignments),
}).Debug("(*worker).Assign")
@ -174,7 +173,7 @@ func (w *worker) Update(ctx context.Context, assignments []*api.AssignmentChange
return ErrClosed
}
log.G(ctx).WithFields(logrus.Fields{
log.G(ctx).WithFields(log.Fields{
"len(assignments)": len(assignments),
}).Debug("(*worker).Update")
@ -212,7 +211,7 @@ func reconcileTaskState(ctx context.Context, w *worker, assignments []*api.Assig
}
}
log.G(ctx).WithFields(logrus.Fields{
log.G(ctx).WithFields(log.Fields{
"len(updatedTasks)": len(updatedTasks),
"len(removedTasks)": len(removedTasks),
}).Debug("(*worker).reconcileTaskState")
@ -227,10 +226,10 @@ func reconcileTaskState(ctx context.Context, w *worker, assignments []*api.Assig
assigned := map[string]struct{}{}
for _, task := range updatedTasks {
log.G(ctx).WithFields(
logrus.Fields{
"task.id": task.ID,
"task.desiredstate": task.DesiredState}).Debug("assigned")
log.G(ctx).WithFields(log.Fields{
"task.id": task.ID,
"task.desiredstate": task.DesiredState,
}).Debug("assigned")
if err := PutTask(tx, task); err != nil {
return err
}
@ -359,7 +358,7 @@ func reconcileSecrets(ctx context.Context, w *worker, assignments []*api.Assignm
secrets := secretsProvider.Secrets()
log.G(ctx).WithFields(logrus.Fields{
log.G(ctx).WithFields(log.Fields{
"len(updatedSecrets)": len(updatedSecrets),
"len(removedSecrets)": len(removedSecrets),
}).Debug("(*worker).reconcileSecrets")
@ -402,7 +401,7 @@ func reconcileConfigs(ctx context.Context, w *worker, assignments []*api.Assignm
configs := configsProvider.Configs()
log.G(ctx).WithFields(logrus.Fields{
log.G(ctx).WithFields(log.Fields{
"len(updatedConfigs)": len(updatedConfigs),
"len(removedConfigs)": len(removedConfigs),
}).Debug("(*worker).reconcileConfigs")
@ -448,7 +447,7 @@ func reconcileVolumes(ctx context.Context, w *worker, assignments []*api.Assignm
volumes := volumesProvider.Volumes()
log.G(ctx).WithFields(logrus.Fields{
log.G(ctx).WithFields(log.Fields{
"len(updatedVolumes)": len(updatedVolumes),
"len(removedVolumes)": len(removedVolumes),
}).Debug("(*worker).reconcileVolumes")
@ -536,7 +535,7 @@ func (w *worker) taskManager(ctx context.Context, tx *bolt.Tx, task *api.Task) (
}
func (w *worker) newTaskManager(ctx context.Context, tx *bolt.Tx, task *api.Task) (*taskManager, error) {
ctx = log.WithLogger(ctx, log.G(ctx).WithFields(logrus.Fields{
ctx = log.WithLogger(ctx, log.G(ctx).WithFields(log.Fields{
"task.id": task.ID,
"service.id": task.ServiceID,
}))

View file

@ -6,8 +6,6 @@ import (
"crypto/x509/pkix"
"strings"
"github.com/sirupsen/logrus"
"github.com/moby/swarmkit/v2/api"
"github.com/moby/swarmkit/v2/log"
"google.golang.org/grpc/codes"
@ -43,7 +41,7 @@ func LogTLSState(ctx context.Context, tlsState *tls.ConnectionState) {
verifiedChain = append(verifiedChain, strings.Join(subjects, ","))
}
log.G(ctx).WithFields(logrus.Fields{
log.G(ctx).WithFields(log.Fields{
"peer.peerCert": peerCerts,
// "peer.verifiedChain": verifiedChain},
}).Debugf("")

View file

@ -769,7 +769,7 @@ func CreateRootCA(rootCN string) (RootCA, error) {
// Create a simple CSR for the CA using the default CA validator and policy
req := cfcsr.CertificateRequest{
CN: rootCN,
KeyRequest: &cfcsr.BasicKeyRequest{A: RootKeyAlgo, S: RootKeySize},
KeyRequest: &cfcsr.KeyRequest{A: RootKeyAlgo, S: RootKeySize},
CA: &cfcsr.CAConfig{Expiry: RootCAExpiration},
}
@ -919,7 +919,7 @@ func SaveRootCA(rootCA RootCA, paths CertPaths) error {
// GenerateNewCSR returns a newly generated key and CSR signed with said key
func GenerateNewCSR() ([]byte, []byte, error) {
req := &cfcsr.CertificateRequest{
KeyRequest: cfcsr.NewBasicKeyRequest(),
KeyRequest: cfcsr.NewKeyRequest(),
}
csr, key, err := cfcsr.ParseRequest(req)

View file

@ -22,7 +22,6 @@ import (
"github.com/moby/swarmkit/v2/watch"
"github.com/opencontainers/go-digest"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"google.golang.org/grpc/credentials"
)
@ -463,7 +462,7 @@ func LoadSecurityConfig(ctx context.Context, rootCA RootCA, krw *KeyReadWriter,
PublicKey: issuer.RawSubjectPublicKeyInfo,
})
if err == nil {
log.G(ctx).WithFields(logrus.Fields{
log.G(ctx).WithFields(log.Fields{
"node.id": secConfig.ClientTLSCreds.NodeID(),
"node.role": secConfig.ClientTLSCreds.Role(),
}).Debug("loaded node credentials")
@ -524,12 +523,12 @@ func (rootCA RootCA) CreateSecurityConfig(ctx context.Context, krw *KeyReadWrite
return nil, nil, err
}
case nil:
log.G(ctx).WithFields(logrus.Fields{
log.G(ctx).WithFields(log.Fields{
"node.id": cn,
"node.role": proposedRole,
}).Debug("issued new TLS certificate")
default:
log.G(ctx).WithFields(logrus.Fields{
log.G(ctx).WithFields(log.Fields{
"node.id": cn,
"node.role": proposedRole,
}).WithError(err).Errorf("failed to issue and save new certificate")
@ -538,7 +537,7 @@ func (rootCA RootCA) CreateSecurityConfig(ctx context.Context, krw *KeyReadWrite
secConfig, cleanup, err := NewSecurityConfig(&rootCA, krw, tlsKeyPair, issuerInfo)
if err == nil {
log.G(ctx).WithFields(logrus.Fields{
log.G(ctx).WithFields(log.Fields{
"node.id": secConfig.ClientTLSCreds.NodeID(),
"node.role": secConfig.ClientTLSCreds.Role(),
}).Debugf("new node credentials generated: %s", krw.Target())
@ -579,7 +578,7 @@ func RenewTLSConfigNow(ctx context.Context, s *SecurityConfig, connBroker *conne
defer s.renewalMu.Unlock()
ctx = log.WithModule(ctx, "tls")
log := log.G(ctx).WithFields(logrus.Fields{
logger := log.G(ctx).WithFields(log.Fields{
"node.id": s.ClientTLSCreds.NodeID(),
"node.role": s.ClientTLSCreds.Role(),
})
@ -602,7 +601,7 @@ func RenewTLSConfigNow(ctx context.Context, s *SecurityConfig, connBroker *conne
}
}
if err != nil {
log.WithError(err).Errorf("failed to renew the certificate")
logger.WithError(err).Errorf("failed to renew the certificate")
return err
}

View file

@ -20,7 +20,6 @@ import (
"github.com/cloudflare/cfssl/signer"
"github.com/moby/swarmkit/v2/log"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"golang.org/x/net/context/ctxhttp"
)
@ -203,7 +202,7 @@ func makeExternalSignRequest(ctx context.Context, client *http.Client, url strin
var apiResponse api.Response
if err := json.Unmarshal(body, &apiResponse); err != nil {
logrus.Debugf("unable to JSON-parse CFSSL API response body: %s", string(body))
log.G(ctx).Debugf("unable to JSON-parse CFSSL API response body: %s", string(body))
return nil, recoverableErr{err: errors.Wrap(err, "unable to parse JSON response")}
}

View file

@ -9,7 +9,6 @@ import (
"github.com/moby/swarmkit/v2/connectionbroker"
"github.com/moby/swarmkit/v2/log"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
)
// RenewTLSExponentialBackoff sets the exponential backoff when trying to renew TLS certificates that have expired
@ -72,7 +71,7 @@ func (t *TLSRenewer) Start(ctx context.Context) <-chan CertificateUpdate {
defer close(updates)
for {
ctx = log.WithModule(ctx, "tls")
log := log.G(ctx).WithFields(logrus.Fields{
logger := log.G(ctx).WithFields(log.Fields{
"node.id": t.s.ClientTLSCreds.NodeID(),
"node.role": t.s.ClientTLSCreds.Role(),
})
@ -85,19 +84,19 @@ func (t *TLSRenewer) Start(ctx context.Context) <-chan CertificateUpdate {
validFrom, validUntil, err := readCertValidity(t.s.KeyReader())
if err != nil {
// We failed to read the expiration, let's stick with the starting default
log.Errorf("failed to read the expiration of the TLS certificate in: %s", t.s.KeyReader().Target())
logger.Errorf("failed to read the expiration of the TLS certificate in: %s", t.s.KeyReader().Target())
select {
case updates <- CertificateUpdate{Err: errors.New("failed to read certificate expiration")}:
case <-ctx.Done():
log.Info("shutting down certificate renewal routine")
logger.Info("shutting down certificate renewal routine")
return
}
} else {
// If we have an expired certificate, try to renew immediately: the hope that this is a temporary clock skew, or
// we can issue our own TLS certs.
if validUntil.Before(time.Now()) {
log.Warn("the current TLS certificate is expired, so an attempt to renew it will be made immediately")
logger.Warn("the current TLS certificate is expired, so an attempt to renew it will be made immediately")
// retry immediately(ish) with exponential backoff
retry = expBackoff.Proceed(nil)
} else if forceRetry {
@ -110,16 +109,16 @@ func (t *TLSRenewer) Start(ctx context.Context) <-chan CertificateUpdate {
}
}
log.WithFields(logrus.Fields{
logger.WithFields(log.Fields{
"time": time.Now().Add(retry),
}).Debugf("next certificate renewal scheduled for %v from now", retry)
select {
case <-time.After(retry):
log.Info("renewing certificate")
logger.Info("renewing certificate")
case <-t.renew:
forceRetry = true
log.Info("forced certificate renewal")
logger.Info("forced certificate renewal")
// Pause briefly before attempting the renewal,
// to give the CA a chance to reconcile the
@ -127,11 +126,11 @@ func (t *TLSRenewer) Start(ctx context.Context) <-chan CertificateUpdate {
select {
case <-time.After(500 * time.Millisecond):
case <-ctx.Done():
log.Info("shutting down certificate renewal routine")
logger.Info("shutting down certificate renewal routine")
return
}
case <-ctx.Done():
log.Info("shutting down certificate renewal routine")
logger.Info("shutting down certificate renewal routine")
return
}
@ -158,7 +157,7 @@ func (t *TLSRenewer) Start(ctx context.Context) <-chan CertificateUpdate {
select {
case updates <- certUpdate:
case <-ctx.Done():
log.Info("shutting down certificate renewal routine")
logger.Info("shutting down certificate renewal routine")
return
}
}

View file

@ -15,7 +15,6 @@ import (
"github.com/moby/swarmkit/v2/log"
"github.com/moby/swarmkit/v2/manager/state/store"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
@ -182,7 +181,7 @@ func (s *Server) NodeCertificateStatus(ctx context.Context, request *api.NodeCer
return nil, status.Errorf(codes.NotFound, codes.NotFound.String())
}
log.G(ctx).WithFields(logrus.Fields{
log.G(ctx).WithFields(log.Fields{
"node.id": node.ID,
"status": node.Certificate.Status,
"method": "NodeCertificateStatus",
@ -196,7 +195,7 @@ func (s *Server) NodeCertificateStatus(ctx context.Context, request *api.NodeCer
}, nil
}
log.G(ctx).WithFields(logrus.Fields{
log.G(ctx).WithFields(log.Fields{
"node.id": node.ID,
"status": node.Certificate.Status,
"method": "NodeCertificateStatus",
@ -326,7 +325,7 @@ func (s *Server) IssueNodeCertificate(ctx context.Context, request *api.IssueNod
return store.CreateNode(tx, node)
})
if err == nil {
log.G(ctx).WithFields(logrus.Fields{
log.G(ctx).WithFields(log.Fields{
"node.id": nodeID,
"node.role": role,
"method": "IssueNodeCertificate",
@ -339,7 +338,7 @@ func (s *Server) IssueNodeCertificate(ctx context.Context, request *api.IssueNod
if i == maxRetries {
return nil, err
}
log.G(ctx).WithFields(logrus.Fields{
log.G(ctx).WithFields(log.Fields{
"node.id": nodeID,
"node.role": role,
"method": "IssueNodeCertificate",
@ -363,7 +362,7 @@ func (s *Server) issueRenewCertificate(ctx context.Context, nodeID string, csr [
// Attempt to retrieve the node with nodeID
node = store.GetNode(tx, nodeID)
if node == nil {
log.G(ctx).WithFields(logrus.Fields{
log.G(ctx).WithFields(log.Fields{
"node.id": nodeID,
"method": "issueRenewCertificate",
}).Warnf("node does not exist")
@ -388,7 +387,7 @@ func (s *Server) issueRenewCertificate(ctx context.Context, nodeID string, csr [
return nil, err
}
log.G(ctx).WithFields(logrus.Fields{
log.G(ctx).WithFields(log.Fields{
"cert.cn": cert.CN,
"cert.role": cert.Role,
"method": "issueRenewCertificate",
@ -404,7 +403,7 @@ func (s *Server) issueRenewCertificate(ctx context.Context, nodeID string, csr [
// the root of trust for the swarm. Clients should be using the CA hash to verify if they weren't target to
// a MiTM. If they fail to do so, node bootstrap works with TOFU semantics.
func (s *Server) GetRootCACertificate(ctx context.Context, request *api.GetRootCACertificateRequest) (*api.GetRootCACertificateResponse, error) {
log.G(ctx).WithFields(logrus.Fields{
log.G(ctx).WithFields(log.Fields{
"method": "GetRootCACertificate",
})
@ -477,7 +476,7 @@ func (s *Server) Run(ctx context.Context) error {
s.mu.Unlock()
if err != nil {
log.G(ctx).WithFields(logrus.Fields{
log.G(ctx).WithFields(log.Fields{
"method": "(*Server).Run",
}).WithError(err).Errorf("snapshot store view failed")
return err
@ -489,7 +488,7 @@ func (s *Server) Run(ctx context.Context) error {
if err := s.reconcileNodeCertificates(ctx, nodes); err != nil {
// We don't return here because that means the Run loop would
// never run. Log an error instead.
log.G(ctx).WithFields(logrus.Fields{
log.G(ctx).WithFields(log.Fields{
"method": "(*Server).Run",
}).WithError(err).Errorf("error attempting to reconcile certificates")
}
@ -668,7 +667,7 @@ func (s *Server) UpdateRootCA(ctx context.Context, cluster *api.Cluster, reconci
firstSeenCluster := s.lastSeenClusterRootCA == nil && s.lastSeenExternalCAs == nil
rootCAChanged := len(rCA.CACert) != 0 && !equality.RootCAEqualStable(s.lastSeenClusterRootCA, rCA)
externalCAChanged := !equality.ExternalCAsEqualStable(s.lastSeenExternalCAs, cluster.Spec.CAConfig.ExternalCAs)
ctx = log.WithLogger(ctx, log.G(ctx).WithFields(logrus.Fields{
ctx = log.WithLogger(ctx, log.G(ctx).WithFields(log.Fields{
"cluster.id": cluster.ID,
"method": "(*Server).UpdateRootCA",
}))
@ -773,7 +772,7 @@ func (s *Server) signNodeCert(ctx context.Context, node *api.Node) error {
// Convert the role from proto format
role, err := ParseRole(node.Certificate.Role)
if err != nil {
log.G(ctx).WithFields(logrus.Fields{
log.G(ctx).WithFields(log.Fields{
"node.id": node.ID,
"method": "(*Server).signNodeCert",
}).WithError(err).Errorf("failed to parse role")
@ -798,7 +797,7 @@ func (s *Server) signNodeCert(ctx context.Context, node *api.Node) error {
}
if err != nil {
log.G(ctx).WithFields(logrus.Fields{
log.G(ctx).WithFields(log.Fields{
"node.id": node.ID,
"method": "(*Server).signNodeCert",
}).WithError(err).Errorf("failed to sign CSR")
@ -830,7 +829,7 @@ func (s *Server) signNodeCert(ctx context.Context, node *api.Node) error {
return store.UpdateNode(tx, node)
})
if err != nil {
log.G(ctx).WithFields(logrus.Fields{
log.G(ctx).WithFields(log.Fields{
"node.id": nodeID,
"method": "(*Server).signNodeCert",
}).WithError(err).Errorf("transaction failed when setting state to FAILED")
@ -858,7 +857,7 @@ func (s *Server) signNodeCert(ctx context.Context, node *api.Node) error {
return err
})
if err == nil {
log.G(ctx).WithFields(logrus.Fields{
log.G(ctx).WithFields(log.Fields{
"node.id": node.ID,
"node.role": node.Certificate.Role,
"method": "(*Server).signNodeCert",
@ -870,7 +869,7 @@ func (s *Server) signNodeCert(ctx context.Context, node *api.Node) error {
continue
}
log.G(ctx).WithFields(logrus.Fields{
log.G(ctx).WithFields(log.Fields{
"node.id": nodeID,
"method": "(*Server).signNodeCert",
}).WithError(err).Errorf("transaction failed")

View file

@ -23,6 +23,9 @@ type (
moduleKey struct{}
)
// Fields type to pass to "WithFields".
type Fields = map[string]any
// WithLogger returns a new context with the provided logger. Use in
// combination with logger.WithField(s) for great effect.
func WithLogger(ctx context.Context, logger *logrus.Entry) context.Context {
@ -30,7 +33,7 @@ func WithLogger(ctx context.Context, logger *logrus.Entry) context.Context {
}
// WithFields returns a new context with added fields to logger.
func WithFields(ctx context.Context, fields logrus.Fields) context.Context {
func WithFields(ctx context.Context, fields Fields) context.Context {
logger := ctx.Value(loggerKey{})
if logger == nil {
@ -41,7 +44,7 @@ func WithFields(ctx context.Context, fields logrus.Fields) context.Context {
// WithField is convenience wrapper around WithFields.
func WithField(ctx context.Context, key, value string) context.Context {
return WithFields(ctx, logrus.Fields{key: value})
return WithFields(ctx, Fields{key: value})
}
// GetLogger retrieves the current logger from the context. If no logger is

View file

@ -1,6 +1,7 @@
package cnmallocator
import (
"context"
"strconv"
"strings"
@ -8,7 +9,7 @@ import (
builtinIpam "github.com/docker/docker/libnetwork/ipams/builtin"
nullIpam "github.com/docker/docker/libnetwork/ipams/null"
"github.com/docker/docker/libnetwork/ipamutils"
"github.com/sirupsen/logrus"
"github.com/moby/swarmkit/v2/log"
)
func initIPAMDrivers(r ipamapi.Registerer, netConfig *NetworkConfig) error {
@ -35,7 +36,7 @@ func initIPAMDrivers(r ipamapi.Registerer, netConfig *NetworkConfig) error {
return err
}
if addressPool != nil {
logrus.Infof("Swarm initialized global default address pool to: " + str.String())
log.G(context.TODO()).Infof("Swarm initialized global default address pool to: " + str.String())
}
for _, fn := range [](func(ipamapi.Registerer) error){

View file

@ -18,7 +18,6 @@ import (
"github.com/moby/swarmkit/v2/log"
"github.com/moby/swarmkit/v2/manager/allocator/networkallocator"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
)
const (
@ -261,7 +260,7 @@ vipLoop:
}
for _, nAttach := range specNetworks {
if nAttach.Target == eAttach.NetworkID {
log.L.WithFields(logrus.Fields{"service_id": s.ID, "vip": eAttach.Addr}).Debug("allocate vip")
log.L.WithFields(log.Fields{"service_id": s.ID, "vip": eAttach.Addr}).Debug("allocate vip")
if err = na.allocateVIP(eAttach); err != nil {
return err
}

View file

@ -9,7 +9,6 @@ import (
"github.com/moby/swarmkit/v2/identity"
"github.com/moby/swarmkit/v2/log"
"github.com/moby/swarmkit/v2/manager/state/store"
"github.com/sirupsen/logrus"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
@ -80,7 +79,7 @@ func (s *Server) UpdateConfig(ctx context.Context, request *api.UpdateConfigRequ
return nil, err
}
log.G(ctx).WithFields(logrus.Fields{
log.G(ctx).WithFields(log.Fields{
"config.ID": request.ConfigID,
"config.Name": request.Spec.Annotations.Name,
"method": "UpdateConfig",
@ -166,7 +165,7 @@ func (s *Server) CreateConfig(ctx context.Context, request *api.CreateConfigRequ
case store.ErrNameConflict:
return nil, status.Errorf(codes.AlreadyExists, "config %s already exists", request.Spec.Annotations.Name)
case nil:
log.G(ctx).WithFields(logrus.Fields{
log.G(ctx).WithFields(log.Fields{
"config.Name": request.Spec.Annotations.Name,
"method": "CreateConfig",
}).Debugf("config created")
@ -222,7 +221,7 @@ func (s *Server) RemoveConfig(ctx context.Context, request *api.RemoveConfigRequ
case store.ErrNotExist:
return nil, status.Errorf(codes.NotFound, "config %s not found", request.ConfigID)
case nil:
log.G(ctx).WithFields(logrus.Fields{
log.G(ctx).WithFields(log.Fields{
"config.ID": request.ConfigID,
"method": "RemoveConfig",
}).Debugf("config removed")

View file

@ -8,7 +8,6 @@ import (
"github.com/moby/swarmkit/v2/identity"
"github.com/moby/swarmkit/v2/log"
"github.com/moby/swarmkit/v2/manager/state/store"
"github.com/sirupsen/logrus"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
@ -37,7 +36,7 @@ func (s *Server) CreateExtension(ctx context.Context, request *api.CreateExtensi
case store.ErrNameConflict:
return nil, status.Errorf(codes.AlreadyExists, "extension %s already exists", request.Annotations.Name)
case nil:
log.G(ctx).WithFields(logrus.Fields{
log.G(ctx).WithFields(log.Fields{
"extension.Name": request.Annotations.Name,
"method": "CreateExtension",
}).Debugf("extension created")
@ -121,7 +120,7 @@ func (s *Server) RemoveExtension(ctx context.Context, request *api.RemoveExtensi
case store.ErrNotExist:
return nil, status.Errorf(codes.NotFound, "extension %s not found", request.ExtensionID)
case nil:
log.G(ctx).WithFields(logrus.Fields{
log.G(ctx).WithFields(log.Fields{
"extension.ID": request.ExtensionID,
"method": "RemoveExtension",
}).Debugf("extension removed")

View file

@ -3,7 +3,6 @@ package controlapi
import (
"context"
"github.com/sirupsen/logrus"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
@ -50,7 +49,7 @@ func (s *Server) CreateResource(ctx context.Context, request *api.CreateResource
r.Annotations.Name,
)
case nil:
log.G(ctx).WithFields(logrus.Fields{
log.G(ctx).WithFields(log.Fields{
"resource.Name": r.Annotations.Name,
"method": "CreateResource",
}).Debugf("resource created")

View file

@ -10,7 +10,6 @@ import (
"github.com/moby/swarmkit/v2/identity"
"github.com/moby/swarmkit/v2/log"
"github.com/moby/swarmkit/v2/manager/state/store"
"github.com/sirupsen/logrus"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
@ -78,7 +77,7 @@ func (s *Server) UpdateSecret(ctx context.Context, request *api.UpdateSecretRequ
return nil, err
}
log.G(ctx).WithFields(logrus.Fields{
log.G(ctx).WithFields(log.Fields{
"secret.ID": request.SecretID,
"secret.Name": request.Spec.Annotations.Name,
"method": "UpdateSecret",
@ -174,7 +173,7 @@ func (s *Server) CreateSecret(ctx context.Context, request *api.CreateSecretRequ
return nil, status.Errorf(codes.AlreadyExists, "secret %s already exists", request.Spec.Annotations.Name)
case nil:
secret.Spec.Data = nil // clean the actual secret data so it's never returned
log.G(ctx).WithFields(logrus.Fields{
log.G(ctx).WithFields(log.Fields{
"secret.Name": request.Spec.Annotations.Name,
"method": "CreateSecret",
}).Debugf("secret created")
@ -230,7 +229,7 @@ func (s *Server) RemoveSecret(ctx context.Context, request *api.RemoveSecretRequ
case store.ErrNotExist:
return nil, status.Errorf(codes.NotFound, "secret %s not found", request.SecretID)
case nil:
log.G(ctx).WithFields(logrus.Fields{
log.G(ctx).WithFields(log.Fields{
"secret.ID": request.SecretID,
"method": "RemoveSecret",
}).Debugf("secret removed")

View file

@ -7,10 +7,8 @@ import (
"sync"
"time"
"github.com/docker/go-events"
"github.com/sirupsen/logrus"
"github.com/docker/docker/pkg/plugingetter"
"github.com/docker/go-events"
"github.com/moby/swarmkit/v2/api"
"github.com/moby/swarmkit/v2/log"
@ -154,7 +152,7 @@ func (vm *Manager) run(pctx context.Context) {
// processVolumes encapuslates the logic for processing pending Volumes.
func (vm *Manager) processVolume(ctx context.Context, id string, attempt uint) {
// set up log fields for a derrived context to pass to handleVolume.
logCtx := log.WithFields(ctx, logrus.Fields{
logCtx := log.WithFields(ctx, log.Fields{
"volume.id": id,
"attempt": attempt,
})

View file

@ -7,6 +7,7 @@ import (
"github.com/moby/swarmkit/v2/api/equality"
"github.com/moby/swarmkit/v2/api/validation"
"github.com/moby/swarmkit/v2/identity"
"github.com/moby/swarmkit/v2/log"
"github.com/moby/swarmkit/v2/manager/drivers"
"github.com/moby/swarmkit/v2/manager/state/store"
"github.com/sirupsen/logrus"
@ -53,7 +54,7 @@ func assignSecret(a *assignmentSet, readTx store.ReadTx, mapKey typeAndID, t *ap
}
secret, doNotReuse, err := a.secret(readTx, t, mapKey.id)
if err != nil {
a.log.WithFields(logrus.Fields{
a.log.WithFields(log.Fields{
"resource.type": "secret",
"secret.id": mapKey.id,
"error": err,
@ -89,7 +90,7 @@ func assignConfig(a *assignmentSet, readTx store.ReadTx, mapKey typeAndID) {
a.tasksUsingDependency[mapKey] = make(map[string]struct{})
config := store.GetConfig(readTx, mapKey.id)
if config == nil {
a.log.WithFields(logrus.Fields{
a.log.WithFields(log.Fields{
"resource.type": "config",
"config.id": mapKey.id,
}).Debug("config not found")

View file

@ -21,7 +21,6 @@ import (
"github.com/moby/swarmkit/v2/remotes"
"github.com/moby/swarmkit/v2/watch"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
@ -619,7 +618,7 @@ func (d *Dispatcher) UpdateTaskStatus(ctx context.Context, r *api.UpdateTaskStat
return nil, err
}
nodeID := nodeInfo.NodeID
fields := logrus.Fields{
fields := log.Fields{
"node.id": nodeID,
"node.session": r.SessionID,
"method": "(*Dispatcher).UpdateTaskStatus",
@ -695,7 +694,7 @@ func (d *Dispatcher) UpdateVolumeStatus(ctx context.Context, r *api.UpdateVolume
}
nodeID := nodeInfo.NodeID
fields := logrus.Fields{
fields := log.Fields{
"node.id": nodeID,
"node.session": r.SessionID,
"method": "(*Dispatcher).UpdateVolumeStatus",
@ -703,19 +702,19 @@ func (d *Dispatcher) UpdateVolumeStatus(ctx context.Context, r *api.UpdateVolume
if nodeInfo.ForwardedBy != nil {
fields["forwarder.id"] = nodeInfo.ForwardedBy.NodeID
}
log := log.G(ctx).WithFields(fields)
logger := log.G(ctx).WithFields(fields)
if _, err := d.nodes.GetWithSession(nodeID, r.SessionID); err != nil {
return nil, err
}
d.unpublishedVolumesLock.Lock()
for _, status := range r.Updates {
if status.Unpublished {
for _, volumeStatus := range r.Updates {
if volumeStatus.Unpublished {
// it's ok if nodes is nil, because append works on a nil slice.
nodes := append(d.unpublishedVolumes[status.ID], nodeID)
d.unpublishedVolumes[status.ID] = nodes
log.Debugf("volume %s unpublished on node %s", status.ID, nodeID)
nodes := append(d.unpublishedVolumes[volumeStatus.ID], nodeID)
d.unpublishedVolumes[volumeStatus.ID] = nodes
logger.Debugf("volume %s unpublished on node %s", volumeStatus.ID, nodeID)
}
}
d.unpublishedVolumesLock.Unlock()
@ -756,14 +755,14 @@ func (d *Dispatcher) processUpdates(ctx context.Context) {
return
}
log := log.G(ctx).WithFields(logrus.Fields{
logr := log.G(ctx).WithFields(log.Fields{
"method": "(*Dispatcher).processUpdates",
})
err := d.store.Batch(func(batch *store.Batch) error {
for taskID, status := range taskUpdates {
for taskID, taskStatus := range taskUpdates {
err := batch.Update(func(tx store.Tx) error {
logger := log.WithField("task.id", taskID)
logger := logr.WithField("task.id", taskID)
task := store.GetTask(tx, taskID)
if task == nil {
// Task may have been deleted
@ -771,14 +770,14 @@ func (d *Dispatcher) processUpdates(ctx context.Context) {
return nil
}
logger = logger.WithField("state.transition", fmt.Sprintf("%v->%v", task.Status.State, status.State))
logger = logger.WithField("state.transition", fmt.Sprintf("%v->%v", task.Status.State, taskStatus.State))
if task.Status == *status {
if task.Status == *taskStatus {
logger.Debug("task status identical, ignoring")
return nil
}
if task.Status.State > status.State {
if task.Status.State > taskStatus.State {
logger.Debug("task status invalid transition")
return nil
}
@ -789,12 +788,12 @@ func (d *Dispatcher) processUpdates(ctx context.Context) {
// the network delay between the worker and the leader.
// This is not ideal, but its a known overestimation, rather than using the status update time
// from the worker node, which may cause unknown incorrect results due to possible clock skew.
if status.State == api.TaskStateRunning {
start := time.Unix(status.AppliedAt.GetSeconds(), int64(status.AppliedAt.GetNanos()))
if taskStatus.State == api.TaskStateRunning {
start := time.Unix(taskStatus.AppliedAt.GetSeconds(), int64(taskStatus.AppliedAt.GetNanos()))
schedulingDelayTimer.UpdateSince(start)
}
task.Status = *status
task.Status = *taskStatus
task.Status.AppliedBy = d.securityConfig.ClientTLSCreds.NodeID()
task.Status.AppliedAt = ptypes.MustTimestampProto(time.Now())
logger.Debugf("state for task %v updated to %v", task.GetID(), task.Status.State)
@ -806,13 +805,13 @@ func (d *Dispatcher) processUpdates(ctx context.Context) {
return nil
})
if err != nil {
log.WithError(err).Error("dispatcher task update transaction failed")
logr.WithError(err).Error("dispatcher task update transaction failed")
}
}
for nodeID, nodeUpdate := range nodeUpdates {
err := batch.Update(func(tx store.Tx) error {
logger := log.WithField("node.id", nodeID)
logger := logr.WithField("node.id", nodeID)
node := store.GetNode(tx, nodeID)
if node == nil {
logger.Error("node unavailable")
@ -838,13 +837,13 @@ func (d *Dispatcher) processUpdates(ctx context.Context) {
return nil
})
if err != nil {
log.WithError(err).Error("dispatcher node update transaction failed")
logr.WithError(err).Error("dispatcher node update transaction failed")
}
}
for volumeID, nodes := range unpublishedVolumes {
err := batch.Update(func(tx store.Tx) error {
logger := log.WithField("volume.id", volumeID)
logger := logr.WithField("volume.id", volumeID)
volume := store.GetVolume(tx, volumeID)
if volume == nil {
logger.Error("volume unavailable")
@ -869,14 +868,14 @@ func (d *Dispatcher) processUpdates(ctx context.Context) {
})
if err != nil {
log.WithError(err).Error("dispatcher volume update transaction failed")
logr.WithError(err).Error("dispatcher volume update transaction failed")
}
}
return nil
})
if err != nil {
log.WithError(err).Error("dispatcher batch failed")
logr.WithError(err).Error("dispatcher batch failed")
}
d.processUpdatesCond.Broadcast()
@ -900,7 +899,7 @@ func (d *Dispatcher) Tasks(r *api.TasksRequest, stream api.Dispatcher_TasksServe
}
nodeID := nodeInfo.NodeID
fields := logrus.Fields{
fields := log.Fields{
"node.id": nodeID,
"node.session": r.SessionID,
"method": "(*Dispatcher).Tasks",
@ -1026,7 +1025,7 @@ func (d *Dispatcher) Assignments(r *api.AssignmentsRequest, stream api.Dispatche
}
nodeID := nodeInfo.NodeID
fields := logrus.Fields{
fields := log.Fields{
"node.id": nodeID,
"node.session": r.SessionID,
"method": "(*Dispatcher).Assignments",
@ -1394,7 +1393,7 @@ func (d *Dispatcher) Session(r *api.SessionRequest, stream api.Dispatcher_Sessio
}
}
fields := logrus.Fields{
fields := log.Fields{
"node.id": nodeID,
"node.session": sessionID,
"method": "(*Dispatcher).Session",
@ -1402,7 +1401,7 @@ func (d *Dispatcher) Session(r *api.SessionRequest, stream api.Dispatcher_Sessio
if nodeInfo.ForwardedBy != nil {
fields["forwarder.id"] = nodeInfo.ForwardedBy.NodeID
}
log := log.G(ctx).WithFields(fields)
logger := log.G(ctx).WithFields(fields)
var nodeObj *api.Node
nodeUpdates, cancel, err := store.ViewAndWatch(d.store, func(readTx store.ReadTx) error {
@ -1416,7 +1415,7 @@ func (d *Dispatcher) Session(r *api.SessionRequest, stream api.Dispatcher_Sessio
}
if err != nil {
log.WithError(err).Error("ViewAndWatch Node failed")
logger.WithError(err).Error("ViewAndWatch Node failed")
}
if _, err = d.nodes.GetWithSession(nodeID, sessionID); err != nil {
@ -1438,9 +1437,9 @@ func (d *Dispatcher) Session(r *api.SessionRequest, stream api.Dispatcher_Sessio
// disconnectNode is a helper forcibly shutdown connection
disconnectNode := func() error {
log.Infof("dispatcher session dropped, marking node %s down", nodeID)
logger.Infof("dispatcher session dropped, marking node %s down", nodeID)
if err := d.markNodeNotReady(nodeID, api.NodeStatus_DISCONNECTED, "node is currently trying to find new manager"); err != nil {
log.WithError(err).Error("failed to remove node")
logger.WithError(err).Error("failed to remove node")
}
// still return an abort if the transport closure was ineffective.
return status.Errorf(codes.Aborted, "node must disconnect")

View file

@ -14,7 +14,6 @@ import (
"github.com/moby/swarmkit/v2/log"
"github.com/moby/swarmkit/v2/manager/state/store"
"github.com/moby/swarmkit/v2/watch"
"github.com/sirupsen/logrus"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
@ -239,13 +238,13 @@ func (lb *LogBroker) SubscribeLogs(request *api.SubscribeLogsRequest, stream api
subscription.Run(pctx)
defer subscription.Stop()
log := log.G(ctx).WithFields(
logrus.Fields{
logger := log.G(ctx).WithFields(
log.Fields{
"method": "(*LogBroker).SubscribeLogs",
"subscription.id": subscription.message.ID,
},
)
log.Debug("subscribed")
logger.Debug("subscribed")
publishCh, publishCancel := lb.subscribe(subscription.message.ID)
defer publishCancel()
@ -319,8 +318,8 @@ func (lb *LogBroker) ListenSubscriptions(request *api.ListenSubscriptionsRequest
lb.nodeConnected(remote.NodeID)
defer lb.nodeDisconnected(remote.NodeID)
log := log.G(stream.Context()).WithFields(
logrus.Fields{
logger := log.G(stream.Context()).WithFields(
log.Fields{
"method": "(*LogBroker).ListenSubscriptions",
"node": remote.NodeID,
},
@ -328,7 +327,7 @@ func (lb *LogBroker) ListenSubscriptions(request *api.ListenSubscriptionsRequest
subscriptions, subscriptionCh, subscriptionCancel := lb.watchSubscriptions(remote.NodeID)
defer subscriptionCancel()
log.Debug("node registered")
logger.Debug("node registered")
activeSubscriptions := make(map[string]*subscription)
@ -343,7 +342,7 @@ func (lb *LogBroker) ListenSubscriptions(request *api.ListenSubscriptionsRequest
}
if err := stream.Send(subscription.message); err != nil {
log.Error(err)
logger.Error(err)
return err
}
activeSubscriptions[subscription.message.ID] = subscription
@ -365,7 +364,7 @@ func (lb *LogBroker) ListenSubscriptions(request *api.ListenSubscriptionsRequest
activeSubscriptions[subscription.message.ID] = subscription
}
if err := stream.Send(subscription.message); err != nil {
log.Error(err)
logger.Error(err)
return err
}
case <-stream.Context().Done():

View file

@ -49,7 +49,6 @@ import (
"github.com/moby/swarmkit/v2/remotes"
"github.com/moby/swarmkit/v2/xnet"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
)
@ -736,7 +735,7 @@ func (m *Manager) Stop(ctx context.Context, clearData bool) {
func (m *Manager) updateKEK(ctx context.Context, cluster *api.Cluster) error {
securityConfig := m.config.SecurityConfig
nodeID := m.config.SecurityConfig.ClientTLSCreds.NodeID()
logger := log.G(ctx).WithFields(logrus.Fields{
logger := log.G(ctx).WithFields(log.Fields{
"node.id": nodeID,
"node.role": ca.ManagerRole,
})
@ -899,11 +898,10 @@ func (m *Manager) serveListener(ctx context.Context, lCh <-chan net.Listener) {
case <-ctx.Done():
return
}
ctx = log.WithLogger(ctx, log.G(ctx).WithFields(
logrus.Fields{
"proto": l.Addr().Network(),
"addr": l.Addr().String(),
}))
ctx = log.WithLogger(ctx, log.G(ctx).WithFields(log.Fields{
"proto": l.Addr().Network(),
"addr": l.Addr().String(),
}))
if _, ok := l.(*net.TCPListener); !ok {
log.G(ctx).Info("Listening for local connections")
// we need to disallow double closes because UnixListener.Close

View file

@ -488,6 +488,18 @@ func (s *Scheduler) tick(ctx context.Context) {
}
func (s *Scheduler) applySchedulingDecisions(ctx context.Context, schedulingDecisions map[string]schedulingDecision) (successful, failed []schedulingDecision) {
// applySchedulingDecisions is the only place where we make store
// transactions in the scheduler. the scheduler is responsible for freeing
// volumes that are no longer in use. this means that volumes should be
// freed in this function. sometimes, there are no scheduling decisions to
// be made, so we return early in the if statement below.
//
// however, in all cases, any activity that results in a tick could result
// in needing volumes to be freed, even if nothing new is scheduled. this
// freeing of volumes should always happen *after* all of the scheduling
// decisions have been committed, hence the defer.
defer s.store.Batch(s.volumes.freeVolumes)
if len(schedulingDecisions) == 0 {
return
}
@ -619,9 +631,7 @@ func (s *Scheduler) applySchedulingDecisions(ctx context.Context, schedulingDeci
}
// finally, every time we make new scheduling decisions, take the
// opportunity to release volumes.
return batch.Update(func(tx store.Tx) error {
return s.volumes.freeVolumes(tx)
})
return nil
})
if err != nil {

View file

@ -183,24 +183,33 @@ func (vs *volumeSet) releaseVolume(volumeID, taskID string) {
//
// TODO(dperny): this is messy and has a lot of overhead. it should be reworked
// to something more streamlined.
func (vs *volumeSet) freeVolumes(tx store.Tx) error {
func (vs *volumeSet) freeVolumes(batch *store.Batch) error {
for volumeID, info := range vs.volumes {
v := store.GetVolume(tx, volumeID)
if v == nil {
continue
}
if err := batch.Update(func(tx store.Tx) error {
v := store.GetVolume(tx, volumeID)
if v == nil {
return nil
}
changed := false
for _, status := range v.PublishStatus {
if info.nodes[status.NodeID] == 0 && status.State == api.VolumePublishStatus_PUBLISHED {
status.State = api.VolumePublishStatus_PENDING_NODE_UNPUBLISH
changed = true
// when we are freeing a volume, we may update more than one of the
// volume's PublishStatuses. this means we can't simply put the
// Update call inside of the if statement; we need to know if we've
// changed anything once we've checked *all* of the statuses.
changed := false
for _, status := range v.PublishStatus {
if info.nodes[status.NodeID] == 0 && status.State == api.VolumePublishStatus_PUBLISHED {
status.State = api.VolumePublishStatus_PENDING_NODE_UNPUBLISH
changed = true
}
}
}
if changed {
if err := store.UpdateVolume(tx, v); err != nil {
return err
if changed {
if err := store.UpdateVolume(tx, v); err != nil {
return err
}
}
return nil
}); err != nil {
return err
}
}
return nil

View file

@ -929,7 +929,7 @@ func (n *Node) Join(ctx context.Context, req *api.JoinRequest) (*api.JoinRespons
return nil, err
}
fields := logrus.Fields{
fields := log.Fields{
"node.id": nodeInfo.NodeID,
"method": "(*Node).Join",
"raft_id": fmt.Sprintf("%x", n.Config.ID),
@ -937,8 +937,8 @@ func (n *Node) Join(ctx context.Context, req *api.JoinRequest) (*api.JoinRespons
if nodeInfo.ForwardedBy != nil {
fields["forwarder.id"] = nodeInfo.ForwardedBy.NodeID
}
log := log.G(ctx).WithFields(fields)
log.Debug("")
logger := log.G(ctx).WithFields(fields)
logger.Debug("")
// can't stop the raft node while an async RPC is in progress
n.stopMu.RLock()
@ -999,11 +999,11 @@ func (n *Node) Join(ctx context.Context, req *api.JoinRequest) (*api.JoinRespons
}
if err := n.updateNodeBlocking(ctx, m.RaftID, remoteAddr); err != nil {
log.WithError(err).Error("failed to update node address")
logger.WithError(err).Error("failed to update node address")
return nil, err
}
log.Info("updated node address")
logger.Info("updated node address")
return n.joinResponse(m.RaftID), nil
}
}
@ -1019,11 +1019,11 @@ func (n *Node) Join(ctx context.Context, req *api.JoinRequest) (*api.JoinRespons
err = n.addMember(ctx, remoteAddr, raftID, nodeInfo.NodeID)
if err != nil {
log.WithError(err).Errorf("failed to add member %x", raftID)
logger.WithError(err).Errorf("failed to add member %x", raftID)
return nil, err
}
log.Debug("node joined")
logger.Debug("node joined")
return n.joinResponse(raftID), nil
}
@ -1126,7 +1126,7 @@ func (n *Node) UpdateNode(id uint64, addr string) {
// spawn updating info in raft in background to unblock transport
go func() {
if err := n.updateNodeBlocking(ctx, id, addr); err != nil {
log.G(ctx).WithFields(logrus.Fields{"raft_id": n.Config.ID, "update_id": id}).WithError(err).Error("failed to update member address in cluster")
log.G(ctx).WithFields(log.Fields{"raft_id": n.Config.ID, "update_id": id}).WithError(err).Error("failed to update member address in cluster")
}
}()
}
@ -1148,7 +1148,7 @@ func (n *Node) Leave(ctx context.Context, req *api.LeaveRequest) (*api.LeaveResp
ctx, cancel := n.WithContext(ctx)
defer cancel()
fields := logrus.Fields{
fields := log.Fields{
"node.id": nodeInfo.NodeID,
"method": "(*Node).Leave",
"raft_id": fmt.Sprintf("%x", n.Config.ID),
@ -1273,7 +1273,7 @@ func (n *Node) RemoveMember(ctx context.Context, id uint64) error {
// ProcessRaftMessage. Usually nothing will be logged, so it is useful to avoid
// formatting strings and allocating a logger when it won't be used.
func (n *Node) processRaftMessageLogger(ctx context.Context, msg *api.ProcessRaftMessageRequest) *logrus.Entry {
fields := logrus.Fields{
fields := log.Fields{
"method": "(*Node).ProcessRaftMessage",
}
@ -1474,7 +1474,7 @@ func (n *Node) ResolveAddress(ctx context.Context, msg *api.ResolveAddressReques
return nil, err
}
fields := logrus.Fields{
fields := log.Fields{
"node.id": nodeInfo.NodeID,
"method": "(*Node).ResolveAddress",
"raft_id": fmt.Sprintf("%x", n.Config.ID),

View file

@ -276,7 +276,7 @@ func configVXLANUDPPort(ctx context.Context, vxlanUDPPort uint32) {
log.G(ctx).WithError(err).Error("failed to configure VXLAN UDP port")
return
}
logrus.Infof("initialized VXLAN UDP port to %d ", vxlanUDPPort)
log.G(ctx).Infof("initialized VXLAN UDP port to %d ", vxlanUDPPort)
}
func (n *Node) run(ctx context.Context) (err error) {
@ -444,7 +444,7 @@ func (n *Node) run(ctx context.Context) (err error) {
go func() {
for certUpdate := range updates {
if certUpdate.Err != nil {
logrus.Warnf("error renewing TLS certificate: %v", certUpdate.Err)
log.G(ctx).Warnf("error renewing TLS certificate: %v", certUpdate.Err)
continue
}
// Set the new role, and notify our waiting role changing logic
@ -862,7 +862,7 @@ func (n *Node) loadSecurityConfig(ctx context.Context, paths *ca.SecurityConfigP
// Attempt to load certificate from disk
securityConfig, cancel, err = ca.LoadSecurityConfig(ctx, rootCA, krw, n.config.ForceNewCluster)
if err == nil {
log.G(ctx).WithFields(logrus.Fields{
log.G(ctx).WithFields(log.Fields{
"node.id": securityConfig.ClientTLSCreds.NodeID(),
}).Debugf("loaded TLS certificate")
} else {

View file

@ -6,7 +6,7 @@ import (
"sync"
"github.com/docker/go-events"
"github.com/sirupsen/logrus"
"github.com/moby/swarmkit/v2/log"
)
// ErrQueueFull is returned by a Write operation when that Write causes the
@ -112,7 +112,7 @@ func (eq *LimitQueue) run() {
// Eventually, go-events should not use logrus at all,
// and should bubble up conditions like this through
// error values.
logrus.WithFields(logrus.Fields{
log.L.WithFields(log.Fields{
"event": event,
"sink": eq.dst,
}).WithError(err).Debug("eventqueue: dropped event")

21
vendor/github.com/weppos/publicsuffix-go/LICENSE.txt generated vendored Normal file
View file

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2016-2020 Simone Carletti
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.

View file

@ -0,0 +1,544 @@
//go:generate go run ../cmd/gen/gen.go
// Package publicsuffix provides a domain name parser
// based on data from the public suffix list http://publicsuffix.org/.
// A public suffix is one under which Internet users can directly register names.
package publicsuffix
import (
"bufio"
"fmt"
"io"
"net/http/cookiejar"
"os"
"strings"
"golang.org/x/net/idna"
)
const (
// Version identifies the current library version.
// This is a pro forma convention given that Go dependencies
// tends to be fetched directly from the repo.
Version = "0.15.0"
// NormalType represents a normal rule such as "com"
NormalType = 1
// WildcardType represents a wildcard rule such as "*.com"
WildcardType = 2
// ExceptionType represents an exception to a wildard rule
ExceptionType = 3
listTokenPrivateDomains = "===BEGIN PRIVATE DOMAINS==="
listTokenComment = "//"
)
// DefaultList is the default List and it is used by Parse and Domain.
var DefaultList = NewList()
// DefaultRule is the default Rule that represents "*".
var DefaultRule = MustNewRule("*")
// DefaultParserOptions are the default options used to parse a Public Suffix list.
var DefaultParserOptions = &ParserOption{PrivateDomains: true, ASCIIEncoded: false}
// DefaultFindOptions are the default options used to perform the lookup of rules in the list.
var DefaultFindOptions = &FindOptions{IgnorePrivate: false, DefaultRule: DefaultRule}
// Rule represents a single rule in a Public Suffix List.
type Rule struct {
Type int
Value string
Length int
Private bool
}
// ParserOption are the options you can use to customize the way a List
// is parsed from a file or a string.
type ParserOption struct {
// Set to false to skip the private domains when parsing.
// Default to true, which means the private domains are included.
PrivateDomains bool
// Set to false if the input is encoded in U-labels (Unicode)
// as opposite to A-labels.
// Default to false, which means the list is containing Unicode domains.
// This is the default because the original PSL currently contains Unicode.
ASCIIEncoded bool
}
// FindOptions are the options you can use to customize the way a Rule
// is searched within the list.
type FindOptions struct {
// Set to true to ignore the rules within the "Private" section of the Public Suffix List.
IgnorePrivate bool
// The default rule to use when no rule matches the input.
// The format Public Suffix algorithm states that the rule "*" should be used when no other rule matches,
// but some consumers may have different needs.
DefaultRule *Rule
}
// List represents a Public Suffix List.
type List struct {
// rules is kept private because you should not access rules directly
rules map[string]*Rule
}
// NewList creates a new empty list.
func NewList() *List {
return &List{
rules: map[string]*Rule{},
}
}
// NewListFromString parses a string that represents a Public Suffix source
// and returns a List initialized with the rules in the source.
func NewListFromString(src string, options *ParserOption) (*List, error) {
l := NewList()
_, err := l.LoadString(src, options)
return l, err
}
// NewListFromFile parses a string that represents a Public Suffix source
// and returns a List initialized with the rules in the source.
func NewListFromFile(path string, options *ParserOption) (*List, error) {
l := NewList()
_, err := l.LoadFile(path, options)
return l, err
}
// Load parses and loads a set of rules from an io.Reader into the current list.
func (l *List) Load(r io.Reader, options *ParserOption) ([]Rule, error) {
return l.parse(r, options)
}
// LoadString parses and loads a set of rules from a String into the current list.
func (l *List) LoadString(src string, options *ParserOption) ([]Rule, error) {
r := strings.NewReader(src)
return l.parse(r, options)
}
// LoadFile parses and loads a set of rules from a File into the current list.
func (l *List) LoadFile(path string, options *ParserOption) ([]Rule, error) {
f, err := os.Open(path)
if err != nil {
return nil, err
}
defer f.Close()
return l.parse(f, options)
}
// AddRule adds a new rule to the list.
//
// The exact position of the rule into the list is unpredictable.
// The list may be optimized internally for lookups, therefore the algorithm
// will decide the best position for the new rule.
func (l *List) AddRule(r *Rule) error {
l.rules[r.Value] = r
return nil
}
// Size returns the size of the list, which is the number of rules.
func (l *List) Size() int {
return len(l.rules)
}
func (l *List) parse(r io.Reader, options *ParserOption) ([]Rule, error) {
if options == nil {
options = DefaultParserOptions
}
var rules []Rule
scanner := bufio.NewScanner(r)
var section int // 1 == ICANN, 2 == PRIVATE
Scanning:
for scanner.Scan() {
line := strings.TrimSpace(scanner.Text())
switch {
// skip blank lines
case line == "":
break
// include private domains or stop scanner
case strings.Contains(line, listTokenPrivateDomains):
if !options.PrivateDomains {
break Scanning
}
section = 2
// skip comments
case strings.HasPrefix(line, listTokenComment):
break
default:
var rule *Rule
var err error
if options.ASCIIEncoded {
rule, err = NewRule(line)
} else {
rule, err = NewRuleUnicode(line)
}
if err != nil {
return []Rule{}, err
}
rule.Private = (section == 2)
l.AddRule(rule)
rules = append(rules, *rule)
}
}
return rules, scanner.Err()
}
// Find and returns the most appropriate rule for the domain name.
func (l *List) Find(name string, options *FindOptions) *Rule {
if options == nil {
options = DefaultFindOptions
}
part := name
for {
rule, ok := l.rules[part]
if ok && rule.Match(name) && !(options.IgnorePrivate && rule.Private) {
return rule
}
i := strings.IndexRune(part, '.')
if i < 0 {
return options.DefaultRule
}
part = part[i+1:]
}
}
// NewRule parses the rule content, creates and returns a Rule.
//
// The content of the rule MUST be encoded in ASCII (A-labels).
func NewRule(content string) (*Rule, error) {
var rule *Rule
var value string
switch content[0] {
case '*': // wildcard
if content == "*" {
value = ""
} else {
value = content[2:]
}
rule = &Rule{Type: WildcardType, Value: value, Length: len(Labels(value)) + 1}
case '!': // exception
value = content[1:]
rule = &Rule{Type: ExceptionType, Value: value, Length: len(Labels(value))}
default: // normal
value = content
rule = &Rule{Type: NormalType, Value: value, Length: len(Labels(value))}
}
return rule, nil
}
// NewRuleUnicode is like NewRule, but expects the content to be encoded in Unicode (U-labels).
func NewRuleUnicode(content string) (*Rule, error) {
var err error
content, err = ToASCII(content)
if err != nil {
return nil, err
}
return NewRule(content)
}
// MustNewRule is like NewRule, but panics if the content cannot be parsed.
func MustNewRule(content string) *Rule {
rule, err := NewRule(content)
if err != nil {
panic(err)
}
return rule
}
// Match checks if the rule matches the name.
//
// A domain name is said to match a rule if and only if all of the following conditions are met:
// - When the domain and rule are split into corresponding labels,
// that the domain contains as many or more labels than the rule.
// - Beginning with the right-most labels of both the domain and the rule,
// and continuing for all labels in the rule, one finds that for every pair,
// either they are identical, or that the label from the rule is "*".
//
// See https://publicsuffix.org/list/
func (r *Rule) Match(name string) bool {
left := strings.TrimSuffix(name, r.Value)
// the name contains as many labels than the rule
// this is a match, unless it's a wildcard
// because the wildcard requires one more label
if left == "" {
return r.Type != WildcardType
}
// if there is one more label, the rule match
// because either the rule is shorter than the domain
// or the rule is a wildcard and there is one more label
return left[len(left)-1:] == "."
}
// Decompose takes a name as input and decomposes it into a tuple of <TRD+SLD, TLD>,
// according to the rule definition and type.
func (r *Rule) Decompose(name string) (result [2]string) {
if r == DefaultRule {
i := strings.LastIndexByte(name, '.')
if i < 0 {
return
}
result[0], result[1] = name[:i], name[i+1:]
return
}
switch r.Type {
case NormalType:
name = strings.TrimSuffix(name, r.Value)
if len(name) == 0 {
return
}
result[0], result[1] = name[:len(name)-1], r.Value
case WildcardType:
name := strings.TrimSuffix(name, r.Value)
if len(name) == 0 {
return
}
name = name[:len(name)-1]
i := strings.LastIndexByte(name, '.')
if i < 0 {
return
}
result[0], result[1] = name[:i], name[i+1:]+"."+r.Value
case ExceptionType:
i := strings.IndexRune(r.Value, '.')
if i < 0 {
return
}
suffix := r.Value[i+1:]
name = strings.TrimSuffix(name, suffix)
if len(name) == 0 {
return
}
result[0], result[1] = name[:len(name)-1], suffix
}
return
}
// Labels decomposes given domain name into labels,
// corresponding to the dot-separated tokens.
func Labels(name string) []string {
return strings.Split(name, ".")
}
// DomainName represents a domain name.
type DomainName struct {
TLD string
SLD string
TRD string
Rule *Rule
}
// String joins the components of the domain name into a single string.
// Empty labels are skipped.
//
// Examples:
//
// DomainName{"com", "example"}.String()
// // example.com
// DomainName{"com", "example", "www"}.String()
// // www.example.com
//
func (d *DomainName) String() string {
switch {
case d.TLD == "":
return ""
case d.SLD == "":
return d.TLD
case d.TRD == "":
return d.SLD + "." + d.TLD
default:
return d.TRD + "." + d.SLD + "." + d.TLD
}
}
// Domain extract and return the domain name from the input
// using the default (Public Suffix) List.
//
// Examples:
//
// publicsuffix.Domain("example.com")
// // example.com
// publicsuffix.Domain("www.example.com")
// // example.com
// publicsuffix.Domain("www.example.co.uk")
// // example.co.uk
//
func Domain(name string) (string, error) {
return DomainFromListWithOptions(DefaultList, name, DefaultFindOptions)
}
// Parse decomposes the name into TLD, SLD, TRD
// using the default (Public Suffix) List,
// and returns the result as a DomainName
//
// Examples:
//
// list := NewList()
//
// publicsuffix.Parse("example.com")
// // &DomainName{"com", "example"}
// publicsuffix.Parse("www.example.com")
// // &DomainName{"com", "example", "www"}
// publicsuffix.Parse("www.example.co.uk")
// // &DomainName{"co.uk", "example"}
//
func Parse(name string) (*DomainName, error) {
return ParseFromListWithOptions(DefaultList, name, DefaultFindOptions)
}
// DomainFromListWithOptions extract and return the domain name from the input
// using the (Public Suffix) list passed as argument.
//
// Examples:
//
// list := NewList()
//
// publicsuffix.DomainFromListWithOptions(list, "example.com")
// // example.com
// publicsuffix.DomainFromListWithOptions(list, "www.example.com")
// // example.com
// publicsuffix.DomainFromListWithOptions(list, "www.example.co.uk")
// // example.co.uk
//
func DomainFromListWithOptions(l *List, name string, options *FindOptions) (string, error) {
dn, err := ParseFromListWithOptions(l, name, options)
if err != nil {
return "", err
}
return dn.SLD + "." + dn.TLD, nil
}
// ParseFromListWithOptions decomposes the name into TLD, SLD, TRD
// using the (Public Suffix) list passed as argument,
// and returns the result as a DomainName
//
// Examples:
//
// list := NewList()
//
// publicsuffix.ParseFromListWithOptions(list, "example.com")
// // &DomainName{"com", "example"}
// publicsuffix.ParseFromListWithOptions(list, "www.example.com")
// // &DomainName{"com", "example", "www"}
// publicsuffix.ParseFromListWithOptions(list, "www.example.co.uk")
// // &DomainName{"co.uk", "example"}
//
func ParseFromListWithOptions(l *List, name string, options *FindOptions) (*DomainName, error) {
n, err := normalize(name)
if err != nil {
return nil, err
}
r := l.Find(n, options)
if r == nil {
return nil, fmt.Errorf("no rule matching name %s", name)
}
parts := r.Decompose(n)
left, tld := parts[0], parts[1]
if tld == "" {
return nil, fmt.Errorf("%s is a suffix", n)
}
dn := &DomainName{
Rule: r,
TLD: tld,
}
if i := strings.LastIndexByte(left, '.'); i < 0 {
dn.SLD = left
} else {
dn.TRD = left[:i]
dn.SLD = left[i+1:]
}
return dn, nil
}
func normalize(name string) (string, error) {
ret := strings.ToLower(name)
if ret == "" {
return "", fmt.Errorf("name is blank")
}
if ret[0] == '.' {
return "", fmt.Errorf("name %s starts with a dot", ret)
}
return ret, nil
}
// ToASCII is a wrapper for idna.ToASCII.
//
// This wrapper exists because idna.ToASCII backward-compatibility was broken twice in few months
// and I can't call this package directly anymore. The wrapper performs some terrible-but-necessary
// before-after replacements to make sure an already ASCII input always results in the same output
// even if passed through ToASCII.
//
// See golang/net@67957fd0b1, golang/net@f2499483f9, golang/net@78ebe5c8b6,
// and weppos/publicsuffix-go#66.
func ToASCII(s string) (string, error) {
// .example.com should be .example.com
// ..example.com should be ..example.com
if strings.HasPrefix(s, ".") {
dotIndex := 0
for i := 0; i < len(s); i++ {
if s[i] == '.' {
dotIndex = i
} else {
break
}
}
out, err := idna.ToASCII(s[dotIndex+1:])
out = s[:dotIndex+1] + out
return out, err
}
return idna.ToASCII(s)
}
// ToUnicode is a wrapper for idna.ToUnicode.
//
// See ToASCII for more details about why this wrapper exists.
func ToUnicode(s string) (string, error) {
return idna.ToUnicode(s)
}
// CookieJarList implements the cookiejar.PublicSuffixList interface.
var CookieJarList cookiejar.PublicSuffixList = cookiejarList{DefaultList}
type cookiejarList struct {
List *List
}
// PublicSuffix implements cookiejar.PublicSuffixList.
func (l cookiejarList) PublicSuffix(domain string) string {
rule := l.List.Find(domain, nil)
return rule.Decompose(domain)[1]
}
// PublicSuffix implements cookiejar.String.
func (cookiejarList) String() string {
return defaultListVersion
}

File diff suppressed because it is too large Load diff

257
vendor/github.com/zmap/zcrypto/LICENSE generated vendored Normal file
View file

@ -0,0 +1,257 @@
ZCrypto is an original work created at the University of Michigan, and is
licensed under the Apache 2.0 license. However, ZCrypto contains a fork of
several packages from Golang standard library, as well as code from the
BoringSSL test runner. Files that were created by Google, and new files in
forks of packages maintained by Google have a Google copyright and fall under
the ISC license. In addition ZCrypto includes a `util/isURL.go` file created by
Alex Saskevich and licensed under the MIT license. All other files are copyright
Regents of the University of Michigan, and fall under the Apache 2.0 license.
All three licenses are reproduced at the bottom of this file.
--------
ISC License used for Google code
/* Copyright (c) 2015, Google Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
--------
MIT License used for util/isURL.go adopted from https://github.com/asaskevich/govalidator
The MIT License (MIT)
Copyright (c) 2014 Alex Saskevich
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.
--------
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.
ZCrypto Copyright 2015 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.

309
vendor/github.com/zmap/zcrypto/dsa/dsa.go generated vendored Normal file
View file

@ -0,0 +1,309 @@
// Copyright 2011 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 dsa implements the Digital Signature Algorithm, as defined in FIPS 186-3.
//
// The DSA operations in this package are not implemented using constant-time algorithms.
//
// Warning: DSA is a legacy algorithm, and modern alternatives such as
// Ed25519 (implemented by package crypto/ed25519) should be used instead. Keys
// with 1024-bit moduli (L1024N160 parameters) are cryptographically weak, while
// bigger keys are not widely supported. Note that FIPS 186-5 no longer approves
// DSA for signature generation.
package dsa
import (
"errors"
"io"
"math/big"
"github.com/zmap/zcrypto/internal/randutil"
)
// Parameters represents the domain parameters for a key. These parameters can
// be shared across many keys. The bit length of Q must be a multiple of 8.
type Parameters struct {
P, Q, G *big.Int
}
// PublicKey represents a DSA public key.
type PublicKey struct {
Parameters
Y *big.Int
}
// PrivateKey represents a DSA private key.
type PrivateKey struct {
PublicKey
X *big.Int
}
// ErrInvalidPublicKey results when a public key is not usable by this code.
// FIPS is quite strict about the format of DSA keys, but other code may be
// less so. Thus, when using keys which may have been generated by other code,
// this error must be handled.
var ErrInvalidPublicKey = errors.New("crypto/dsa: invalid public key")
// ParameterSizes is an enumeration of the acceptable bit lengths of the primes
// in a set of DSA parameters. See FIPS 186-3, section 4.2.
type ParameterSizes int
const (
L1024N160 ParameterSizes = iota
L2048N224
L2048N256
L3072N256
)
// numMRTests is the number of Miller-Rabin primality tests that we perform. We
// pick the largest recommended number from table C.1 of FIPS 186-3.
const numMRTests = 64
// GenerateParameters puts a random, valid set of DSA parameters into params.
// This function can take many seconds, even on fast machines.
func GenerateParameters(params *Parameters, rand io.Reader, sizes ParameterSizes) error {
// This function doesn't follow FIPS 186-3 exactly in that it doesn't
// use a verification seed to generate the primes. The verification
// seed doesn't appear to be exported or used by other code and
// omitting it makes the code cleaner.
var L, N int
switch sizes {
case L1024N160:
L = 1024
N = 160
case L2048N224:
L = 2048
N = 224
case L2048N256:
L = 2048
N = 256
case L3072N256:
L = 3072
N = 256
default:
return errors.New("crypto/dsa: invalid ParameterSizes")
}
qBytes := make([]byte, N/8)
pBytes := make([]byte, L/8)
q := new(big.Int)
p := new(big.Int)
rem := new(big.Int)
one := new(big.Int)
one.SetInt64(1)
GeneratePrimes:
for {
if _, err := io.ReadFull(rand, qBytes); err != nil {
return err
}
qBytes[len(qBytes)-1] |= 1
qBytes[0] |= 0x80
q.SetBytes(qBytes)
if !q.ProbablyPrime(numMRTests) {
continue
}
for i := 0; i < 4*L; i++ {
if _, err := io.ReadFull(rand, pBytes); err != nil {
return err
}
pBytes[len(pBytes)-1] |= 1
pBytes[0] |= 0x80
p.SetBytes(pBytes)
rem.Mod(p, q)
rem.Sub(rem, one)
p.Sub(p, rem)
if p.BitLen() < L {
continue
}
if !p.ProbablyPrime(numMRTests) {
continue
}
params.P = p
params.Q = q
break GeneratePrimes
}
}
h := new(big.Int)
h.SetInt64(2)
g := new(big.Int)
pm1 := new(big.Int).Sub(p, one)
e := new(big.Int).Div(pm1, q)
for {
g.Exp(h, e, p)
if g.Cmp(one) == 0 {
h.Add(h, one)
continue
}
params.G = g
return nil
}
}
// GenerateKey generates a public&private key pair. The Parameters of the
// PrivateKey must already be valid (see GenerateParameters).
func GenerateKey(priv *PrivateKey, rand io.Reader) error {
if priv.P == nil || priv.Q == nil || priv.G == nil {
return errors.New("crypto/dsa: parameters not set up before generating key")
}
x := new(big.Int)
xBytes := make([]byte, priv.Q.BitLen()/8)
for {
_, err := io.ReadFull(rand, xBytes)
if err != nil {
return err
}
x.SetBytes(xBytes)
if x.Sign() != 0 && x.Cmp(priv.Q) < 0 {
break
}
}
priv.X = x
priv.Y = new(big.Int)
priv.Y.Exp(priv.G, x, priv.P)
return nil
}
// fermatInverse calculates the inverse of k in GF(P) using Fermat's method.
// This has better constant-time properties than Euclid's method (implemented
// in math/big.Int.ModInverse) although math/big itself isn't strictly
// constant-time so it's not perfect.
func fermatInverse(k, P *big.Int) *big.Int {
two := big.NewInt(2)
pMinus2 := new(big.Int).Sub(P, two)
return new(big.Int).Exp(k, pMinus2, P)
}
// Sign signs an arbitrary length hash (which should be the result of hashing a
// larger message) using the private key, priv. It returns the signature as a
// pair of integers. The security of the private key depends on the entropy of
// rand.
//
// Note that FIPS 186-3 section 4.6 specifies that the hash should be truncated
// to the byte-length of the subgroup. This function does not perform that
// truncation itself.
//
// Be aware that calling Sign with an attacker-controlled PrivateKey may
// require an arbitrary amount of CPU.
func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err error) {
randutil.MaybeReadByte(rand)
// FIPS 186-3, section 4.6
n := priv.Q.BitLen()
if priv.Q.Sign() <= 0 || priv.P.Sign() <= 0 || priv.G.Sign() <= 0 || priv.X.Sign() <= 0 || n%8 != 0 {
err = ErrInvalidPublicKey
return
}
n >>= 3
var attempts int
for attempts = 10; attempts > 0; attempts-- {
k := new(big.Int)
buf := make([]byte, n)
for {
_, err = io.ReadFull(rand, buf)
if err != nil {
return
}
k.SetBytes(buf)
// priv.Q must be >= 128 because the test above
// requires it to be > 0 and that
// ceil(log_2(Q)) mod 8 = 0
// Thus this loop will quickly terminate.
if k.Sign() > 0 && k.Cmp(priv.Q) < 0 {
break
}
}
kInv := fermatInverse(k, priv.Q)
r = new(big.Int).Exp(priv.G, k, priv.P)
r.Mod(r, priv.Q)
if r.Sign() == 0 {
continue
}
z := k.SetBytes(hash)
s = new(big.Int).Mul(priv.X, r)
s.Add(s, z)
s.Mod(s, priv.Q)
s.Mul(s, kInv)
s.Mod(s, priv.Q)
if s.Sign() != 0 {
break
}
}
// Only degenerate private keys will require more than a handful of
// attempts.
if attempts == 0 {
return nil, nil, ErrInvalidPublicKey
}
return
}
// Verify verifies the signature in r, s of hash using the public key, pub. It
// reports whether the signature is valid.
//
// Note that FIPS 186-3 section 4.6 specifies that the hash should be truncated
// to the byte-length of the subgroup. This function does not perform that
// truncation itself.
func Verify(pub *PublicKey, hash []byte, r, s *big.Int) bool {
// FIPS 186-3, section 4.7
if pub.P.Sign() == 0 {
return false
}
if r.Sign() < 1 || r.Cmp(pub.Q) >= 0 {
return false
}
if s.Sign() < 1 || s.Cmp(pub.Q) >= 0 {
return false
}
w := new(big.Int).ModInverse(s, pub.Q)
if w == nil {
return false
}
n := pub.Q.BitLen()
if n%8 != 0 {
return false
}
z := new(big.Int).SetBytes(hash)
u1 := new(big.Int).Mul(z, w)
u1.Mod(u1, pub.Q)
u2 := w.Mul(r, w)
u2.Mod(u2, pub.Q)
v := u1.Exp(pub.G, u1, pub.P)
u2.Exp(pub.Y, u2, pub.P)
v.Mul(v, u2)
v.Mod(v, pub.P)
v.Mod(v, pub.Q)
return v.Cmp(r) == 0
}

View file

@ -0,0 +1,38 @@
// Copyright 2018 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 randutil contains internal randomness utilities for various
// crypto packages.
package randutil
import (
"io"
"sync"
)
var (
closedChanOnce sync.Once
closedChan chan struct{}
)
// MaybeReadByte reads a single byte from r with ~50% probability. This is used
// to ensure that callers do not depend on non-guaranteed behaviour, e.g.
// assuming that rsa.GenerateKey is deterministic w.r.t. a given random stream.
//
// This does not affect tests that pass a stream of fixed bytes as the random
// source (e.g. a zeroReader).
func MaybeReadByte(r io.Reader) {
closedChanOnce.Do(func() {
closedChan = make(chan struct{})
close(closedChan)
})
select {
case <-closedChan:
return
case <-closedChan:
var buf [1]byte
r.Read(buf[:])
}
}

130
vendor/github.com/zmap/zcrypto/json/dhe.go generated vendored Normal file
View file

@ -0,0 +1,130 @@
/*
* ZGrab Copyright 2015 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 json
import (
"encoding/json"
"math/big"
)
// DHParams can be used to store finite-field Diffie-Hellman parameters. At any
// point in time, it is unlikely that both OurPrivate and TheirPrivate will be
// non-nil.
type DHParams struct {
Prime *big.Int
Generator *big.Int
ServerPublic *big.Int
ServerPrivate *big.Int
ClientPublic *big.Int
ClientPrivate *big.Int
SessionKey *big.Int
}
type auxDHParams struct {
Prime *cryptoParameter `json:"prime"`
Generator *cryptoParameter `json:"generator"`
ServerPublic *cryptoParameter `json:"server_public,omitempty"`
ServerPrivate *cryptoParameter `json:"server_private,omitempty"`
ClientPublic *cryptoParameter `json:"client_public,omitempty"`
ClientPrivate *cryptoParameter `json:"client_private,omitempty"`
SessionKey *cryptoParameter `json:"session_key,omitempty"`
}
// MarshalJSON implements the json.Marshal interface
func (p *DHParams) MarshalJSON() ([]byte, error) {
aux := auxDHParams{
Prime: &cryptoParameter{Int: p.Prime},
Generator: &cryptoParameter{Int: p.Generator},
}
if p.ServerPublic != nil {
aux.ServerPublic = &cryptoParameter{Int: p.ServerPublic}
}
if p.ServerPrivate != nil {
aux.ServerPrivate = &cryptoParameter{Int: p.ServerPrivate}
}
if p.ClientPublic != nil {
aux.ClientPublic = &cryptoParameter{Int: p.ClientPublic}
}
if p.ClientPrivate != nil {
aux.ClientPrivate = &cryptoParameter{Int: p.ClientPrivate}
}
if p.SessionKey != nil {
aux.SessionKey = &cryptoParameter{Int: p.SessionKey}
}
return json.Marshal(aux)
}
// UnmarshalJSON implement the json.Unmarshaler interface
func (p *DHParams) UnmarshalJSON(b []byte) error {
var aux auxDHParams
if err := json.Unmarshal(b, &aux); err != nil {
return err
}
if aux.Prime != nil {
p.Prime = aux.Prime.Int
}
if aux.Generator != nil {
p.Generator = aux.Generator.Int
}
if aux.ServerPublic != nil {
p.ServerPublic = aux.ServerPublic.Int
}
if aux.ServerPrivate != nil {
p.ServerPrivate = aux.ServerPrivate.Int
}
if aux.ClientPublic != nil {
p.ClientPublic = aux.ClientPublic.Int
}
if aux.ClientPrivate != nil {
p.ClientPrivate = aux.ClientPrivate.Int
}
if aux.SessionKey != nil {
p.SessionKey = aux.SessionKey.Int
}
return nil
}
// CryptoParameter represents a big.Int used a parameter in some cryptography.
// It serializes to json as a tupe of a base64-encoded number and a length in
// bits.
type cryptoParameter struct {
*big.Int
}
type auxCryptoParameter struct {
Raw []byte `json:"value"`
Length int `json:"length"`
}
// MarshalJSON implements the json.Marshaler interface
func (p *cryptoParameter) MarshalJSON() ([]byte, error) {
var aux auxCryptoParameter
if p.Int != nil {
aux.Raw = p.Bytes()
aux.Length = 8 * len(aux.Raw)
}
return json.Marshal(&aux)
}
// UnmarshalJSON implements the json.Unmarshal interface
func (p *cryptoParameter) UnmarshalJSON(b []byte) error {
var aux auxCryptoParameter
if err := json.Unmarshal(b, &aux); err != nil {
return err
}
p.Int = new(big.Int)
p.SetBytes(aux.Raw)
return nil
}

107
vendor/github.com/zmap/zcrypto/json/ecdhe.go generated vendored Normal file
View file

@ -0,0 +1,107 @@
/*
* ZGrab Copyright 2015 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 json
import (
"crypto/elliptic"
"encoding/json"
"math/big"
)
// TLSCurveID is the type of a TLS identifier for an elliptic curve. See
// http://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-8
type TLSCurveID uint16
// ECDHPrivateParams are the TLS key exchange parameters for ECDH keys.
type ECDHPrivateParams struct {
Value []byte `json:"value,omitempty"`
Length int `json:"length,omitempty"`
}
// ECDHParams stores elliptic-curve Diffie-Hellman paramters.At any point in
// time, it is unlikely that both ServerPrivate and ClientPrivate will be non-nil.
type ECDHParams struct {
TLSCurveID TLSCurveID `json:"curve_id,omitempty"`
Curve elliptic.Curve `json:"-"`
ServerPublic *ECPoint `json:"server_public,omitempty"`
ServerPrivate *ECDHPrivateParams `json:"server_private,omitempty"`
ClientPublic *ECPoint `json:"client_public,omitempty"`
ClientPrivate *ECDHPrivateParams `json:"client_private,omitempty"`
}
// ECPoint represents an elliptic curve point and serializes nicely to JSON
type ECPoint struct {
X *big.Int
Y *big.Int
}
// MarshalJSON implements the json.Marshler interface
func (p *ECPoint) MarshalJSON() ([]byte, error) {
aux := struct {
X *cryptoParameter `json:"x"`
Y *cryptoParameter `json:"y"`
}{
X: &cryptoParameter{Int: p.X},
Y: &cryptoParameter{Int: p.Y},
}
return json.Marshal(&aux)
}
// UnmarshalJSON implements the json.Unmarshler interface
func (p *ECPoint) UnmarshalJSON(b []byte) error {
aux := struct {
X *cryptoParameter `json:"x"`
Y *cryptoParameter `json:"y"`
}{}
if err := json.Unmarshal(b, &aux); err != nil {
return err
}
p.X = aux.X.Int
p.Y = aux.Y.Int
return nil
}
// Description returns the description field for the given ID. See
// http://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-8
func (c *TLSCurveID) Description() string {
if desc, ok := ecIDToName[*c]; ok {
return desc
}
return "unknown"
}
// MarshalJSON implements the json.Marshaler interface
func (c *TLSCurveID) MarshalJSON() ([]byte, error) {
aux := struct {
Name string `json:"name"`
ID uint16 `json:"id"`
}{
Name: c.Description(),
ID: uint16(*c),
}
return json.Marshal(&aux)
}
//UnmarshalJSON implements the json.Unmarshaler interface
func (c *TLSCurveID) UnmarshalJSON(b []byte) error {
aux := struct {
ID uint16 `json:"id"`
}{}
if err := json.Unmarshal(b, &aux); err != nil {
return err
}
*c = TLSCurveID(aux.ID)
return nil
}

113
vendor/github.com/zmap/zcrypto/json/names.go generated vendored Normal file
View file

@ -0,0 +1,113 @@
/*
* ZGrab Copyright 2015 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 json
// IANA-assigned curve ID values, see
// http://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-8
const (
Sect163k1 TLSCurveID = 1
Sect163r1 TLSCurveID = 2
Sect163r2 TLSCurveID = 3
Sect193r1 TLSCurveID = 4
Sect193r2 TLSCurveID = 5
Sect233k1 TLSCurveID = 6
Sect233r1 TLSCurveID = 7
Sect239k1 TLSCurveID = 8
Sect283k1 TLSCurveID = 9
Sect283r1 TLSCurveID = 10
Sect409k1 TLSCurveID = 11
Sect409r1 TLSCurveID = 12
Sect571k1 TLSCurveID = 13
Sect571r1 TLSCurveID = 14
Secp160k1 TLSCurveID = 15
Secp160r1 TLSCurveID = 16
Secp160r2 TLSCurveID = 17
Secp192k1 TLSCurveID = 18
Secp192r1 TLSCurveID = 19
Secp224k1 TLSCurveID = 20
Secp224r1 TLSCurveID = 21
Secp256k1 TLSCurveID = 22
Secp256r1 TLSCurveID = 23
Secp384r1 TLSCurveID = 24
Secp521r1 TLSCurveID = 25
BrainpoolP256r1 TLSCurveID = 26
BrainpoolP384r1 TLSCurveID = 27
BrainpoolP512r1 TLSCurveID = 28
)
var ecIDToName map[TLSCurveID]string
var ecNameToID map[string]TLSCurveID
func init() {
ecIDToName = make(map[TLSCurveID]string, 64)
ecIDToName[Sect163k1] = "sect163k1"
ecIDToName[Sect163r1] = "sect163r1"
ecIDToName[Sect163r2] = "sect163r2"
ecIDToName[Sect193r1] = "sect193r1"
ecIDToName[Sect193r2] = "sect193r2"
ecIDToName[Sect233k1] = "sect233k1"
ecIDToName[Sect233r1] = "sect233r1"
ecIDToName[Sect239k1] = "sect239k1"
ecIDToName[Sect283k1] = "sect283k1"
ecIDToName[Sect283r1] = "sect283r1"
ecIDToName[Sect409k1] = "sect409k1"
ecIDToName[Sect409r1] = "sect409r1"
ecIDToName[Sect571k1] = "sect571k1"
ecIDToName[Sect571r1] = "sect571r1"
ecIDToName[Secp160k1] = "secp160k1"
ecIDToName[Secp160r1] = "secp160r1"
ecIDToName[Secp160r2] = "secp160r2"
ecIDToName[Secp192k1] = "secp192k1"
ecIDToName[Secp192r1] = "secp192r1"
ecIDToName[Secp224k1] = "secp224k1"
ecIDToName[Secp224r1] = "secp224r1"
ecIDToName[Secp256k1] = "secp256k1"
ecIDToName[Secp256r1] = "secp256r1"
ecIDToName[Secp384r1] = "secp384r1"
ecIDToName[Secp521r1] = "secp521r1"
ecIDToName[BrainpoolP256r1] = "brainpoolp256r1"
ecIDToName[BrainpoolP384r1] = "brainpoolp384r1"
ecIDToName[BrainpoolP512r1] = "brainpoolp512r1"
ecNameToID = make(map[string]TLSCurveID, 64)
ecNameToID["sect163k1"] = Sect163k1
ecNameToID["sect163r1"] = Sect163r1
ecNameToID["sect163r2"] = Sect163r2
ecNameToID["sect193r1"] = Sect193r1
ecNameToID["sect193r2"] = Sect193r2
ecNameToID["sect233k1"] = Sect233k1
ecNameToID["sect233r1"] = Sect233r1
ecNameToID["sect239k1"] = Sect239k1
ecNameToID["sect283k1"] = Sect283k1
ecNameToID["sect283r1"] = Sect283r1
ecNameToID["sect409k1"] = Sect409k1
ecNameToID["sect409r1"] = Sect409r1
ecNameToID["sect571k1"] = Sect571k1
ecNameToID["sect571r1"] = Sect571r1
ecNameToID["secp160k1"] = Secp160k1
ecNameToID["secp160r1"] = Secp160r1
ecNameToID["secp160r2"] = Secp160r2
ecNameToID["secp192k1"] = Secp192k1
ecNameToID["secp192r1"] = Secp192r1
ecNameToID["secp224k1"] = Secp224k1
ecNameToID["secp224r1"] = Secp224r1
ecNameToID["secp256k1"] = Secp256k1
ecNameToID["secp256r1"] = Secp256r1
ecNameToID["secp384r1"] = Secp384r1
ecNameToID["secp521r1"] = Secp521r1
ecNameToID["brainpoolp256r1"] = BrainpoolP256r1
ecNameToID["brainpoolp384r1"] = BrainpoolP384r1
ecNameToID["brainpoolp512r1"] = BrainpoolP512r1
}

67
vendor/github.com/zmap/zcrypto/json/rsa.go generated vendored Normal file
View file

@ -0,0 +1,67 @@
/*
* ZGrab Copyright 2015 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 json
import (
"crypto/rsa"
"encoding/json"
"fmt"
"math/big"
)
// RSAPublicKey provides JSON methods for the standard rsa.PublicKey.
type RSAPublicKey struct {
*rsa.PublicKey
}
type auxRSAPublicKey struct {
Exponent int `json:"exponent"`
Modulus []byte `json:"modulus"`
Length int `json:"length"`
}
// RSAClientParams are the TLS key exchange parameters for RSA keys.
type RSAClientParams struct {
Length uint16 `json:"length,omitempty"`
EncryptedPMS []byte `json:"encrypted_pre_master_secret,omitempty"`
}
// MarshalJSON implements the json.Marshal interface
func (rp *RSAPublicKey) MarshalJSON() ([]byte, error) {
var aux auxRSAPublicKey
if rp.PublicKey != nil {
aux.Exponent = rp.E
aux.Modulus = rp.N.Bytes()
aux.Length = len(aux.Modulus) * 8
}
return json.Marshal(&aux)
}
// UnmarshalJSON implements the json.Unmarshal interface
func (rp *RSAPublicKey) UnmarshalJSON(b []byte) error {
var aux auxRSAPublicKey
if err := json.Unmarshal(b, &aux); err != nil {
return err
}
if rp.PublicKey == nil {
rp.PublicKey = new(rsa.PublicKey)
}
rp.E = aux.Exponent
rp.N = big.NewInt(0).SetBytes(aux.Modulus)
if len(aux.Modulus)*8 != aux.Length {
return fmt.Errorf("mismatched length (got %d, field specified %d)", len(aux.Modulus), aux.Length)
}
return nil
}

77
vendor/github.com/zmap/zcrypto/util/isURL.go generated vendored Normal file
View file

@ -0,0 +1,77 @@
/*
The MIT License (MIT)
Copyright (c) 2014 Alex Saskevich
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.
*/
package util
import (
"net/url"
"regexp"
"strings"
"unicode/utf8"
)
const (
maxURLRuneCount = 2083
minURLRuneCount = 3
IP = `(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))`
URLSchema = `((ftp|tcp|udp|wss?|https?):\/\/)`
URLUsername = `(\S+(:\S*)?@)`
URLPath = `((\/|\?|#)[^\s]*)`
URLPort = `(:(\d{1,5}))`
URLIP = `([1-9]\d?|1\d\d|2[01]\d|22[0-3])(\.(1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.([0-9]\d?|1\d\d|2[0-4]\d|25[0-4]))`
URLSubdomain = `((www\.)|([a-zA-Z0-9]+([-_\.]?[a-zA-Z0-9])*[a-zA-Z0-9]\.[a-zA-Z0-9]+))`
)
var (
URL = `^` + URLSchema + `?` + URLUsername + `?` + `((` + URLIP + `|(\[` + IP + `\])|(([a-zA-Z0-9]([a-zA-Z0-9-_]+)?[a-zA-Z0-9]([-\.][a-zA-Z0-9]+)*)|(` + URLSubdomain + `?))?(([a-zA-Z\x{00a1}-\x{ffff}0-9]+-?-?)*[a-zA-Z\x{00a1}-\x{ffff}0-9]+)(?:\.([a-zA-Z\x{00a1}-\x{ffff}]{1,}))?))\.?` + URLPort + `?` + URLPath + `?$`
rxURL = regexp.MustCompile(URL)
)
// IsURL check if the string is an URL.
// This function is (graciously) adopted from
// https://github.com/asaskevich/govalidator to avoid needing a full dependency on
// `govalidator` for the one `IsURL` function.
func IsURL(str string) bool {
if str == "" || utf8.RuneCountInString(str) >= maxURLRuneCount || len(str) <= minURLRuneCount || strings.HasPrefix(str, ".") {
return false
}
strTemp := str
if strings.Contains(str, ":") && !strings.Contains(str, "://") {
// support no indicated urlscheme but with colon for port number
// http:// is appended so url.Parse will succeed, strTemp used so it does not impact rxURL.MatchString
strTemp = "http://" + str
}
u, err := url.Parse(strTemp)
if err != nil {
return false
}
if strings.HasPrefix(u.Host, ".") {
return false
}
if u.Host == "" && (u.Path != "" && !strings.Contains(u.Path, ".")) {
return false
}
return rxURL.MatchString(str)
}

8
vendor/github.com/zmap/zcrypto/x509/README.md generated vendored Normal file
View file

@ -0,0 +1,8 @@
Originally based on the go/crypto/x509 standard library,
this package has now diverged enough that it is no longer
updated with direct correspondence to new go releases.
Approximately supports all the features of
github.com/golang/go/crypto/x509 package at:
branch: release-branch.go1.10
revision: dea961ebd9f871b39b3bdaab32f952037f28cd71

171
vendor/github.com/zmap/zcrypto/x509/cert_pool.go generated vendored Normal file
View file

@ -0,0 +1,171 @@
// Copyright 2011 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 x509
import (
"encoding/pem"
)
// CertPool is a set of certificates.
type CertPool struct {
bySubjectKeyId map[string][]int
byName map[string][]int
bySHA256 map[string]int
certs []*Certificate
}
// NewCertPool returns a new, empty CertPool.
func NewCertPool() *CertPool {
return &CertPool{
bySubjectKeyId: make(map[string][]int),
byName: make(map[string][]int),
bySHA256: make(map[string]int),
}
}
// findVerifiedParents attempts to find certificates in s which have signed the
// given certificate. If any candidates were rejected then errCert will be set
// to one of them, arbitrarily, and err will contain the reason that it was
// rejected.
func (s *CertPool) findVerifiedParents(cert *Certificate) (parents []int, errCert *Certificate, err error) {
if s == nil {
return
}
var candidates []int
if len(cert.AuthorityKeyId) > 0 {
candidates, _ = s.bySubjectKeyId[string(cert.AuthorityKeyId)]
}
if len(candidates) == 0 {
candidates, _ = s.byName[string(cert.RawIssuer)]
}
for _, c := range candidates {
if err = cert.CheckSignatureFrom(s.certs[c]); err == nil {
cert.validSignature = true
parents = append(parents, c)
} else {
errCert = s.certs[c]
}
}
return
}
// Contains returns true if c is in s.
func (s *CertPool) Contains(c *Certificate) bool {
if s == nil {
return false
}
_, ok := s.bySHA256[string(c.FingerprintSHA256)]
return ok
}
// Covers returns true if all certs in pool are in s.
func (s *CertPool) Covers(pool *CertPool) bool {
if pool == nil {
return true
}
for _, c := range pool.certs {
if !s.Contains(c) {
return false
}
}
return true
}
// Certificates returns a list of parsed certificates in the pool.
func (s *CertPool) Certificates() []*Certificate {
out := make([]*Certificate, 0, len(s.certs))
out = append(out, s.certs...)
return out
}
// Size returns the number of unique certificates in the CertPool.
func (s *CertPool) Size() int {
if s == nil {
return 0
}
return len(s.certs)
}
// Sum returns the union of two certificate pools as a new certificate pool.
func (s *CertPool) Sum(other *CertPool) (sum *CertPool) {
sum = NewCertPool()
if s != nil {
for _, c := range s.certs {
sum.AddCert(c)
}
}
if other != nil {
for _, c := range other.certs {
sum.AddCert(c)
}
}
return
}
// AddCert adds a certificate to a pool.
func (s *CertPool) AddCert(cert *Certificate) {
if cert == nil {
panic("adding nil Certificate to CertPool")
}
// Check that the certificate isn't being added twice.
sha256fp := string(cert.FingerprintSHA256)
if _, ok := s.bySHA256[sha256fp]; ok {
return
}
n := len(s.certs)
s.certs = append(s.certs, cert)
if len(cert.SubjectKeyId) > 0 {
keyId := string(cert.SubjectKeyId)
s.bySubjectKeyId[keyId] = append(s.bySubjectKeyId[keyId], n)
}
name := string(cert.RawSubject)
s.byName[name] = append(s.byName[name], n)
s.bySHA256[sha256fp] = n
}
// AppendCertsFromPEM attempts to parse a series of PEM encoded certificates.
// It appends any certificates found to s and reports whether any certificates
// were successfully parsed.
//
// On many Linux systems, /etc/ssl/cert.pem will contain the system wide set
// of root CAs in a format suitable for this function.
func (s *CertPool) AppendCertsFromPEM(pemCerts []byte) (ok bool) {
for len(pemCerts) > 0 {
var block *pem.Block
block, pemCerts = pem.Decode(pemCerts)
if block == nil {
break
}
if block.Type != "CERTIFICATE" || len(block.Headers) != 0 {
continue
}
cert, err := ParseCertificate(block.Bytes)
if err != nil {
continue
}
s.AddCert(cert)
ok = true
}
return
}
// Subjects returns a list of the DER-encoded subjects of
// all of the certificates in the pool.
func (s *CertPool) Subjects() [][]byte {
res := make([][]byte, len(s.certs))
for i, c := range s.certs {
res[i] = c.RawSubject
}
return res
}

View file

@ -0,0 +1,64 @@
// 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 x509
import "encoding/json"
// TODO: Automatically generate this file from a CSV
// CertificateType represents whether a certificate is a root, intermediate, or
// leaf.
type CertificateType int
// CertificateType constants. Values should not be considered significant aside
// from CertificateTypeUnknown is the zero value.
const (
CertificateTypeUnknown CertificateType = 0
CertificateTypeLeaf CertificateType = 1
CertificateTypeIntermediate CertificateType = 2
CertificateTypeRoot CertificateType = 3
)
const (
certificateTypeStringLeaf = "leaf"
certificateTypeStringIntermediate = "intermediate"
certificateTypeStringRoot = "root"
certificateTypeStringUnknown = "unknown"
)
// MarshalJSON implements the json.Marshaler interface. Any unknown integer
// value is considered the same as CertificateTypeUnknown.
func (t CertificateType) MarshalJSON() ([]byte, error) {
switch t {
case CertificateTypeLeaf:
return json.Marshal(certificateTypeStringLeaf)
case CertificateTypeIntermediate:
return json.Marshal(certificateTypeStringIntermediate)
case CertificateTypeRoot:
return json.Marshal(certificateTypeStringRoot)
default:
return json.Marshal(certificateTypeStringUnknown)
}
}
// UnmarshalJSON implements the json.Unmarshaler interface. Any unknown string
// is considered the same CertificateTypeUnknown.
func (t *CertificateType) UnmarshalJSON(b []byte) error {
var certificateTypeString string
if err := json.Unmarshal(b, &certificateTypeString); err != nil {
return err
}
switch certificateTypeString {
case certificateTypeStringLeaf:
*t = CertificateTypeLeaf
case certificateTypeStringIntermediate:
*t = CertificateTypeIntermediate
case certificateTypeStringRoot:
*t = CertificateTypeRoot
default:
*t = CertificateTypeUnknown
}
return nil
}

70
vendor/github.com/zmap/zcrypto/x509/chain.go generated vendored Normal file
View file

@ -0,0 +1,70 @@
// 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 x509
import (
"bytes"
"strings"
)
// CertificateChain is a slice of certificates. The 0'th element is the leaf,
// and the last element is a root. Successive elements have a child-parent
// relationship.
type CertificateChain []*Certificate
// Range runs a function on each element of chain. It can modify each
// certificate in place.
func (chain CertificateChain) Range(f func(int, *Certificate)) {
for i, c := range chain {
f(i, c)
}
}
// SubjectAndKeyInChain returns true if the given SubjectAndKey is found in any
// certificate in the chain.
func (chain CertificateChain) SubjectAndKeyInChain(sk *SubjectAndKey) bool {
for _, cert := range chain {
if bytes.Equal(sk.RawSubject, cert.RawSubject) && bytes.Equal(sk.RawSubjectPublicKeyInfo, cert.RawSubjectPublicKeyInfo) {
return true
}
}
return false
}
// CertificateSubjectAndKeyInChain returns true if the SubjectAndKey from c is
// found in any certificate in the chain.
func (chain CertificateChain) CertificateSubjectAndKeyInChain(c *Certificate) bool {
for _, cert := range chain {
if bytes.Equal(c.RawSubject, cert.RawSubject) && bytes.Equal(c.RawSubjectPublicKeyInfo, cert.RawSubjectPublicKeyInfo) {
return true
}
}
return false
}
// CertificateInChain returns true if c is in the chain.
func (chain CertificateChain) CertificateInChain(c *Certificate) bool {
for _, cert := range chain {
if bytes.Equal(c.Raw, cert.Raw) {
return true
}
}
return false
}
func (chain CertificateChain) AppendToFreshChain(c *Certificate) CertificateChain {
n := make([]*Certificate, len(chain)+1)
copy(n, chain)
n[len(chain)] = c
return n
}
func (chain CertificateChain) chainID() string {
var parts []string
for _, c := range chain {
parts = append(parts, string(c.FingerprintSHA256))
}
return strings.Join(parts, "")
}

168
vendor/github.com/zmap/zcrypto/x509/ct/serialization.go generated vendored Normal file
View file

@ -0,0 +1,168 @@
package ct
// This file contains selectively chosen snippets of
// github.com/google/certificate-transparency-go@ 5cfe585726ad9d990d4db524d6ce2567b13e2f80
//
// These snippets only perform deserialization for SCTs and are recreated here to prevent pulling in the whole of the ct
// which contains yet another version of x509,asn1 and tls
import (
"encoding/binary"
"errors"
"fmt"
"io"
)
// Variable size structure prefix-header byte lengths
const (
CertificateLengthBytes = 3
PreCertificateLengthBytes = 3
ExtensionsLengthBytes = 2
CertificateChainLengthBytes = 3
SignatureLengthBytes = 2
)
func writeUint(w io.Writer, value uint64, numBytes int) error {
buf := make([]uint8, numBytes)
for i := 0; i < numBytes; i++ {
buf[numBytes-i-1] = uint8(value & 0xff)
value >>= 8
}
if value != 0 {
return errors.New("numBytes was insufficiently large to represent value")
}
if _, err := w.Write(buf); err != nil {
return err
}
return nil
}
func writeVarBytes(w io.Writer, value []byte, numLenBytes int) error {
if err := writeUint(w, uint64(len(value)), numLenBytes); err != nil {
return err
}
if _, err := w.Write(value); err != nil {
return err
}
return nil
}
func readUint(r io.Reader, numBytes int) (uint64, error) {
var l uint64
for i := 0; i < numBytes; i++ {
l <<= 8
var t uint8
if err := binary.Read(r, binary.BigEndian, &t); err != nil {
return 0, err
}
l |= uint64(t)
}
return l, nil
}
// Reads a variable length array of bytes from |r|. |numLenBytes| specifies the
// number of (BigEndian) prefix-bytes which contain the length of the actual
// array data bytes that follow.
// Allocates an array to hold the contents and returns a slice view into it if
// the read was successful, or an error otherwise.
func readVarBytes(r io.Reader, numLenBytes int) ([]byte, error) {
switch {
case numLenBytes > 8:
return nil, fmt.Errorf("numLenBytes too large (%d)", numLenBytes)
case numLenBytes == 0:
return nil, errors.New("numLenBytes should be > 0")
}
l, err := readUint(r, numLenBytes)
if err != nil {
return nil, err
}
data := make([]byte, l)
if n, err := io.ReadFull(r, data); err != nil {
if err == io.EOF || err == io.ErrUnexpectedEOF {
return nil, fmt.Errorf("short read: expected %d but got %d", l, n)
}
return nil, err
}
return data, nil
}
// UnmarshalDigitallySigned reconstructs a DigitallySigned structure from a Reader
func UnmarshalDigitallySigned(r io.Reader) (*DigitallySigned, error) {
var h byte
if err := binary.Read(r, binary.BigEndian, &h); err != nil {
return nil, fmt.Errorf("failed to read HashAlgorithm: %v", err)
}
var s byte
if err := binary.Read(r, binary.BigEndian, &s); err != nil {
return nil, fmt.Errorf("failed to read SignatureAlgorithm: %v", err)
}
sig, err := readVarBytes(r, SignatureLengthBytes)
if err != nil {
return nil, fmt.Errorf("failed to read Signature bytes: %v", err)
}
return &DigitallySigned{
HashAlgorithm: HashAlgorithm(h),
SignatureAlgorithm: SignatureAlgorithm(s),
Signature: sig,
}, nil
}
func marshalDigitallySignedHere(ds DigitallySigned, here []byte) ([]byte, error) {
sigLen := len(ds.Signature)
dsOutLen := 2 + SignatureLengthBytes + sigLen
if here == nil {
here = make([]byte, dsOutLen)
}
if len(here) < dsOutLen {
return nil, ErrNotEnoughBuffer
}
here = here[0:dsOutLen]
here[0] = byte(ds.HashAlgorithm)
here[1] = byte(ds.SignatureAlgorithm)
binary.BigEndian.PutUint16(here[2:4], uint16(sigLen))
copy(here[4:], ds.Signature)
return here, nil
}
// MarshalDigitallySigned marshalls a DigitallySigned structure into a byte array
func MarshalDigitallySigned(ds DigitallySigned) ([]byte, error) {
return marshalDigitallySignedHere(ds, nil)
}
func deserializeSCTV1(r io.Reader, sct *SignedCertificateTimestamp) error {
if err := binary.Read(r, binary.BigEndian, &sct.LogID); err != nil {
return err
}
if err := binary.Read(r, binary.BigEndian, &sct.Timestamp); err != nil {
return err
}
ext, err := readVarBytes(r, ExtensionsLengthBytes)
if err != nil {
return err
}
sct.Extensions = ext
ds, err := UnmarshalDigitallySigned(r)
if err != nil {
return err
}
sct.Signature = *ds
return nil
}
func DeserializeSCT(r io.Reader) (*SignedCertificateTimestamp, error) {
var sct SignedCertificateTimestamp
if err := binary.Read(r, binary.BigEndian, &sct.SCTVersion); err != nil {
return nil, err
}
switch sct.SCTVersion {
case V1:
return &sct, deserializeSCTV1(r, &sct)
default:
return nil, fmt.Errorf("unknown SCT version %d", sct.SCTVersion)
}
}

229
vendor/github.com/zmap/zcrypto/x509/ct/types.go generated vendored Normal file
View file

@ -0,0 +1,229 @@
package ct
// This file contains selectively chosen snippets of
// github.com/google/certificate-transparency-go@ 5cfe585726ad9d990d4db524d6ce2567b13e2f80
//
// These snippets only perform deserialization for SCTs and are recreated here to prevent pulling in the whole of the ct
// which contains yet another version of x509,asn1 and tls
import (
"bytes"
"crypto/sha256"
"encoding/base64"
"encoding/json"
"fmt"
)
// CTExtensions is a representation of the raw bytes of any CtExtension
// structure (see section 3.2)
type CTExtensions []byte
// SHA256Hash represents the output from the SHA256 hash function.
type SHA256Hash [sha256.Size]byte
// FromBase64String populates the SHA256 struct with the contents of the base64 data passed in.
func (s *SHA256Hash) FromBase64String(b64 string) error {
bs, err := base64.StdEncoding.DecodeString(b64)
if err != nil {
return fmt.Errorf("failed to unbase64 LogID: %v", err)
}
if len(bs) != sha256.Size {
return fmt.Errorf("invalid SHA256 length, expected 32 but got %d", len(bs))
}
copy(s[:], bs)
return nil
}
// Base64String returns the base64 representation of this SHA256Hash.
func (s SHA256Hash) Base64String() string {
return base64.StdEncoding.EncodeToString(s[:])
}
// MarshalJSON implements the json.Marshaller interface for SHA256Hash.
func (s SHA256Hash) MarshalJSON() ([]byte, error) {
return []byte(`"` + s.Base64String() + `"`), nil
}
// UnmarshalJSON implements the json.Unmarshaller interface.
func (s *SHA256Hash) UnmarshalJSON(b []byte) error {
var content string
if err := json.Unmarshal(b, &content); err != nil {
return fmt.Errorf("failed to unmarshal SHA256Hash: %v", err)
}
return s.FromBase64String(content)
}
// HashAlgorithm from the DigitallySigned struct
type HashAlgorithm byte
// HashAlgorithm constants
const (
None HashAlgorithm = 0
MD5 HashAlgorithm = 1
SHA1 HashAlgorithm = 2
SHA224 HashAlgorithm = 3
SHA256 HashAlgorithm = 4
SHA384 HashAlgorithm = 5
SHA512 HashAlgorithm = 6
)
func (h HashAlgorithm) String() string {
switch h {
case None:
return "None"
case MD5:
return "MD5"
case SHA1:
return "SHA1"
case SHA224:
return "SHA224"
case SHA256:
return "SHA256"
case SHA384:
return "SHA384"
case SHA512:
return "SHA512"
default:
return fmt.Sprintf("UNKNOWN(%d)", h)
}
}
// SignatureAlgorithm from the the DigitallySigned struct
type SignatureAlgorithm byte
// SignatureAlgorithm constants
const (
Anonymous SignatureAlgorithm = 0
RSA SignatureAlgorithm = 1
DSA SignatureAlgorithm = 2
ECDSA SignatureAlgorithm = 3
)
func (s SignatureAlgorithm) String() string {
switch s {
case Anonymous:
return "Anonymous"
case RSA:
return "RSA"
case DSA:
return "DSA"
case ECDSA:
return "ECDSA"
default:
return fmt.Sprintf("UNKNOWN(%d)", s)
}
}
// DigitallySigned represents an RFC5246 DigitallySigned structure
type DigitallySigned struct {
HashAlgorithm HashAlgorithm
SignatureAlgorithm SignatureAlgorithm
Signature []byte
}
// FromBase64String populates the DigitallySigned structure from the base64 data passed in.
// Returns an error if the base64 data is invalid.
func (d *DigitallySigned) FromBase64String(b64 string) error {
raw, err := base64.StdEncoding.DecodeString(b64)
if err != nil {
return fmt.Errorf("failed to unbase64 DigitallySigned: %v", err)
}
ds, err := UnmarshalDigitallySigned(bytes.NewReader(raw))
if err != nil {
return fmt.Errorf("failed to unmarshal DigitallySigned: %v", err)
}
*d = *ds
return nil
}
// Base64String returns the base64 representation of the DigitallySigned struct.
func (d DigitallySigned) Base64String() (string, error) {
b, err := MarshalDigitallySigned(d)
if err != nil {
return "", err
}
return base64.StdEncoding.EncodeToString(b), nil
}
// MarshalJSON implements the json.Marshaller interface.
func (d DigitallySigned) MarshalJSON() ([]byte, error) {
b64, err := d.Base64String()
if err != nil {
return []byte{}, err
}
return []byte(`"` + b64 + `"`), nil
}
// UnmarshalJSON implements the json.Unmarshaler interface.
func (d *DigitallySigned) UnmarshalJSON(b []byte) error {
var content string
if err := json.Unmarshal(b, &content); err != nil {
return fmt.Errorf("failed to unmarshal DigitallySigned: %v", err)
}
return d.FromBase64String(content)
}
// Version represents the Version enum from section 3.2 of the RFC:
// enum { v1(0), (255) } Version;
type Version uint8
func (v Version) String() string {
switch v {
case V1:
return "V1"
default:
return fmt.Sprintf("UnknownVersion(%d)", v)
}
}
// CT Version constants, see section 3.2 of the RFC.
const (
V1 Version = 0
)
// SignedCertificateTimestamp represents the structure returned by the
// add-chain and add-pre-chain methods after base64 decoding. (see RFC sections
// 3.2 ,4.1 and 4.2)
type SignedCertificateTimestamp struct {
SCTVersion Version `json:"version"` // The version of the protocol to which the SCT conforms
LogID SHA256Hash `json:"log_id"` // the SHA-256 hash of the log's public key, calculated over
// the DER encoding of the key represented as SubjectPublicKeyInfo.
Timestamp uint64 `json:"timestamp,omitempty"` // Timestamp (in ms since unix epoc) at which the SCT was issued. NOTE: When this is serialized, the output is in seconds, not milliseconds.
Extensions CTExtensions `json:"extensions,omitempty"` // For future extensions to the protocol
Signature DigitallySigned `json:"signature"` // The Log's signature for this SCT
}
// Copied from ct/types.go 2018/06/15 to deal with BQ timestamp overflow; output
// is expected to be seconds, not milliseconds.
type auxSignedCertificateTimestamp SignedCertificateTimestamp
const kMaxTimestamp = 253402300799
// MarshalJSON implements the JSON.Marshaller interface.
func (sct *SignedCertificateTimestamp) MarshalJSON() ([]byte, error) {
aux := auxSignedCertificateTimestamp(*sct)
aux.Timestamp = sct.Timestamp / 1000 // convert ms to sec
if aux.Timestamp > kMaxTimestamp {
aux.Timestamp = 0
}
return json.Marshal(&aux)
}
type sctError int
// Preallocate errors for performance
var (
ErrInvalidVersion error = sctError(1)
ErrNotEnoughBuffer error = sctError(2)
)
func (e sctError) Error() string {
switch e {
case ErrInvalidVersion:
return "invalid SCT version detected"
case ErrNotEnoughBuffer:
return "provided buffer was too small"
default:
return "unknown error"
}
}

65
vendor/github.com/zmap/zcrypto/x509/example.json generated vendored Normal file
View file

@ -0,0 +1,65 @@
{
"domain": null,
"certificate": {
"version": 3,
"serial_number": 123893,
"signature_algorithm": {
"id": 123,
"name": "SHA1"
},
"issuer": {
"common_name": "Starfield CA",
"attributes": [
{ "organization": "Startfield" },
{ "location": "Scottsdale" },
{ "state": "Arizona" },
{ "country": "US" }
]
},
"validity": {
"start": "20140102",
"end": "20150102",
"length" :8760
},
"subject": {
"common_name": "*.tools.ieft.org",
"attributes": [
{ "organization_unit": "Domain Control Validated" }
]
},
"subject_key_info": {
"algorithm": {
"id": 234,
"name": "RSA"
},
"key": {
"modulus": "base64encodedmodulus",
"exponent": 65537
}
},
"extensions": [
{
"id": 345,
"name": "Certificate Basic Constraints",
"is_ca": false
},
{
"id": 456,
"name": "Alt Names",
"alt_names": [
"*.tools.ietf.org",
"tools.ietf.org"
]
}
]
},
"signature_algorithm": {
"id": 123,
"name": "SHA1"
},
"signature": {
"value": "base64encodedsignature",
"is_valid": true,
"matches_domain": null
}
}

View file

@ -0,0 +1,679 @@
// Created by extended_key_usage_gen; DO NOT EDIT
// 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 x509
import (
"encoding/asn1"
)
const (
OID_EKU_APPLE_CODE_SIGNING = "1.2.840.113635.100.4.1"
OID_EKU_APPLE_CODE_SIGNING_DEVELOPMENT = "1.2.840.113635.100.4.1.1"
OID_EKU_APPLE_SOFTWARE_UPDATE_SIGNING = "1.2.840.113635.100.4.1.2"
OID_EKU_APPLE_CODE_SIGNING_THIRD_PARTY = "1.2.840.113635.100.4.1.3"
OID_EKU_APPLE_RESOURCE_SIGNING = "1.2.840.113635.100.4.1.4"
OID_EKU_APPLE_ICHAT_SIGNING = "1.2.840.113635.100.4.2"
OID_EKU_APPLE_ICHAT_ENCRYPTION = "1.2.840.113635.100.4.3"
OID_EKU_APPLE_SYSTEM_IDENTITY = "1.2.840.113635.100.4.4"
OID_EKU_APPLE_CRYPTO_ENV = "1.2.840.113635.100.4.5"
OID_EKU_APPLE_CRYPTO_PRODUCTION_ENV = "1.2.840.113635.100.4.5.1"
OID_EKU_APPLE_CRYPTO_MAINTENANCE_ENV = "1.2.840.113635.100.4.5.2"
OID_EKU_APPLE_CRYPTO_TEST_ENV = "1.2.840.113635.100.4.5.3"
OID_EKU_APPLE_CRYPTO_DEVELOPMENT_ENV = "1.2.840.113635.100.4.5.4"
OID_EKU_APPLE_CRYPTO_QOS = "1.2.840.113635.100.4.6"
OID_EKU_APPLE_CRYPTO_TIER0_QOS = "1.2.840.113635.100.4.6.1"
OID_EKU_APPLE_CRYPTO_TIER1_QOS = "1.2.840.113635.100.4.6.2"
OID_EKU_APPLE_CRYPTO_TIER2_QOS = "1.2.840.113635.100.4.6.3"
OID_EKU_APPLE_CRYPTO_TIER3_QOS = "1.2.840.113635.100.4.6.4"
OID_EKU_MICROSOFT_CERT_TRUST_LIST_SIGNING = "1.3.6.1.4.1.311.10.3.1"
OID_EKU_MICROSOFT_QUALIFIED_SUBORDINATE = "1.3.6.1.4.1.311.10.3.10"
OID_EKU_MICROSOFT_KEY_RECOVERY_3 = "1.3.6.1.4.1.311.10.3.11"
OID_EKU_MICROSOFT_DOCUMENT_SIGNING = "1.3.6.1.4.1.311.10.3.12"
OID_EKU_MICROSOFT_LIFETIME_SIGNING = "1.3.6.1.4.1.311.10.3.13"
OID_EKU_MICROSOFT_MOBILE_DEVICE_SOFTWARE = "1.3.6.1.4.1.311.10.3.14"
OID_EKU_MICROSOFT_SMART_DISPLAY = "1.3.6.1.4.1.311.10.3.15"
OID_EKU_MICROSOFT_CSP_SIGNATURE = "1.3.6.1.4.1.311.10.3.16"
OID_EKU_MICROSOFT_TIMESTAMP_SIGNING = "1.3.6.1.4.1.311.10.3.2"
OID_EKU_MICROSOFT_SERVER_GATED_CRYPTO = "1.3.6.1.4.1.311.10.3.3"
OID_EKU_MICROSOFT_SGC_SERIALIZED = "1.3.6.1.4.1.311.10.3.3.1"
OID_EKU_MICROSOFT_ENCRYPTED_FILE_SYSTEM = "1.3.6.1.4.1.311.10.3.4"
OID_EKU_MICROSOFT_EFS_RECOVERY = "1.3.6.1.4.1.311.10.3.4.1"
OID_EKU_MICROSOFT_WHQL_CRYPTO = "1.3.6.1.4.1.311.10.3.5"
OID_EKU_MICROSOFT_NT5_CRYPTO = "1.3.6.1.4.1.311.10.3.6"
OID_EKU_MICROSOFT_OEM_WHQL_CRYPTO = "1.3.6.1.4.1.311.10.3.7"
OID_EKU_MICROSOFT_EMBEDDED_NT_CRYPTO = "1.3.6.1.4.1.311.10.3.8"
OID_EKU_MICROSOFT_ROOT_LIST_SIGNER = "1.3.6.1.4.1.311.10.3.9"
OID_EKU_MICROSOFT_DRM = "1.3.6.1.4.1.311.10.5.1"
OID_EKU_MICROSOFT_DRM_INDIVIDUALIZATION = "1.3.6.1.4.1.311.10.5.2"
OID_EKU_MICROSOFT_LICENSES = "1.3.6.1.4.1.311.10.5.3"
OID_EKU_MICROSOFT_LICENSE_SERVER = "1.3.6.1.4.1.311.10.5.4"
OID_EKU_MICROSOFT_ENROLLMENT_AGENT = "1.3.6.1.4.1.311.20.2.1"
OID_EKU_MICROSOFT_SMARTCARD_LOGON = "1.3.6.1.4.1.311.20.2.2"
OID_EKU_MICROSOFT_CA_EXCHANGE = "1.3.6.1.4.1.311.21.5"
OID_EKU_MICROSOFT_KEY_RECOVERY_21 = "1.3.6.1.4.1.311.21.6"
OID_EKU_MICROSOFT_SYSTEM_HEALTH = "1.3.6.1.4.1.311.47.1.1"
OID_EKU_MICROSOFT_SYSTEM_HEALTH_LOOPHOLE = "1.3.6.1.4.1.311.47.1.3"
OID_EKU_MICROSOFT_KERNEL_MODE_CODE_SIGNING = "1.3.6.1.4.1.311.61.1.1"
OID_EKU_SERVER_AUTH = "1.3.6.1.5.5.7.3.1"
OID_EKU_DVCS = "1.3.6.1.5.5.7.3.10"
OID_EKU_SBGP_CERT_AA_SERVICE_AUTH = "1.3.6.1.5.5.7.3.11"
OID_EKU_EAP_OVER_PPP = "1.3.6.1.5.5.7.3.13"
OID_EKU_EAP_OVER_LAN = "1.3.6.1.5.5.7.3.14"
OID_EKU_CLIENT_AUTH = "1.3.6.1.5.5.7.3.2"
OID_EKU_CODE_SIGNING = "1.3.6.1.5.5.7.3.3"
OID_EKU_EMAIL_PROTECTION = "1.3.6.1.5.5.7.3.4"
OID_EKU_IPSEC_END_SYSTEM = "1.3.6.1.5.5.7.3.5"
OID_EKU_IPSEC_TUNNEL = "1.3.6.1.5.5.7.3.6"
OID_EKU_IPSEC_USER = "1.3.6.1.5.5.7.3.7"
OID_EKU_TIME_STAMPING = "1.3.6.1.5.5.7.3.8"
OID_EKU_OCSP_SIGNING = "1.3.6.1.5.5.7.3.9"
OID_EKU_IPSEC_INTERMEDIATE_SYSTEM_USAGE = "1.3.6.1.5.5.8.2.2"
OID_EKU_NETSCAPE_SERVER_GATED_CRYPTO = "2.16.840.1.113730.4.1"
OID_EKU_ANY = "2.5.29.37.0"
)
var (
oidExtKeyUsageAppleCodeSigning = asn1.ObjectIdentifier{1, 2, 840, 113635, 100, 4, 1}
oidExtKeyUsageAppleCodeSigningDevelopment = asn1.ObjectIdentifier{1, 2, 840, 113635, 100, 4, 1, 1}
oidExtKeyUsageAppleSoftwareUpdateSigning = asn1.ObjectIdentifier{1, 2, 840, 113635, 100, 4, 1, 2}
oidExtKeyUsageAppleCodeSigningThirdParty = asn1.ObjectIdentifier{1, 2, 840, 113635, 100, 4, 1, 3}
oidExtKeyUsageAppleResourceSigning = asn1.ObjectIdentifier{1, 2, 840, 113635, 100, 4, 1, 4}
oidExtKeyUsageAppleIchatSigning = asn1.ObjectIdentifier{1, 2, 840, 113635, 100, 4, 2}
oidExtKeyUsageAppleIchatEncryption = asn1.ObjectIdentifier{1, 2, 840, 113635, 100, 4, 3}
oidExtKeyUsageAppleSystemIdentity = asn1.ObjectIdentifier{1, 2, 840, 113635, 100, 4, 4}
oidExtKeyUsageAppleCryptoEnv = asn1.ObjectIdentifier{1, 2, 840, 113635, 100, 4, 5}
oidExtKeyUsageAppleCryptoProductionEnv = asn1.ObjectIdentifier{1, 2, 840, 113635, 100, 4, 5, 1}
oidExtKeyUsageAppleCryptoMaintenanceEnv = asn1.ObjectIdentifier{1, 2, 840, 113635, 100, 4, 5, 2}
oidExtKeyUsageAppleCryptoTestEnv = asn1.ObjectIdentifier{1, 2, 840, 113635, 100, 4, 5, 3}
oidExtKeyUsageAppleCryptoDevelopmentEnv = asn1.ObjectIdentifier{1, 2, 840, 113635, 100, 4, 5, 4}
oidExtKeyUsageAppleCryptoQos = asn1.ObjectIdentifier{1, 2, 840, 113635, 100, 4, 6}
oidExtKeyUsageAppleCryptoTier0Qos = asn1.ObjectIdentifier{1, 2, 840, 113635, 100, 4, 6, 1}
oidExtKeyUsageAppleCryptoTier1Qos = asn1.ObjectIdentifier{1, 2, 840, 113635, 100, 4, 6, 2}
oidExtKeyUsageAppleCryptoTier2Qos = asn1.ObjectIdentifier{1, 2, 840, 113635, 100, 4, 6, 3}
oidExtKeyUsageAppleCryptoTier3Qos = asn1.ObjectIdentifier{1, 2, 840, 113635, 100, 4, 6, 4}
oidExtKeyUsageMicrosoftCertTrustListSigning = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 10, 3, 1}
oidExtKeyUsageMicrosoftQualifiedSubordinate = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 10, 3, 10}
oidExtKeyUsageMicrosoftKeyRecovery3 = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 10, 3, 11}
oidExtKeyUsageMicrosoftDocumentSigning = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 10, 3, 12}
oidExtKeyUsageMicrosoftLifetimeSigning = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 10, 3, 13}
oidExtKeyUsageMicrosoftMobileDeviceSoftware = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 10, 3, 14}
oidExtKeyUsageMicrosoftSmartDisplay = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 10, 3, 15}
oidExtKeyUsageMicrosoftCspSignature = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 10, 3, 16}
oidExtKeyUsageMicrosoftTimestampSigning = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 10, 3, 2}
oidExtKeyUsageMicrosoftServerGatedCrypto = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 10, 3, 3}
oidExtKeyUsageMicrosoftSgcSerialized = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 10, 3, 3, 1}
oidExtKeyUsageMicrosoftEncryptedFileSystem = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 10, 3, 4}
oidExtKeyUsageMicrosoftEfsRecovery = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 10, 3, 4, 1}
oidExtKeyUsageMicrosoftWhqlCrypto = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 10, 3, 5}
oidExtKeyUsageMicrosoftNt5Crypto = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 10, 3, 6}
oidExtKeyUsageMicrosoftOemWhqlCrypto = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 10, 3, 7}
oidExtKeyUsageMicrosoftEmbeddedNtCrypto = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 10, 3, 8}
oidExtKeyUsageMicrosoftRootListSigner = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 10, 3, 9}
oidExtKeyUsageMicrosoftDrm = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 10, 5, 1}
oidExtKeyUsageMicrosoftDrmIndividualization = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 10, 5, 2}
oidExtKeyUsageMicrosoftLicenses = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 10, 5, 3}
oidExtKeyUsageMicrosoftLicenseServer = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 10, 5, 4}
oidExtKeyUsageMicrosoftEnrollmentAgent = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 20, 2, 1}
oidExtKeyUsageMicrosoftSmartcardLogon = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 20, 2, 2}
oidExtKeyUsageMicrosoftCaExchange = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 21, 5}
oidExtKeyUsageMicrosoftKeyRecovery21 = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 21, 6}
oidExtKeyUsageMicrosoftSystemHealth = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 47, 1, 1}
oidExtKeyUsageMicrosoftSystemHealthLoophole = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 47, 1, 3}
oidExtKeyUsageMicrosoftKernelModeCodeSigning = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 61, 1, 1}
oidExtKeyUsageServerAuth = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 1}
oidExtKeyUsageDvcs = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 10}
oidExtKeyUsageSbgpCertAaServiceAuth = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 11}
oidExtKeyUsageEapOverPpp = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 13}
oidExtKeyUsageEapOverLan = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 14}
oidExtKeyUsageClientAuth = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 2}
oidExtKeyUsageCodeSigning = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 3}
oidExtKeyUsageEmailProtection = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 4}
oidExtKeyUsageIpsecEndSystem = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 5}
oidExtKeyUsageIpsecTunnel = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 6}
oidExtKeyUsageIpsecUser = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 7}
oidExtKeyUsageTimeStamping = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 8}
oidExtKeyUsageOcspSigning = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 9}
oidExtKeyUsageIpsecIntermediateSystemUsage = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 8, 2, 2}
oidExtKeyUsageNetscapeServerGatedCrypto = asn1.ObjectIdentifier{2, 16, 840, 1, 113730, 4, 1}
oidExtKeyUsageAny = asn1.ObjectIdentifier{2, 5, 29, 37, 0}
)
const (
ExtKeyUsageAppleCodeSigning ExtKeyUsage = iota
ExtKeyUsageAppleCodeSigningDevelopment
ExtKeyUsageAppleSoftwareUpdateSigning
ExtKeyUsageAppleCodeSigningThirdParty
ExtKeyUsageAppleResourceSigning
ExtKeyUsageAppleIchatSigning
ExtKeyUsageAppleIchatEncryption
ExtKeyUsageAppleSystemIdentity
ExtKeyUsageAppleCryptoEnv
ExtKeyUsageAppleCryptoProductionEnv
ExtKeyUsageAppleCryptoMaintenanceEnv
ExtKeyUsageAppleCryptoTestEnv
ExtKeyUsageAppleCryptoDevelopmentEnv
ExtKeyUsageAppleCryptoQos
ExtKeyUsageAppleCryptoTier0Qos
ExtKeyUsageAppleCryptoTier1Qos
ExtKeyUsageAppleCryptoTier2Qos
ExtKeyUsageAppleCryptoTier3Qos
ExtKeyUsageMicrosoftCertTrustListSigning
ExtKeyUsageMicrosoftQualifiedSubordinate
ExtKeyUsageMicrosoftKeyRecovery3
ExtKeyUsageMicrosoftDocumentSigning
ExtKeyUsageMicrosoftLifetimeSigning
ExtKeyUsageMicrosoftMobileDeviceSoftware
ExtKeyUsageMicrosoftSmartDisplay
ExtKeyUsageMicrosoftCspSignature
ExtKeyUsageMicrosoftTimestampSigning
ExtKeyUsageMicrosoftServerGatedCrypto
ExtKeyUsageMicrosoftSgcSerialized
ExtKeyUsageMicrosoftEncryptedFileSystem
ExtKeyUsageMicrosoftEfsRecovery
ExtKeyUsageMicrosoftWhqlCrypto
ExtKeyUsageMicrosoftNt5Crypto
ExtKeyUsageMicrosoftOemWhqlCrypto
ExtKeyUsageMicrosoftEmbeddedNtCrypto
ExtKeyUsageMicrosoftRootListSigner
ExtKeyUsageMicrosoftDrm
ExtKeyUsageMicrosoftDrmIndividualization
ExtKeyUsageMicrosoftLicenses
ExtKeyUsageMicrosoftLicenseServer
ExtKeyUsageMicrosoftEnrollmentAgent
ExtKeyUsageMicrosoftSmartcardLogon
ExtKeyUsageMicrosoftCaExchange
ExtKeyUsageMicrosoftKeyRecovery21
ExtKeyUsageMicrosoftSystemHealth
ExtKeyUsageMicrosoftSystemHealthLoophole
ExtKeyUsageMicrosoftKernelModeCodeSigning
ExtKeyUsageServerAuth
ExtKeyUsageDvcs
ExtKeyUsageSbgpCertAaServiceAuth
ExtKeyUsageEapOverPpp
ExtKeyUsageEapOverLan
ExtKeyUsageClientAuth
ExtKeyUsageCodeSigning
ExtKeyUsageEmailProtection
ExtKeyUsageIpsecEndSystem
ExtKeyUsageIpsecTunnel
ExtKeyUsageIpsecUser
ExtKeyUsageTimeStamping
ExtKeyUsageOcspSigning
ExtKeyUsageIpsecIntermediateSystemUsage
ExtKeyUsageNetscapeServerGatedCrypto
ExtKeyUsageAny
)
type auxExtendedKeyUsage struct {
AppleCodeSigning bool `json:"apple_code_signing,omitempty" oid:"1.2.840.113635.100.4.1"`
AppleCodeSigningDevelopment bool `json:"apple_code_signing_development,omitempty" oid:"1.2.840.113635.100.4.1.1"`
AppleSoftwareUpdateSigning bool `json:"apple_software_update_signing,omitempty" oid:"1.2.840.113635.100.4.1.2"`
AppleCodeSigningThirdParty bool `json:"apple_code_signing_third_party,omitempty" oid:"1.2.840.113635.100.4.1.3"`
AppleResourceSigning bool `json:"apple_resource_signing,omitempty" oid:"1.2.840.113635.100.4.1.4"`
AppleIchatSigning bool `json:"apple_ichat_signing,omitempty" oid:"1.2.840.113635.100.4.2"`
AppleIchatEncryption bool `json:"apple_ichat_encryption,omitempty" oid:"1.2.840.113635.100.4.3"`
AppleSystemIdentity bool `json:"apple_system_identity,omitempty" oid:"1.2.840.113635.100.4.4"`
AppleCryptoEnv bool `json:"apple_crypto_env,omitempty" oid:"1.2.840.113635.100.4.5"`
AppleCryptoProductionEnv bool `json:"apple_crypto_production_env,omitempty" oid:"1.2.840.113635.100.4.5.1"`
AppleCryptoMaintenanceEnv bool `json:"apple_crypto_maintenance_env,omitempty" oid:"1.2.840.113635.100.4.5.2"`
AppleCryptoTestEnv bool `json:"apple_crypto_test_env,omitempty" oid:"1.2.840.113635.100.4.5.3"`
AppleCryptoDevelopmentEnv bool `json:"apple_crypto_development_env,omitempty" oid:"1.2.840.113635.100.4.5.4"`
AppleCryptoQos bool `json:"apple_crypto_qos,omitempty" oid:"1.2.840.113635.100.4.6"`
AppleCryptoTier0Qos bool `json:"apple_crypto_tier0_qos,omitempty" oid:"1.2.840.113635.100.4.6.1"`
AppleCryptoTier1Qos bool `json:"apple_crypto_tier1_qos,omitempty" oid:"1.2.840.113635.100.4.6.2"`
AppleCryptoTier2Qos bool `json:"apple_crypto_tier2_qos,omitempty" oid:"1.2.840.113635.100.4.6.3"`
AppleCryptoTier3Qos bool `json:"apple_crypto_tier3_qos,omitempty" oid:"1.2.840.113635.100.4.6.4"`
MicrosoftCertTrustListSigning bool `json:"microsoft_cert_trust_list_signing,omitempty" oid:"1.3.6.1.4.1.311.10.3.1"`
MicrosoftQualifiedSubordinate bool `json:"microsoft_qualified_subordinate,omitempty" oid:"1.3.6.1.4.1.311.10.3.10"`
MicrosoftKeyRecovery3 bool `json:"microsoft_key_recovery_3,omitempty" oid:"1.3.6.1.4.1.311.10.3.11"`
MicrosoftDocumentSigning bool `json:"microsoft_document_signing,omitempty" oid:"1.3.6.1.4.1.311.10.3.12"`
MicrosoftLifetimeSigning bool `json:"microsoft_lifetime_signing,omitempty" oid:"1.3.6.1.4.1.311.10.3.13"`
MicrosoftMobileDeviceSoftware bool `json:"microsoft_mobile_device_software,omitempty" oid:"1.3.6.1.4.1.311.10.3.14"`
MicrosoftSmartDisplay bool `json:"microsoft_smart_display,omitempty" oid:"1.3.6.1.4.1.311.10.3.15"`
MicrosoftCspSignature bool `json:"microsoft_csp_signature,omitempty" oid:"1.3.6.1.4.1.311.10.3.16"`
MicrosoftTimestampSigning bool `json:"microsoft_timestamp_signing,omitempty" oid:"1.3.6.1.4.1.311.10.3.2"`
MicrosoftServerGatedCrypto bool `json:"microsoft_server_gated_crypto,omitempty" oid:"1.3.6.1.4.1.311.10.3.3"`
MicrosoftSgcSerialized bool `json:"microsoft_sgc_serialized,omitempty" oid:"1.3.6.1.4.1.311.10.3.3.1"`
MicrosoftEncryptedFileSystem bool `json:"microsoft_encrypted_file_system,omitempty" oid:"1.3.6.1.4.1.311.10.3.4"`
MicrosoftEfsRecovery bool `json:"microsoft_efs_recovery,omitempty" oid:"1.3.6.1.4.1.311.10.3.4.1"`
MicrosoftWhqlCrypto bool `json:"microsoft_whql_crypto,omitempty" oid:"1.3.6.1.4.1.311.10.3.5"`
MicrosoftNt5Crypto bool `json:"microsoft_nt5_crypto,omitempty" oid:"1.3.6.1.4.1.311.10.3.6"`
MicrosoftOemWhqlCrypto bool `json:"microsoft_oem_whql_crypto,omitempty" oid:"1.3.6.1.4.1.311.10.3.7"`
MicrosoftEmbeddedNtCrypto bool `json:"microsoft_embedded_nt_crypto,omitempty" oid:"1.3.6.1.4.1.311.10.3.8"`
MicrosoftRootListSigner bool `json:"microsoft_root_list_signer,omitempty" oid:"1.3.6.1.4.1.311.10.3.9"`
MicrosoftDrm bool `json:"microsoft_drm,omitempty" oid:"1.3.6.1.4.1.311.10.5.1"`
MicrosoftDrmIndividualization bool `json:"microsoft_drm_individualization,omitempty" oid:"1.3.6.1.4.1.311.10.5.2"`
MicrosoftLicenses bool `json:"microsoft_licenses,omitempty" oid:"1.3.6.1.4.1.311.10.5.3"`
MicrosoftLicenseServer bool `json:"microsoft_license_server,omitempty" oid:"1.3.6.1.4.1.311.10.5.4"`
MicrosoftEnrollmentAgent bool `json:"microsoft_enrollment_agent,omitempty" oid:"1.3.6.1.4.1.311.20.2.1"`
MicrosoftSmartcardLogon bool `json:"microsoft_smartcard_logon,omitempty" oid:"1.3.6.1.4.1.311.20.2.2"`
MicrosoftCaExchange bool `json:"microsoft_ca_exchange,omitempty" oid:"1.3.6.1.4.1.311.21.5"`
MicrosoftKeyRecovery21 bool `json:"microsoft_key_recovery_21,omitempty" oid:"1.3.6.1.4.1.311.21.6"`
MicrosoftSystemHealth bool `json:"microsoft_system_health,omitempty" oid:"1.3.6.1.4.1.311.47.1.1"`
MicrosoftSystemHealthLoophole bool `json:"microsoft_system_health_loophole,omitempty" oid:"1.3.6.1.4.1.311.47.1.3"`
MicrosoftKernelModeCodeSigning bool `json:"microsoft_kernel_mode_code_signing,omitempty" oid:"1.3.6.1.4.1.311.61.1.1"`
ServerAuth bool `json:"server_auth,omitempty" oid:"1.3.6.1.5.5.7.3.1"`
Dvcs bool `json:"dvcs,omitempty" oid:"1.3.6.1.5.5.7.3.10"`
SbgpCertAaServiceAuth bool `json:"sbgp_cert_aa_service_auth,omitempty" oid:"1.3.6.1.5.5.7.3.11"`
EapOverPpp bool `json:"eap_over_ppp,omitempty" oid:"1.3.6.1.5.5.7.3.13"`
EapOverLan bool `json:"eap_over_lan,omitempty" oid:"1.3.6.1.5.5.7.3.14"`
ClientAuth bool `json:"client_auth,omitempty" oid:"1.3.6.1.5.5.7.3.2"`
CodeSigning bool `json:"code_signing,omitempty" oid:"1.3.6.1.5.5.7.3.3"`
EmailProtection bool `json:"email_protection,omitempty" oid:"1.3.6.1.5.5.7.3.4"`
IpsecEndSystem bool `json:"ipsec_end_system,omitempty" oid:"1.3.6.1.5.5.7.3.5"`
IpsecTunnel bool `json:"ipsec_tunnel,omitempty" oid:"1.3.6.1.5.5.7.3.6"`
IpsecUser bool `json:"ipsec_user,omitempty" oid:"1.3.6.1.5.5.7.3.7"`
TimeStamping bool `json:"time_stamping,omitempty" oid:"1.3.6.1.5.5.7.3.8"`
OcspSigning bool `json:"ocsp_signing,omitempty" oid:"1.3.6.1.5.5.7.3.9"`
IpsecIntermediateSystemUsage bool `json:"ipsec_intermediate_system_usage,omitempty" oid:"1.3.6.1.5.5.8.2.2"`
NetscapeServerGatedCrypto bool `json:"netscape_server_gated_crypto,omitempty" oid:"2.16.840.1.113730.4.1"`
Any bool `json:"any,omitempty" oid:"2.5.29.37.0"`
Unknown []string `json:"unknown,omitempty"`
}
func (aux *auxExtendedKeyUsage) populateFromASN1(oid asn1.ObjectIdentifier) {
s := oid.String()
switch s {
case OID_EKU_APPLE_CODE_SIGNING:
aux.AppleCodeSigning = true
case OID_EKU_APPLE_CODE_SIGNING_DEVELOPMENT:
aux.AppleCodeSigningDevelopment = true
case OID_EKU_APPLE_SOFTWARE_UPDATE_SIGNING:
aux.AppleSoftwareUpdateSigning = true
case OID_EKU_APPLE_CODE_SIGNING_THIRD_PARTY:
aux.AppleCodeSigningThirdParty = true
case OID_EKU_APPLE_RESOURCE_SIGNING:
aux.AppleResourceSigning = true
case OID_EKU_APPLE_ICHAT_SIGNING:
aux.AppleIchatSigning = true
case OID_EKU_APPLE_ICHAT_ENCRYPTION:
aux.AppleIchatEncryption = true
case OID_EKU_APPLE_SYSTEM_IDENTITY:
aux.AppleSystemIdentity = true
case OID_EKU_APPLE_CRYPTO_ENV:
aux.AppleCryptoEnv = true
case OID_EKU_APPLE_CRYPTO_PRODUCTION_ENV:
aux.AppleCryptoProductionEnv = true
case OID_EKU_APPLE_CRYPTO_MAINTENANCE_ENV:
aux.AppleCryptoMaintenanceEnv = true
case OID_EKU_APPLE_CRYPTO_TEST_ENV:
aux.AppleCryptoTestEnv = true
case OID_EKU_APPLE_CRYPTO_DEVELOPMENT_ENV:
aux.AppleCryptoDevelopmentEnv = true
case OID_EKU_APPLE_CRYPTO_QOS:
aux.AppleCryptoQos = true
case OID_EKU_APPLE_CRYPTO_TIER0_QOS:
aux.AppleCryptoTier0Qos = true
case OID_EKU_APPLE_CRYPTO_TIER1_QOS:
aux.AppleCryptoTier1Qos = true
case OID_EKU_APPLE_CRYPTO_TIER2_QOS:
aux.AppleCryptoTier2Qos = true
case OID_EKU_APPLE_CRYPTO_TIER3_QOS:
aux.AppleCryptoTier3Qos = true
case OID_EKU_MICROSOFT_CERT_TRUST_LIST_SIGNING:
aux.MicrosoftCertTrustListSigning = true
case OID_EKU_MICROSOFT_QUALIFIED_SUBORDINATE:
aux.MicrosoftQualifiedSubordinate = true
case OID_EKU_MICROSOFT_KEY_RECOVERY_3:
aux.MicrosoftKeyRecovery3 = true
case OID_EKU_MICROSOFT_DOCUMENT_SIGNING:
aux.MicrosoftDocumentSigning = true
case OID_EKU_MICROSOFT_LIFETIME_SIGNING:
aux.MicrosoftLifetimeSigning = true
case OID_EKU_MICROSOFT_MOBILE_DEVICE_SOFTWARE:
aux.MicrosoftMobileDeviceSoftware = true
case OID_EKU_MICROSOFT_SMART_DISPLAY:
aux.MicrosoftSmartDisplay = true
case OID_EKU_MICROSOFT_CSP_SIGNATURE:
aux.MicrosoftCspSignature = true
case OID_EKU_MICROSOFT_TIMESTAMP_SIGNING:
aux.MicrosoftTimestampSigning = true
case OID_EKU_MICROSOFT_SERVER_GATED_CRYPTO:
aux.MicrosoftServerGatedCrypto = true
case OID_EKU_MICROSOFT_SGC_SERIALIZED:
aux.MicrosoftSgcSerialized = true
case OID_EKU_MICROSOFT_ENCRYPTED_FILE_SYSTEM:
aux.MicrosoftEncryptedFileSystem = true
case OID_EKU_MICROSOFT_EFS_RECOVERY:
aux.MicrosoftEfsRecovery = true
case OID_EKU_MICROSOFT_WHQL_CRYPTO:
aux.MicrosoftWhqlCrypto = true
case OID_EKU_MICROSOFT_NT5_CRYPTO:
aux.MicrosoftNt5Crypto = true
case OID_EKU_MICROSOFT_OEM_WHQL_CRYPTO:
aux.MicrosoftOemWhqlCrypto = true
case OID_EKU_MICROSOFT_EMBEDDED_NT_CRYPTO:
aux.MicrosoftEmbeddedNtCrypto = true
case OID_EKU_MICROSOFT_ROOT_LIST_SIGNER:
aux.MicrosoftRootListSigner = true
case OID_EKU_MICROSOFT_DRM:
aux.MicrosoftDrm = true
case OID_EKU_MICROSOFT_DRM_INDIVIDUALIZATION:
aux.MicrosoftDrmIndividualization = true
case OID_EKU_MICROSOFT_LICENSES:
aux.MicrosoftLicenses = true
case OID_EKU_MICROSOFT_LICENSE_SERVER:
aux.MicrosoftLicenseServer = true
case OID_EKU_MICROSOFT_ENROLLMENT_AGENT:
aux.MicrosoftEnrollmentAgent = true
case OID_EKU_MICROSOFT_SMARTCARD_LOGON:
aux.MicrosoftSmartcardLogon = true
case OID_EKU_MICROSOFT_CA_EXCHANGE:
aux.MicrosoftCaExchange = true
case OID_EKU_MICROSOFT_KEY_RECOVERY_21:
aux.MicrosoftKeyRecovery21 = true
case OID_EKU_MICROSOFT_SYSTEM_HEALTH:
aux.MicrosoftSystemHealth = true
case OID_EKU_MICROSOFT_SYSTEM_HEALTH_LOOPHOLE:
aux.MicrosoftSystemHealthLoophole = true
case OID_EKU_MICROSOFT_KERNEL_MODE_CODE_SIGNING:
aux.MicrosoftKernelModeCodeSigning = true
case OID_EKU_SERVER_AUTH:
aux.ServerAuth = true
case OID_EKU_DVCS:
aux.Dvcs = true
case OID_EKU_SBGP_CERT_AA_SERVICE_AUTH:
aux.SbgpCertAaServiceAuth = true
case OID_EKU_EAP_OVER_PPP:
aux.EapOverPpp = true
case OID_EKU_EAP_OVER_LAN:
aux.EapOverLan = true
case OID_EKU_CLIENT_AUTH:
aux.ClientAuth = true
case OID_EKU_CODE_SIGNING:
aux.CodeSigning = true
case OID_EKU_EMAIL_PROTECTION:
aux.EmailProtection = true
case OID_EKU_IPSEC_END_SYSTEM:
aux.IpsecEndSystem = true
case OID_EKU_IPSEC_TUNNEL:
aux.IpsecTunnel = true
case OID_EKU_IPSEC_USER:
aux.IpsecUser = true
case OID_EKU_TIME_STAMPING:
aux.TimeStamping = true
case OID_EKU_OCSP_SIGNING:
aux.OcspSigning = true
case OID_EKU_IPSEC_INTERMEDIATE_SYSTEM_USAGE:
aux.IpsecIntermediateSystemUsage = true
case OID_EKU_NETSCAPE_SERVER_GATED_CRYPTO:
aux.NetscapeServerGatedCrypto = true
case OID_EKU_ANY:
aux.Any = true
default:
}
return
}
func (aux *auxExtendedKeyUsage) populateFromExtKeyUsage(eku ExtKeyUsage) {
switch eku {
case ExtKeyUsageAppleCodeSigning:
aux.AppleCodeSigning = true
case ExtKeyUsageAppleCodeSigningDevelopment:
aux.AppleCodeSigningDevelopment = true
case ExtKeyUsageAppleSoftwareUpdateSigning:
aux.AppleSoftwareUpdateSigning = true
case ExtKeyUsageAppleCodeSigningThirdParty:
aux.AppleCodeSigningThirdParty = true
case ExtKeyUsageAppleResourceSigning:
aux.AppleResourceSigning = true
case ExtKeyUsageAppleIchatSigning:
aux.AppleIchatSigning = true
case ExtKeyUsageAppleIchatEncryption:
aux.AppleIchatEncryption = true
case ExtKeyUsageAppleSystemIdentity:
aux.AppleSystemIdentity = true
case ExtKeyUsageAppleCryptoEnv:
aux.AppleCryptoEnv = true
case ExtKeyUsageAppleCryptoProductionEnv:
aux.AppleCryptoProductionEnv = true
case ExtKeyUsageAppleCryptoMaintenanceEnv:
aux.AppleCryptoMaintenanceEnv = true
case ExtKeyUsageAppleCryptoTestEnv:
aux.AppleCryptoTestEnv = true
case ExtKeyUsageAppleCryptoDevelopmentEnv:
aux.AppleCryptoDevelopmentEnv = true
case ExtKeyUsageAppleCryptoQos:
aux.AppleCryptoQos = true
case ExtKeyUsageAppleCryptoTier0Qos:
aux.AppleCryptoTier0Qos = true
case ExtKeyUsageAppleCryptoTier1Qos:
aux.AppleCryptoTier1Qos = true
case ExtKeyUsageAppleCryptoTier2Qos:
aux.AppleCryptoTier2Qos = true
case ExtKeyUsageAppleCryptoTier3Qos:
aux.AppleCryptoTier3Qos = true
case ExtKeyUsageMicrosoftCertTrustListSigning:
aux.MicrosoftCertTrustListSigning = true
case ExtKeyUsageMicrosoftQualifiedSubordinate:
aux.MicrosoftQualifiedSubordinate = true
case ExtKeyUsageMicrosoftKeyRecovery3:
aux.MicrosoftKeyRecovery3 = true
case ExtKeyUsageMicrosoftDocumentSigning:
aux.MicrosoftDocumentSigning = true
case ExtKeyUsageMicrosoftLifetimeSigning:
aux.MicrosoftLifetimeSigning = true
case ExtKeyUsageMicrosoftMobileDeviceSoftware:
aux.MicrosoftMobileDeviceSoftware = true
case ExtKeyUsageMicrosoftSmartDisplay:
aux.MicrosoftSmartDisplay = true
case ExtKeyUsageMicrosoftCspSignature:
aux.MicrosoftCspSignature = true
case ExtKeyUsageMicrosoftTimestampSigning:
aux.MicrosoftTimestampSigning = true
case ExtKeyUsageMicrosoftServerGatedCrypto:
aux.MicrosoftServerGatedCrypto = true
case ExtKeyUsageMicrosoftSgcSerialized:
aux.MicrosoftSgcSerialized = true
case ExtKeyUsageMicrosoftEncryptedFileSystem:
aux.MicrosoftEncryptedFileSystem = true
case ExtKeyUsageMicrosoftEfsRecovery:
aux.MicrosoftEfsRecovery = true
case ExtKeyUsageMicrosoftWhqlCrypto:
aux.MicrosoftWhqlCrypto = true
case ExtKeyUsageMicrosoftNt5Crypto:
aux.MicrosoftNt5Crypto = true
case ExtKeyUsageMicrosoftOemWhqlCrypto:
aux.MicrosoftOemWhqlCrypto = true
case ExtKeyUsageMicrosoftEmbeddedNtCrypto:
aux.MicrosoftEmbeddedNtCrypto = true
case ExtKeyUsageMicrosoftRootListSigner:
aux.MicrosoftRootListSigner = true
case ExtKeyUsageMicrosoftDrm:
aux.MicrosoftDrm = true
case ExtKeyUsageMicrosoftDrmIndividualization:
aux.MicrosoftDrmIndividualization = true
case ExtKeyUsageMicrosoftLicenses:
aux.MicrosoftLicenses = true
case ExtKeyUsageMicrosoftLicenseServer:
aux.MicrosoftLicenseServer = true
case ExtKeyUsageMicrosoftEnrollmentAgent:
aux.MicrosoftEnrollmentAgent = true
case ExtKeyUsageMicrosoftSmartcardLogon:
aux.MicrosoftSmartcardLogon = true
case ExtKeyUsageMicrosoftCaExchange:
aux.MicrosoftCaExchange = true
case ExtKeyUsageMicrosoftKeyRecovery21:
aux.MicrosoftKeyRecovery21 = true
case ExtKeyUsageMicrosoftSystemHealth:
aux.MicrosoftSystemHealth = true
case ExtKeyUsageMicrosoftSystemHealthLoophole:
aux.MicrosoftSystemHealthLoophole = true
case ExtKeyUsageMicrosoftKernelModeCodeSigning:
aux.MicrosoftKernelModeCodeSigning = true
case ExtKeyUsageServerAuth:
aux.ServerAuth = true
case ExtKeyUsageDvcs:
aux.Dvcs = true
case ExtKeyUsageSbgpCertAaServiceAuth:
aux.SbgpCertAaServiceAuth = true
case ExtKeyUsageEapOverPpp:
aux.EapOverPpp = true
case ExtKeyUsageEapOverLan:
aux.EapOverLan = true
case ExtKeyUsageClientAuth:
aux.ClientAuth = true
case ExtKeyUsageCodeSigning:
aux.CodeSigning = true
case ExtKeyUsageEmailProtection:
aux.EmailProtection = true
case ExtKeyUsageIpsecEndSystem:
aux.IpsecEndSystem = true
case ExtKeyUsageIpsecTunnel:
aux.IpsecTunnel = true
case ExtKeyUsageIpsecUser:
aux.IpsecUser = true
case ExtKeyUsageTimeStamping:
aux.TimeStamping = true
case ExtKeyUsageOcspSigning:
aux.OcspSigning = true
case ExtKeyUsageIpsecIntermediateSystemUsage:
aux.IpsecIntermediateSystemUsage = true
case ExtKeyUsageNetscapeServerGatedCrypto:
aux.NetscapeServerGatedCrypto = true
case ExtKeyUsageAny:
aux.Any = true
default:
}
return
}
var ekuOIDs map[string]asn1.ObjectIdentifier
var ekuConstants map[string]ExtKeyUsage
func init() {
ekuOIDs = make(map[string]asn1.ObjectIdentifier)
ekuOIDs[OID_EKU_APPLE_CODE_SIGNING] = oidExtKeyUsageAppleCodeSigning
ekuOIDs[OID_EKU_APPLE_CODE_SIGNING_DEVELOPMENT] = oidExtKeyUsageAppleCodeSigningDevelopment
ekuOIDs[OID_EKU_APPLE_SOFTWARE_UPDATE_SIGNING] = oidExtKeyUsageAppleSoftwareUpdateSigning
ekuOIDs[OID_EKU_APPLE_CODE_SIGNING_THIRD_PARTY] = oidExtKeyUsageAppleCodeSigningThirdParty
ekuOIDs[OID_EKU_APPLE_RESOURCE_SIGNING] = oidExtKeyUsageAppleResourceSigning
ekuOIDs[OID_EKU_APPLE_ICHAT_SIGNING] = oidExtKeyUsageAppleIchatSigning
ekuOIDs[OID_EKU_APPLE_ICHAT_ENCRYPTION] = oidExtKeyUsageAppleIchatEncryption
ekuOIDs[OID_EKU_APPLE_SYSTEM_IDENTITY] = oidExtKeyUsageAppleSystemIdentity
ekuOIDs[OID_EKU_APPLE_CRYPTO_ENV] = oidExtKeyUsageAppleCryptoEnv
ekuOIDs[OID_EKU_APPLE_CRYPTO_PRODUCTION_ENV] = oidExtKeyUsageAppleCryptoProductionEnv
ekuOIDs[OID_EKU_APPLE_CRYPTO_MAINTENANCE_ENV] = oidExtKeyUsageAppleCryptoMaintenanceEnv
ekuOIDs[OID_EKU_APPLE_CRYPTO_TEST_ENV] = oidExtKeyUsageAppleCryptoTestEnv
ekuOIDs[OID_EKU_APPLE_CRYPTO_DEVELOPMENT_ENV] = oidExtKeyUsageAppleCryptoDevelopmentEnv
ekuOIDs[OID_EKU_APPLE_CRYPTO_QOS] = oidExtKeyUsageAppleCryptoQos
ekuOIDs[OID_EKU_APPLE_CRYPTO_TIER0_QOS] = oidExtKeyUsageAppleCryptoTier0Qos
ekuOIDs[OID_EKU_APPLE_CRYPTO_TIER1_QOS] = oidExtKeyUsageAppleCryptoTier1Qos
ekuOIDs[OID_EKU_APPLE_CRYPTO_TIER2_QOS] = oidExtKeyUsageAppleCryptoTier2Qos
ekuOIDs[OID_EKU_APPLE_CRYPTO_TIER3_QOS] = oidExtKeyUsageAppleCryptoTier3Qos
ekuOIDs[OID_EKU_MICROSOFT_CERT_TRUST_LIST_SIGNING] = oidExtKeyUsageMicrosoftCertTrustListSigning
ekuOIDs[OID_EKU_MICROSOFT_QUALIFIED_SUBORDINATE] = oidExtKeyUsageMicrosoftQualifiedSubordinate
ekuOIDs[OID_EKU_MICROSOFT_KEY_RECOVERY_3] = oidExtKeyUsageMicrosoftKeyRecovery3
ekuOIDs[OID_EKU_MICROSOFT_DOCUMENT_SIGNING] = oidExtKeyUsageMicrosoftDocumentSigning
ekuOIDs[OID_EKU_MICROSOFT_LIFETIME_SIGNING] = oidExtKeyUsageMicrosoftLifetimeSigning
ekuOIDs[OID_EKU_MICROSOFT_MOBILE_DEVICE_SOFTWARE] = oidExtKeyUsageMicrosoftMobileDeviceSoftware
ekuOIDs[OID_EKU_MICROSOFT_SMART_DISPLAY] = oidExtKeyUsageMicrosoftSmartDisplay
ekuOIDs[OID_EKU_MICROSOFT_CSP_SIGNATURE] = oidExtKeyUsageMicrosoftCspSignature
ekuOIDs[OID_EKU_MICROSOFT_TIMESTAMP_SIGNING] = oidExtKeyUsageMicrosoftTimestampSigning
ekuOIDs[OID_EKU_MICROSOFT_SERVER_GATED_CRYPTO] = oidExtKeyUsageMicrosoftServerGatedCrypto
ekuOIDs[OID_EKU_MICROSOFT_SGC_SERIALIZED] = oidExtKeyUsageMicrosoftSgcSerialized
ekuOIDs[OID_EKU_MICROSOFT_ENCRYPTED_FILE_SYSTEM] = oidExtKeyUsageMicrosoftEncryptedFileSystem
ekuOIDs[OID_EKU_MICROSOFT_EFS_RECOVERY] = oidExtKeyUsageMicrosoftEfsRecovery
ekuOIDs[OID_EKU_MICROSOFT_WHQL_CRYPTO] = oidExtKeyUsageMicrosoftWhqlCrypto
ekuOIDs[OID_EKU_MICROSOFT_NT5_CRYPTO] = oidExtKeyUsageMicrosoftNt5Crypto
ekuOIDs[OID_EKU_MICROSOFT_OEM_WHQL_CRYPTO] = oidExtKeyUsageMicrosoftOemWhqlCrypto
ekuOIDs[OID_EKU_MICROSOFT_EMBEDDED_NT_CRYPTO] = oidExtKeyUsageMicrosoftEmbeddedNtCrypto
ekuOIDs[OID_EKU_MICROSOFT_ROOT_LIST_SIGNER] = oidExtKeyUsageMicrosoftRootListSigner
ekuOIDs[OID_EKU_MICROSOFT_DRM] = oidExtKeyUsageMicrosoftDrm
ekuOIDs[OID_EKU_MICROSOFT_DRM_INDIVIDUALIZATION] = oidExtKeyUsageMicrosoftDrmIndividualization
ekuOIDs[OID_EKU_MICROSOFT_LICENSES] = oidExtKeyUsageMicrosoftLicenses
ekuOIDs[OID_EKU_MICROSOFT_LICENSE_SERVER] = oidExtKeyUsageMicrosoftLicenseServer
ekuOIDs[OID_EKU_MICROSOFT_ENROLLMENT_AGENT] = oidExtKeyUsageMicrosoftEnrollmentAgent
ekuOIDs[OID_EKU_MICROSOFT_SMARTCARD_LOGON] = oidExtKeyUsageMicrosoftSmartcardLogon
ekuOIDs[OID_EKU_MICROSOFT_CA_EXCHANGE] = oidExtKeyUsageMicrosoftCaExchange
ekuOIDs[OID_EKU_MICROSOFT_KEY_RECOVERY_21] = oidExtKeyUsageMicrosoftKeyRecovery21
ekuOIDs[OID_EKU_MICROSOFT_SYSTEM_HEALTH] = oidExtKeyUsageMicrosoftSystemHealth
ekuOIDs[OID_EKU_MICROSOFT_SYSTEM_HEALTH_LOOPHOLE] = oidExtKeyUsageMicrosoftSystemHealthLoophole
ekuOIDs[OID_EKU_MICROSOFT_KERNEL_MODE_CODE_SIGNING] = oidExtKeyUsageMicrosoftKernelModeCodeSigning
ekuOIDs[OID_EKU_SERVER_AUTH] = oidExtKeyUsageServerAuth
ekuOIDs[OID_EKU_DVCS] = oidExtKeyUsageDvcs
ekuOIDs[OID_EKU_SBGP_CERT_AA_SERVICE_AUTH] = oidExtKeyUsageSbgpCertAaServiceAuth
ekuOIDs[OID_EKU_EAP_OVER_PPP] = oidExtKeyUsageEapOverPpp
ekuOIDs[OID_EKU_EAP_OVER_LAN] = oidExtKeyUsageEapOverLan
ekuOIDs[OID_EKU_CLIENT_AUTH] = oidExtKeyUsageClientAuth
ekuOIDs[OID_EKU_CODE_SIGNING] = oidExtKeyUsageCodeSigning
ekuOIDs[OID_EKU_EMAIL_PROTECTION] = oidExtKeyUsageEmailProtection
ekuOIDs[OID_EKU_IPSEC_END_SYSTEM] = oidExtKeyUsageIpsecEndSystem
ekuOIDs[OID_EKU_IPSEC_TUNNEL] = oidExtKeyUsageIpsecTunnel
ekuOIDs[OID_EKU_IPSEC_USER] = oidExtKeyUsageIpsecUser
ekuOIDs[OID_EKU_TIME_STAMPING] = oidExtKeyUsageTimeStamping
ekuOIDs[OID_EKU_OCSP_SIGNING] = oidExtKeyUsageOcspSigning
ekuOIDs[OID_EKU_IPSEC_INTERMEDIATE_SYSTEM_USAGE] = oidExtKeyUsageIpsecIntermediateSystemUsage
ekuOIDs[OID_EKU_NETSCAPE_SERVER_GATED_CRYPTO] = oidExtKeyUsageNetscapeServerGatedCrypto
ekuOIDs[OID_EKU_ANY] = oidExtKeyUsageAny
ekuConstants = make(map[string]ExtKeyUsage)
ekuConstants[OID_EKU_APPLE_CODE_SIGNING] = ExtKeyUsageAppleCodeSigning
ekuConstants[OID_EKU_APPLE_CODE_SIGNING_DEVELOPMENT] = ExtKeyUsageAppleCodeSigningDevelopment
ekuConstants[OID_EKU_APPLE_SOFTWARE_UPDATE_SIGNING] = ExtKeyUsageAppleSoftwareUpdateSigning
ekuConstants[OID_EKU_APPLE_CODE_SIGNING_THIRD_PARTY] = ExtKeyUsageAppleCodeSigningThirdParty
ekuConstants[OID_EKU_APPLE_RESOURCE_SIGNING] = ExtKeyUsageAppleResourceSigning
ekuConstants[OID_EKU_APPLE_ICHAT_SIGNING] = ExtKeyUsageAppleIchatSigning
ekuConstants[OID_EKU_APPLE_ICHAT_ENCRYPTION] = ExtKeyUsageAppleIchatEncryption
ekuConstants[OID_EKU_APPLE_SYSTEM_IDENTITY] = ExtKeyUsageAppleSystemIdentity
ekuConstants[OID_EKU_APPLE_CRYPTO_ENV] = ExtKeyUsageAppleCryptoEnv
ekuConstants[OID_EKU_APPLE_CRYPTO_PRODUCTION_ENV] = ExtKeyUsageAppleCryptoProductionEnv
ekuConstants[OID_EKU_APPLE_CRYPTO_MAINTENANCE_ENV] = ExtKeyUsageAppleCryptoMaintenanceEnv
ekuConstants[OID_EKU_APPLE_CRYPTO_TEST_ENV] = ExtKeyUsageAppleCryptoTestEnv
ekuConstants[OID_EKU_APPLE_CRYPTO_DEVELOPMENT_ENV] = ExtKeyUsageAppleCryptoDevelopmentEnv
ekuConstants[OID_EKU_APPLE_CRYPTO_QOS] = ExtKeyUsageAppleCryptoQos
ekuConstants[OID_EKU_APPLE_CRYPTO_TIER0_QOS] = ExtKeyUsageAppleCryptoTier0Qos
ekuConstants[OID_EKU_APPLE_CRYPTO_TIER1_QOS] = ExtKeyUsageAppleCryptoTier1Qos
ekuConstants[OID_EKU_APPLE_CRYPTO_TIER2_QOS] = ExtKeyUsageAppleCryptoTier2Qos
ekuConstants[OID_EKU_APPLE_CRYPTO_TIER3_QOS] = ExtKeyUsageAppleCryptoTier3Qos
ekuConstants[OID_EKU_MICROSOFT_CERT_TRUST_LIST_SIGNING] = ExtKeyUsageMicrosoftCertTrustListSigning
ekuConstants[OID_EKU_MICROSOFT_QUALIFIED_SUBORDINATE] = ExtKeyUsageMicrosoftQualifiedSubordinate
ekuConstants[OID_EKU_MICROSOFT_KEY_RECOVERY_3] = ExtKeyUsageMicrosoftKeyRecovery3
ekuConstants[OID_EKU_MICROSOFT_DOCUMENT_SIGNING] = ExtKeyUsageMicrosoftDocumentSigning
ekuConstants[OID_EKU_MICROSOFT_LIFETIME_SIGNING] = ExtKeyUsageMicrosoftLifetimeSigning
ekuConstants[OID_EKU_MICROSOFT_MOBILE_DEVICE_SOFTWARE] = ExtKeyUsageMicrosoftMobileDeviceSoftware
ekuConstants[OID_EKU_MICROSOFT_SMART_DISPLAY] = ExtKeyUsageMicrosoftSmartDisplay
ekuConstants[OID_EKU_MICROSOFT_CSP_SIGNATURE] = ExtKeyUsageMicrosoftCspSignature
ekuConstants[OID_EKU_MICROSOFT_TIMESTAMP_SIGNING] = ExtKeyUsageMicrosoftTimestampSigning
ekuConstants[OID_EKU_MICROSOFT_SERVER_GATED_CRYPTO] = ExtKeyUsageMicrosoftServerGatedCrypto
ekuConstants[OID_EKU_MICROSOFT_SGC_SERIALIZED] = ExtKeyUsageMicrosoftSgcSerialized
ekuConstants[OID_EKU_MICROSOFT_ENCRYPTED_FILE_SYSTEM] = ExtKeyUsageMicrosoftEncryptedFileSystem
ekuConstants[OID_EKU_MICROSOFT_EFS_RECOVERY] = ExtKeyUsageMicrosoftEfsRecovery
ekuConstants[OID_EKU_MICROSOFT_WHQL_CRYPTO] = ExtKeyUsageMicrosoftWhqlCrypto
ekuConstants[OID_EKU_MICROSOFT_NT5_CRYPTO] = ExtKeyUsageMicrosoftNt5Crypto
ekuConstants[OID_EKU_MICROSOFT_OEM_WHQL_CRYPTO] = ExtKeyUsageMicrosoftOemWhqlCrypto
ekuConstants[OID_EKU_MICROSOFT_EMBEDDED_NT_CRYPTO] = ExtKeyUsageMicrosoftEmbeddedNtCrypto
ekuConstants[OID_EKU_MICROSOFT_ROOT_LIST_SIGNER] = ExtKeyUsageMicrosoftRootListSigner
ekuConstants[OID_EKU_MICROSOFT_DRM] = ExtKeyUsageMicrosoftDrm
ekuConstants[OID_EKU_MICROSOFT_DRM_INDIVIDUALIZATION] = ExtKeyUsageMicrosoftDrmIndividualization
ekuConstants[OID_EKU_MICROSOFT_LICENSES] = ExtKeyUsageMicrosoftLicenses
ekuConstants[OID_EKU_MICROSOFT_LICENSE_SERVER] = ExtKeyUsageMicrosoftLicenseServer
ekuConstants[OID_EKU_MICROSOFT_ENROLLMENT_AGENT] = ExtKeyUsageMicrosoftEnrollmentAgent
ekuConstants[OID_EKU_MICROSOFT_SMARTCARD_LOGON] = ExtKeyUsageMicrosoftSmartcardLogon
ekuConstants[OID_EKU_MICROSOFT_CA_EXCHANGE] = ExtKeyUsageMicrosoftCaExchange
ekuConstants[OID_EKU_MICROSOFT_KEY_RECOVERY_21] = ExtKeyUsageMicrosoftKeyRecovery21
ekuConstants[OID_EKU_MICROSOFT_SYSTEM_HEALTH] = ExtKeyUsageMicrosoftSystemHealth
ekuConstants[OID_EKU_MICROSOFT_SYSTEM_HEALTH_LOOPHOLE] = ExtKeyUsageMicrosoftSystemHealthLoophole
ekuConstants[OID_EKU_MICROSOFT_KERNEL_MODE_CODE_SIGNING] = ExtKeyUsageMicrosoftKernelModeCodeSigning
ekuConstants[OID_EKU_SERVER_AUTH] = ExtKeyUsageServerAuth
ekuConstants[OID_EKU_DVCS] = ExtKeyUsageDvcs
ekuConstants[OID_EKU_SBGP_CERT_AA_SERVICE_AUTH] = ExtKeyUsageSbgpCertAaServiceAuth
ekuConstants[OID_EKU_EAP_OVER_PPP] = ExtKeyUsageEapOverPpp
ekuConstants[OID_EKU_EAP_OVER_LAN] = ExtKeyUsageEapOverLan
ekuConstants[OID_EKU_CLIENT_AUTH] = ExtKeyUsageClientAuth
ekuConstants[OID_EKU_CODE_SIGNING] = ExtKeyUsageCodeSigning
ekuConstants[OID_EKU_EMAIL_PROTECTION] = ExtKeyUsageEmailProtection
ekuConstants[OID_EKU_IPSEC_END_SYSTEM] = ExtKeyUsageIpsecEndSystem
ekuConstants[OID_EKU_IPSEC_TUNNEL] = ExtKeyUsageIpsecTunnel
ekuConstants[OID_EKU_IPSEC_USER] = ExtKeyUsageIpsecUser
ekuConstants[OID_EKU_TIME_STAMPING] = ExtKeyUsageTimeStamping
ekuConstants[OID_EKU_OCSP_SIGNING] = ExtKeyUsageOcspSigning
ekuConstants[OID_EKU_IPSEC_INTERMEDIATE_SYSTEM_USAGE] = ExtKeyUsageIpsecIntermediateSystemUsage
ekuConstants[OID_EKU_NETSCAPE_SERVER_GATED_CRYPTO] = ExtKeyUsageNetscapeServerGatedCrypto
ekuConstants[OID_EKU_ANY] = ExtKeyUsageAny
}

View file

@ -0,0 +1,21 @@
#!/bin/bash
set -e
# TODO: This should really be generated by Go code as a subrecord, but
# importing in Python is hard. This is quick and dirty.
FIELDS=$(\
cat extended_key_usage.go |\
grep json |\
cut -d ':' -f 2 |\
sed 's|,omitempty||g' |\
tr -d '`')
echo "extended_key_usage = SubRecord({"
for f in $FIELDS; do
if [ $f == "\"unknown\"" ]; then
echo " $f: ListOf(OID())"
else
echo " $f: Boolean(),"
fi
done
echo "})"

818
vendor/github.com/zmap/zcrypto/x509/extensions.go generated vendored Normal file
View file

@ -0,0 +1,818 @@
// Copyright 2015 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 x509
import (
"encoding/asn1"
"encoding/hex"
"encoding/json"
"net"
"strconv"
"strings"
"github.com/zmap/zcrypto/x509/ct"
"github.com/zmap/zcrypto/x509/pkix"
)
var (
oidExtKeyUsage = asn1.ObjectIdentifier{2, 5, 29, 15}
oidExtBasicConstraints = asn1.ObjectIdentifier{2, 5, 29, 19}
oidExtSubjectAltName = asn1.ObjectIdentifier{2, 5, 29, 17}
oidExtIssuerAltName = asn1.ObjectIdentifier{2, 5, 29, 18}
oidExtNameConstraints = asn1.ObjectIdentifier{2, 5, 29, 30}
oidCRLDistributionPoints = asn1.ObjectIdentifier{2, 5, 29, 31}
oidExtAuthKeyId = asn1.ObjectIdentifier{2, 5, 29, 35}
oidExtSubjectKeyId = asn1.ObjectIdentifier{2, 5, 29, 14}
oidExtExtendedKeyUsage = asn1.ObjectIdentifier{2, 5, 29, 37}
oidExtCertificatePolicy = asn1.ObjectIdentifier{2, 5, 29, 32}
oidExtAuthorityInfoAccess = oidExtensionAuthorityInfoAccess
oidExtensionCTPrecertificatePoison = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 11129, 2, 4, 3}
oidExtSignedCertificateTimestampList = oidExtensionSignedCertificateTimestampList
oidExtCABFOrganizationID = asn1.ObjectIdentifier{2, 23, 140, 3, 1}
oidExtQCStatements = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 1, 3}
)
type CertificateExtensions struct {
KeyUsage KeyUsage `json:"key_usage,omitempty"`
BasicConstraints *BasicConstraints `json:"basic_constraints,omitempty"`
SubjectAltName *GeneralNames `json:"subject_alt_name,omitempty"`
IssuerAltName *GeneralNames `json:"issuer_alt_name,omitempty"`
NameConstraints *NameConstraints `json:"name_constraints,omitempty"`
CRLDistributionPoints CRLDistributionPoints `json:"crl_distribution_points,omitempty"`
AuthKeyID SubjAuthKeyId `json:"authority_key_id,omitempty"`
SubjectKeyID SubjAuthKeyId `json:"subject_key_id,omitempty"`
ExtendedKeyUsage *ExtendedKeyUsageExtension `json:"extended_key_usage,omitempty"`
CertificatePolicies *CertificatePoliciesData `json:"certificate_policies,omitempty"`
AuthorityInfoAccess *AuthorityInfoAccess `json:"authority_info_access,omitempty"`
IsPrecert IsPrecert `json:"ct_poison,omitempty"`
SignedCertificateTimestampList []*ct.SignedCertificateTimestamp `json:"signed_certificate_timestamps,omitempty"`
TorServiceDescriptors []*TorServiceDescriptorHash `json:"tor_service_descriptors,omitempty"`
CABFOrganizationIdentifier *CABFOrganizationIdentifier `json:"cabf_organization_id,omitempty"`
QCStatements *QCStatements `json:"qc_statements,omitempty"`
}
type UnknownCertificateExtensions []pkix.Extension
type IsPrecert bool
type BasicConstraints struct {
IsCA bool `json:"is_ca"`
MaxPathLen *int `json:"max_path_len,omitempty"`
}
type NoticeReference struct {
Organization string `json:"organization,omitempty"`
NoticeNumbers NoticeNumber `json:"notice_numbers,omitempty"`
}
type UserNoticeData struct {
ExplicitText string `json:"explicit_text,omitempty"`
NoticeReference []NoticeReference `json:"notice_reference,omitempty"`
}
type CertificatePoliciesJSON struct {
PolicyIdentifier string `json:"id,omitempty"`
CPSUri []string `json:"cps,omitempty"`
UserNotice []UserNoticeData `json:"user_notice,omitempty"`
}
type CertificatePolicies []CertificatePoliciesJSON
type CertificatePoliciesData struct {
PolicyIdentifiers []asn1.ObjectIdentifier
QualifierId [][]asn1.ObjectIdentifier
CPSUri [][]string
ExplicitTexts [][]string
NoticeRefOrganization [][]string
NoticeRefNumbers [][]NoticeNumber
}
func (cp *CertificatePoliciesData) MarshalJSON() ([]byte, error) {
policies := CertificatePolicies{}
for idx, oid := range cp.PolicyIdentifiers {
cpsJSON := CertificatePoliciesJSON{}
cpsJSON.PolicyIdentifier = oid.String()
for _, uri := range cp.CPSUri[idx] {
cpsJSON.CPSUri = append(cpsJSON.CPSUri, uri)
}
for idx2, explicit_text := range cp.ExplicitTexts[idx] {
uNoticeData := UserNoticeData{}
uNoticeData.ExplicitText = explicit_text
noticeRef := NoticeReference{}
if len(cp.NoticeRefOrganization[idx]) > 0 {
organization := cp.NoticeRefOrganization[idx][idx2]
noticeRef.Organization = organization
noticeRef.NoticeNumbers = cp.NoticeRefNumbers[idx][idx2]
uNoticeData.NoticeReference = append(uNoticeData.NoticeReference, noticeRef)
}
cpsJSON.UserNotice = append(cpsJSON.UserNotice, uNoticeData)
}
policies = append(policies, cpsJSON)
}
return json.Marshal(policies)
}
// GeneralNames corresponds an X.509 GeneralName defined in
// Section 4.2.1.6 of RFC 5280.
//
// GeneralName ::= CHOICE {
// otherName [0] AnotherName,
// rfc822Name [1] IA5String,
// dNSName [2] IA5String,
// x400Address [3] ORAddress,
// directoryName [4] Name,
// ediPartyName [5] EDIPartyName,
// uniformResourceIdentifier [6] IA5String,
// iPAddress [7] OCTET STRING,
// registeredID [8] OBJECT IDENTIFIER }
type GeneralNames struct {
DirectoryNames []pkix.Name
DNSNames []string
EDIPartyNames []pkix.EDIPartyName
EmailAddresses []string
IPAddresses []net.IP
OtherNames []pkix.OtherName
RegisteredIDs []asn1.ObjectIdentifier
URIs []string
}
type jsonGeneralNames struct {
DirectoryNames []pkix.Name `json:"directory_names,omitempty"`
DNSNames []string `json:"dns_names,omitempty"`
EDIPartyNames []pkix.EDIPartyName `json:"edi_party_names,omitempty"`
EmailAddresses []string `json:"email_addresses,omitempty"`
IPAddresses []net.IP `json:"ip_addresses,omitempty"`
OtherNames []pkix.OtherName `json:"other_names,omitempty"`
RegisteredIDs []string `json:"registered_ids,omitempty"`
URIs []string `json:"uniform_resource_identifiers,omitempty"`
}
func (gn *GeneralNames) MarshalJSON() ([]byte, error) {
jsan := jsonGeneralNames{
DirectoryNames: gn.DirectoryNames,
DNSNames: gn.DNSNames,
EDIPartyNames: gn.EDIPartyNames,
EmailAddresses: gn.EmailAddresses,
IPAddresses: gn.IPAddresses,
OtherNames: gn.OtherNames,
RegisteredIDs: make([]string, 0, len(gn.RegisteredIDs)),
URIs: gn.URIs,
}
for _, id := range gn.RegisteredIDs {
jsan.RegisteredIDs = append(jsan.RegisteredIDs, id.String())
}
return json.Marshal(jsan)
}
func (gn *GeneralNames) UnmarshalJSON(b []byte) error {
var jsan jsonGeneralNames
err := json.Unmarshal(b, &jsan)
if err != nil {
return err
}
gn.DirectoryNames = jsan.DirectoryNames
gn.DNSNames = jsan.DNSNames
gn.EDIPartyNames = jsan.EDIPartyNames
gn.EmailAddresses = jsan.EmailAddresses
gn.IPAddresses = jsan.IPAddresses
gn.OtherNames = jsan.OtherNames
gn.RegisteredIDs = make([]asn1.ObjectIdentifier, len(jsan.RegisteredIDs))
gn.URIs = jsan.URIs
for i, rID := range jsan.RegisteredIDs {
arcs := strings.Split(rID, ".")
oid := make(asn1.ObjectIdentifier, len(arcs))
for j, s := range arcs {
tmp, err := strconv.ParseInt(s, 10, 32)
if err != nil {
return err
}
oid[j] = int(tmp)
}
gn.RegisteredIDs[i] = oid
}
return nil
}
// TODO: Handle excluded names
type NameConstraints struct {
Critical bool `json:"critical"`
PermittedDNSNames []GeneralSubtreeString
PermittedEmailAddresses []GeneralSubtreeString
PermittedURIs []GeneralSubtreeString
PermittedIPAddresses []GeneralSubtreeIP
PermittedDirectoryNames []GeneralSubtreeName
PermittedEdiPartyNames []GeneralSubtreeEdi
PermittedRegisteredIDs []GeneralSubtreeOid
ExcludedEmailAddresses []GeneralSubtreeString
ExcludedDNSNames []GeneralSubtreeString
ExcludedURIs []GeneralSubtreeString
ExcludedIPAddresses []GeneralSubtreeIP
ExcludedDirectoryNames []GeneralSubtreeName
ExcludedEdiPartyNames []GeneralSubtreeEdi
ExcludedRegisteredIDs []GeneralSubtreeOid
}
type NameConstraintsJSON struct {
Critical bool `json:"critical"`
PermittedDNSNames []string `json:"permitted_names,omitempty"`
PermittedEmailAddresses []string `json:"permitted_email_addresses,omitempty"`
PermittedURIs []string `json:"permitted_uris,omitempty"`
PermittedIPAddresses []GeneralSubtreeIP `json:"permitted_ip_addresses,omitempty"`
PermittedDirectoryNames []pkix.Name `json:"permitted_directory_names,omitempty"`
PermittedEdiPartyNames []pkix.EDIPartyName `json:"permitted_edi_party_names,omitempty"`
PermittedRegisteredIDs []string `json:"permitted_registred_id,omitempty"`
ExcludedDNSNames []string `json:"excluded_names,omitempty"`
ExcludedEmailAddresses []string `json:"excluded_email_addresses,omitempty"`
ExcludedURIs []string `json:"excluded_uris,omitempty"`
ExcludedIPAddresses []GeneralSubtreeIP `json:"excluded_ip_addresses,omitempty"`
ExcludedDirectoryNames []pkix.Name `json:"excluded_directory_names,omitempty"`
ExcludedEdiPartyNames []pkix.EDIPartyName `json:"excluded_edi_party_names,omitempty"`
ExcludedRegisteredIDs []string `json:"excluded_registred_id,omitempty"`
}
func (nc *NameConstraints) UnmarshalJSON(b []byte) error {
var ncJson NameConstraintsJSON
err := json.Unmarshal(b, &ncJson)
if err != nil {
return err
}
for _, dns := range ncJson.PermittedDNSNames {
nc.PermittedDNSNames = append(nc.PermittedDNSNames, GeneralSubtreeString{Data: dns})
}
for _, email := range ncJson.PermittedEmailAddresses {
nc.PermittedEmailAddresses = append(nc.PermittedEmailAddresses, GeneralSubtreeString{Data: email})
}
for _, uri := range ncJson.PermittedURIs {
nc.PermittedURIs = append(nc.PermittedURIs, GeneralSubtreeString{Data: uri})
}
for _, constraint := range ncJson.PermittedIPAddresses {
nc.PermittedIPAddresses = append(nc.PermittedIPAddresses, constraint)
}
for _, directory := range ncJson.PermittedDirectoryNames {
nc.PermittedDirectoryNames = append(nc.PermittedDirectoryNames, GeneralSubtreeName{Data: directory})
}
for _, edi := range ncJson.PermittedEdiPartyNames {
nc.PermittedEdiPartyNames = append(nc.PermittedEdiPartyNames, GeneralSubtreeEdi{Data: edi})
}
for _, id := range ncJson.PermittedRegisteredIDs {
arcs := strings.Split(id, ".")
oid := make(asn1.ObjectIdentifier, len(arcs))
for j, s := range arcs {
tmp, err := strconv.ParseInt(s, 10, 32)
if err != nil {
return err
}
oid[j] = int(tmp)
}
nc.PermittedRegisteredIDs = append(nc.PermittedRegisteredIDs, GeneralSubtreeOid{Data: oid})
}
for _, dns := range ncJson.ExcludedDNSNames {
nc.ExcludedDNSNames = append(nc.ExcludedDNSNames, GeneralSubtreeString{Data: dns})
}
for _, email := range ncJson.ExcludedEmailAddresses {
nc.ExcludedEmailAddresses = append(nc.ExcludedEmailAddresses, GeneralSubtreeString{Data: email})
}
for _, uri := range ncJson.ExcludedURIs {
nc.ExcludedURIs = append(nc.ExcludedURIs, GeneralSubtreeString{Data: uri})
}
for _, constraint := range ncJson.ExcludedIPAddresses {
nc.ExcludedIPAddresses = append(nc.ExcludedIPAddresses, constraint)
}
for _, directory := range ncJson.ExcludedDirectoryNames {
nc.ExcludedDirectoryNames = append(nc.ExcludedDirectoryNames, GeneralSubtreeName{Data: directory})
}
for _, edi := range ncJson.ExcludedEdiPartyNames {
nc.ExcludedEdiPartyNames = append(nc.ExcludedEdiPartyNames, GeneralSubtreeEdi{Data: edi})
}
for _, id := range ncJson.ExcludedRegisteredIDs {
arcs := strings.Split(id, ".")
oid := make(asn1.ObjectIdentifier, len(arcs))
for j, s := range arcs {
tmp, err := strconv.ParseInt(s, 10, 32)
if err != nil {
return err
}
oid[j] = int(tmp)
}
nc.ExcludedRegisteredIDs = append(nc.ExcludedRegisteredIDs, GeneralSubtreeOid{Data: oid})
}
return nil
}
func (nc NameConstraints) MarshalJSON() ([]byte, error) {
var out NameConstraintsJSON
for _, dns := range nc.PermittedDNSNames {
out.PermittedDNSNames = append(out.PermittedDNSNames, dns.Data)
}
for _, email := range nc.PermittedEmailAddresses {
out.PermittedEmailAddresses = append(out.PermittedEmailAddresses, email.Data)
}
for _, uri := range nc.PermittedURIs {
out.PermittedURIs = append(out.PermittedURIs, uri.Data)
}
out.PermittedIPAddresses = nc.PermittedIPAddresses
for _, directory := range nc.PermittedDirectoryNames {
out.PermittedDirectoryNames = append(out.PermittedDirectoryNames, directory.Data)
}
for _, edi := range nc.PermittedEdiPartyNames {
out.PermittedEdiPartyNames = append(out.PermittedEdiPartyNames, edi.Data)
}
for _, id := range nc.PermittedRegisteredIDs {
out.PermittedRegisteredIDs = append(out.PermittedRegisteredIDs, id.Data.String())
}
for _, dns := range nc.ExcludedDNSNames {
out.ExcludedDNSNames = append(out.ExcludedDNSNames, dns.Data)
}
for _, email := range nc.ExcludedEmailAddresses {
out.ExcludedEmailAddresses = append(out.ExcludedEmailAddresses, email.Data)
}
for _, uri := range nc.ExcludedURIs {
out.ExcludedURIs = append(out.ExcludedURIs, uri.Data)
}
for _, ip := range nc.ExcludedIPAddresses {
out.ExcludedIPAddresses = append(out.ExcludedIPAddresses, ip)
}
for _, directory := range nc.ExcludedDirectoryNames {
out.ExcludedDirectoryNames = append(out.ExcludedDirectoryNames, directory.Data)
}
for _, edi := range nc.ExcludedEdiPartyNames {
out.ExcludedEdiPartyNames = append(out.ExcludedEdiPartyNames, edi.Data)
}
for _, id := range nc.ExcludedRegisteredIDs {
out.ExcludedRegisteredIDs = append(out.ExcludedRegisteredIDs, id.Data.String())
}
return json.Marshal(out)
}
type CRLDistributionPoints []string
type SubjAuthKeyId []byte
func (kid SubjAuthKeyId) MarshalJSON() ([]byte, error) {
enc := hex.EncodeToString(kid)
return json.Marshal(enc)
}
type ExtendedKeyUsage []ExtKeyUsage
type ExtendedKeyUsageExtension struct {
Known ExtendedKeyUsage
Unknown []asn1.ObjectIdentifier
}
// MarshalJSON implements the json.Marshal interface. The output is a struct of
// bools, with an additional `Value` field containing the actual OIDs.
func (e *ExtendedKeyUsageExtension) MarshalJSON() ([]byte, error) {
aux := new(auxExtendedKeyUsage)
for _, e := range e.Known {
aux.populateFromExtKeyUsage(e)
}
for _, oid := range e.Unknown {
aux.Unknown = append(aux.Unknown, oid.String())
}
return json.Marshal(aux)
}
func (e *ExtendedKeyUsageExtension) UnmarshalJSON(b []byte) error {
aux := new(auxExtendedKeyUsage)
if err := json.Unmarshal(b, aux); err != nil {
return err
}
// TODO: Generate the reverse functions.
return nil
}
//go:generate go run extended_key_usage_gen.go
// The string functions for CertValidationLevel are auto-generated via
// `go generate <full_path_to_x509_package>` or running `go generate` in the package directory
//go:generate stringer -type=CertValidationLevel -output=generated_certvalidationlevel_string.go
type CertValidationLevel int
const (
UnknownValidationLevel CertValidationLevel = 0
DV CertValidationLevel = 1
OV CertValidationLevel = 2
EV CertValidationLevel = 3
)
func (c *CertValidationLevel) MarshalJSON() ([]byte, error) {
if *c == UnknownValidationLevel || *c < 0 || *c > EV {
return json.Marshal("unknown")
}
return json.Marshal(c.String())
}
// TODO: All of validation-level maps should be auto-generated from
// https://github.com/zmap/constants.
// ExtendedValidationOIDs contains the UNION of Chromium
// (https://chromium.googlesource.com/chromium/src/net/+/master/cert/ev_root_ca_metadata.cc)
// and Firefox
// (http://hg.mozilla.org/mozilla-central/file/tip/security/certverifier/ExtendedValidation.cpp)
// EV OID lists
var ExtendedValidationOIDs = map[string]interface{}{
// CA/Browser Forum EV OID standard
// https://cabforum.org/object-registry/
"2.23.140.1.1": nil,
// CA/Browser Forum EV Code Signing
"2.23.140.1.3": nil,
// CA/Browser Forum .onion EV Certs
"2.23.140.1.31": nil,
// AC Camerfirma S.A. Chambers of Commerce Root - 2008
// https://www.camerfirma.com
// AC Camerfirma uses the last two arcs to track how the private key
// is managed - the effective verification policy is the same.
"1.3.6.1.4.1.17326.10.14.2.1.2": nil,
"1.3.6.1.4.1.17326.10.14.2.2.2": nil,
// AC Camerfirma S.A. Global Chambersign Root - 2008
// https://server2.camerfirma.com:8082
// AC Camerfirma uses the last two arcs to track how the private key
// is managed - the effective verification policy is the same.
"1.3.6.1.4.1.17326.10.8.12.1.2": nil,
"1.3.6.1.4.1.17326.10.8.12.2.2": nil,
// Actalis Authentication Root CA
// https://ssltest-a.actalis.it:8443
"1.3.159.1.17.1": nil,
// AffirmTrust Commercial
// https://commercial.affirmtrust.com/
"1.3.6.1.4.1.34697.2.1": nil,
// AffirmTrust Networking
// https://networking.affirmtrust.com:4431
"1.3.6.1.4.1.34697.2.2": nil,
// AffirmTrust Premium
// https://premium.affirmtrust.com:4432/
"1.3.6.1.4.1.34697.2.3": nil,
// AffirmTrust Premium ECC
// https://premiumecc.affirmtrust.com:4433/
"1.3.6.1.4.1.34697.2.4": nil,
// Autoridad de Certificacion Firmaprofesional CIF A62634068
// https://publifirma.firmaprofesional.com/
"1.3.6.1.4.1.13177.10.1.3.10": nil,
// Buypass Class 3 CA 1
// https://valid.evident.ca13.ssl.buypass.no/
"2.16.578.1.26.1.3.3": nil,
// Certification Authority of WoSign
// CA 沃通根证书
// https://root2evtest.wosign.com/
"1.3.6.1.4.1.36305.2": nil,
// CertPlus Class 2 Primary CA (KEYNECTIS)
// https://www.keynectis.com/
"1.3.6.1.4.1.22234.2.5.2.3.1": nil,
// Certum Trusted Network CA
// https://juice.certum.pl/
"1.2.616.1.113527.2.5.1.1": nil,
// China Internet Network Information Center EV Certificates Root
// https://evdemo.cnnic.cn/
"1.3.6.1.4.1.29836.1.10": nil,
// COMODO Certification Authority & USERTrust RSA Certification Authority & UTN-USERFirst-Hardware & AddTrust External CA Root
// https://secure.comodo.com/
// https://usertrustrsacertificationauthority-ev.comodoca.com/
// https://addtrustexternalcaroot-ev.comodoca.com
"1.3.6.1.4.1.6449.1.2.1.5.1": nil,
// Cybertrust Global Root & GTE CyberTrust Global Root & Baltimore CyberTrust Root
// https://evup.cybertrust.ne.jp/ctj-ev-upgrader/evseal.gif
// https://www.cybertrust.ne.jp/
// https://secure.omniroot.com/repository/
"1.3.6.1.4.1.6334.1.100.1": nil,
// DigiCert High Assurance EV Root CA
// https://www.digicert.com
"2.16.840.1.114412.2.1": nil,
// D-TRUST Root Class 3 CA 2 EV 2009
// https://certdemo-ev-valid.ssl.d-trust.net/
"1.3.6.1.4.1.4788.2.202.1": nil,
// Entrust.net Secure Server Certification Authority
// https://www.entrust.net/
"2.16.840.1.114028.10.1.2": nil,
// E-Tugra Certification Authority
// https://sslev.e-tugra.com.tr
"2.16.792.3.0.4.1.1.4": nil,
// GeoTrust Primary Certification Authority
// https://www.geotrust.com/
"1.3.6.1.4.1.14370.1.6": nil,
// GlobalSign Root CA - R2
// https://www.globalsign.com/
"1.3.6.1.4.1.4146.1.1": nil,
// Go Daddy Class 2 Certification Authority & Go Daddy Root Certificate Authority - G2
// https://www.godaddy.com/
// https://valid.gdig2.catest.godaddy.com/
"2.16.840.1.114413.1.7.23.3": nil,
// Izenpe.com - SHA256 root
// The first OID is for businesses and the second for government entities.
// These are the test sites, respectively:
// https://servicios.izenpe.com
// https://servicios1.izenpe.com
// Windows XP finds this, SHA1, root instead. The policy OIDs are the same
// as for the SHA256 root, above.
"1.3.6.1.4.1.14777.6.1.1": nil,
"1.3.6.1.4.1.14777.6.1.2": nil,
// Network Solutions Certificate Authority
// https://www.networksolutions.com/website-packages/index.jsp
"1.3.6.1.4.1.782.1.2.1.8.1": nil,
// QuoVadis Root CA 2
// https://www.quovadis.bm/
"1.3.6.1.4.1.8024.0.2.100.1.2": nil,
// SecureTrust CA, SecureTrust Corporation
// https://www.securetrust.com
// https://www.trustwave.com/
"2.16.840.1.114404.1.1.2.4.1": nil,
// Security Communication RootCA1
// https://www.secomtrust.net/contact/form.html
"1.2.392.200091.100.721.1": nil,
// Staat der Nederlanden EV Root CA
// https://pkioevssl-v.quovadisglobal.com/
"2.16.528.1.1003.1.2.7": nil,
// StartCom Certification Authority
// https://www.startssl.com/
"1.3.6.1.4.1.23223.1.1.1": nil,
// Starfield Class 2 Certification Authority
// https://www.starfieldtech.com/
"2.16.840.1.114414.1.7.23.3": nil,
// Starfield Services Root Certificate Authority - G2
// https://valid.sfsg2.catest.starfieldtech.com/
"2.16.840.1.114414.1.7.24.3": nil,
// SwissSign Gold CA - G2
// https://testevg2.swisssign.net/
"2.16.756.1.89.1.2.1.1": nil,
// Swisscom Root EV CA 2
// https://test-quarz-ev-ca-2.pre.swissdigicert.ch
"2.16.756.1.83.21.0": nil,
// thawte Primary Root CA
// https://www.thawte.com/
"2.16.840.1.113733.1.7.48.1": nil,
// TWCA Global Root CA
// https://evssldemo3.twca.com.tw/index.html
"1.3.6.1.4.1.40869.1.1.22.3": nil,
// T-TeleSec GlobalRoot Class 3
// http://www.telesec.de/ / https://root-class3.test.telesec.de/
"1.3.6.1.4.1.7879.13.24.1": nil,
// VeriSign Class 3 Public Primary Certification Authority - G5
// https://www.verisign.com/
"2.16.840.1.113733.1.7.23.6": nil,
// Wells Fargo WellsSecure Public Root Certificate Authority
// https://nerys.wellsfargo.com/test.html
"2.16.840.1.114171.500.9": nil,
// CN=CFCA EV ROOT,O=China Financial Certification Authority,C=CN
// https://www.cfca.com.cn/
"2.16.156.112554.3": nil,
// CN=OISTE WISeKey Global Root GB CA,OU=OISTE Foundation Endorsed,O=WISeKey,C=CH
// https://www.wisekey.com/repository/cacertificates/
"2.16.756.5.14.7.4.8": nil,
// CN=TÜRKTRUST Elektronik Sertifika Hizmet Sağlayıcısı H6,O=TÜRKTRUST Bilgi İletişim ve Bilişim Güvenliği Hizmetleri A...,L=Ankara,C=TR
// https://www.turktrust.com.tr/
"2.16.792.3.0.3.1.1.5": nil,
}
// OrganizationValidationOIDs contains CA specific OV OIDs from
// https://cabforum.org/object-registry/
var OrganizationValidationOIDs = map[string]interface{}{
// CA/Browser Forum OV OID standard
// https://cabforum.org/object-registry/
"2.23.140.1.2.2": nil,
// CA/Browser Forum individually validated
"2.23.140.1.2.3": nil,
// Digicert
"2.16.840.1.114412.1.1": nil,
// D-Trust
"1.3.6.1.4.1.4788.2.200.1": nil,
// GoDaddy
"2.16.840.1.114413.1.7.23.2": nil,
// Logius
"2.16.528.1.1003.1.2.5.6": nil,
// QuoVadis
"1.3.6.1.4.1.8024.0.2.100.1.1": nil,
// Starfield
"2.16.840.1.114414.1.7.23.2": nil,
// TurkTrust
"2.16.792.3.0.3.1.1.2": nil,
}
// DomainValidationOIDs contain OIDs that identify DV certs.
var DomainValidationOIDs = map[string]interface{}{
// Globalsign
"1.3.6.1.4.1.4146.1.10.10": nil,
// Let's Encrypt
"1.3.6.1.4.1.44947.1.1.1": nil,
// Comodo (eNom)
"1.3.6.1.4.1.6449.1.2.2.10": nil,
// Comodo (WoTrust)
"1.3.6.1.4.1.6449.1.2.2.15": nil,
// Comodo (RBC SOFT)
"1.3.6.1.4.1.6449.1.2.2.16": nil,
// Comodo (RegisterFly)
"1.3.6.1.4.1.6449.1.2.2.17": nil,
// Comodo (Central Security Patrols)
"1.3.6.1.4.1.6449.1.2.2.18": nil,
// Comodo (eBiz Networks)
"1.3.6.1.4.1.6449.1.2.2.19": nil,
// Comodo (OptimumSSL)
"1.3.6.1.4.1.6449.1.2.2.21": nil,
// Comodo (WoSign)
"1.3.6.1.4.1.6449.1.2.2.22": nil,
// Comodo (Register.com)
"1.3.6.1.4.1.6449.1.2.2.24": nil,
// Comodo (The Code Project)
"1.3.6.1.4.1.6449.1.2.2.25": nil,
// Comodo (Gandi)
"1.3.6.1.4.1.6449.1.2.2.26": nil,
// Comodo (GlobeSSL)
"1.3.6.1.4.1.6449.1.2.2.27": nil,
// Comodo (DreamHost)
"1.3.6.1.4.1.6449.1.2.2.28": nil,
// Comodo (TERENA)
"1.3.6.1.4.1.6449.1.2.2.29": nil,
// Comodo (GlobalSSL)
"1.3.6.1.4.1.6449.1.2.2.31": nil,
// Comodo (IceWarp)
"1.3.6.1.4.1.6449.1.2.2.35": nil,
// Comodo (Dotname Korea)
"1.3.6.1.4.1.6449.1.2.2.37": nil,
// Comodo (TrustSign)
"1.3.6.1.4.1.6449.1.2.2.38": nil,
// Comodo (Formidable)
"1.3.6.1.4.1.6449.1.2.2.39": nil,
// Comodo (SSL Blindado)
"1.3.6.1.4.1.6449.1.2.2.40": nil,
// Comodo (Dreamscape Networks)
"1.3.6.1.4.1.6449.1.2.2.41": nil,
// Comodo (K Software)
"1.3.6.1.4.1.6449.1.2.2.42": nil,
// Comodo (FBS)
"1.3.6.1.4.1.6449.1.2.2.44": nil,
// Comodo (ReliaSite)
"1.3.6.1.4.1.6449.1.2.2.45": nil,
// Comodo (CertAssure)
"1.3.6.1.4.1.6449.1.2.2.47": nil,
// Comodo (TrustAsia)
"1.3.6.1.4.1.6449.1.2.2.49": nil,
// Comodo (SecureCore)
"1.3.6.1.4.1.6449.1.2.2.50": nil,
// Comodo (Western Digital)
"1.3.6.1.4.1.6449.1.2.2.51": nil,
// Comodo (cPanel)
"1.3.6.1.4.1.6449.1.2.2.52": nil,
// Comodo (BlackCert)
"1.3.6.1.4.1.6449.1.2.2.53": nil,
// Comodo (KeyNet Systems)
"1.3.6.1.4.1.6449.1.2.2.54": nil,
// Comodo
"1.3.6.1.4.1.6449.1.2.2.7": nil,
// Comodo (CSC)
"1.3.6.1.4.1.6449.1.2.2.8": nil,
// Digicert
"2.16.840.1.114412.1.2": nil,
// GoDaddy
"2.16.840.1.114413.1.7.23.1": nil,
// Starfield
"2.16.840.1.114414.1.7.23.1": nil,
// CA/B Forum
"2.23.140.1.2.1": nil,
}
// TODO pull out other types
type AuthorityInfoAccess struct {
OCSPServer []string `json:"ocsp_urls,omitempty"`
IssuingCertificateURL []string `json:"issuer_urls,omitempty"`
}
/*
id-CABFOrganizationIdentifier OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) international-organizations(23) ca-browser-forum(140) certificate-extensions(3) cabf-organization-identifier(1) }
ext-CABFOrganizationIdentifier EXTENSION ::= { SYNTAX CABFOrganizationIdentifier IDENTIFIED BY id-CABFOrganizationIdentifier }
CABFOrganizationIdentifier ::= SEQUENCE {
registrationSchemeIdentifier PrintableString (SIZE(3)),
registrationCountry PrintableString (SIZE(2)),
registrationStateOrProvince [0] IMPLICIT PrintableString OPTIONAL (SIZE(0..128)),
registrationReference UTF8String
}
*/
type CABFOrganizationIDASN struct {
RegistrationSchemeIdentifier string `asn1:"printable"`
RegistrationCountry string `asn1:"printable"`
RegistrationStateOrProvince string `asn1:"printable,optional,tag:0"`
RegistrationReference string `asn1:"utf8"`
}
type CABFOrganizationIdentifier struct {
Scheme string `json:"scheme,omitempty"`
Country string `json:"country,omitempty"`
State string `json:"state,omitempty"`
Reference string `json:"reference,omitempty"`
}
func (c *Certificate) jsonifyExtensions() (*CertificateExtensions, UnknownCertificateExtensions) {
exts := new(CertificateExtensions)
unk := make([]pkix.Extension, 0, 2)
for _, e := range c.Extensions {
if e.Id.Equal(oidExtKeyUsage) {
exts.KeyUsage = c.KeyUsage
} else if e.Id.Equal(oidExtBasicConstraints) {
exts.BasicConstraints = new(BasicConstraints)
exts.BasicConstraints.IsCA = c.IsCA
if c.MaxPathLen > 0 || c.MaxPathLenZero {
exts.BasicConstraints.MaxPathLen = new(int)
*exts.BasicConstraints.MaxPathLen = c.MaxPathLen
}
} else if e.Id.Equal(oidExtSubjectAltName) {
exts.SubjectAltName = new(GeneralNames)
exts.SubjectAltName.DirectoryNames = c.DirectoryNames
exts.SubjectAltName.DNSNames = c.DNSNames
exts.SubjectAltName.EDIPartyNames = c.EDIPartyNames
exts.SubjectAltName.EmailAddresses = c.EmailAddresses
exts.SubjectAltName.IPAddresses = c.IPAddresses
exts.SubjectAltName.OtherNames = c.OtherNames
exts.SubjectAltName.RegisteredIDs = c.RegisteredIDs
exts.SubjectAltName.URIs = c.URIs
} else if e.Id.Equal(oidExtIssuerAltName) {
exts.IssuerAltName = new(GeneralNames)
exts.IssuerAltName.DirectoryNames = c.IANDirectoryNames
exts.IssuerAltName.DNSNames = c.IANDNSNames
exts.IssuerAltName.EDIPartyNames = c.IANEDIPartyNames
exts.IssuerAltName.EmailAddresses = c.IANEmailAddresses
exts.IssuerAltName.IPAddresses = c.IANIPAddresses
exts.IssuerAltName.OtherNames = c.IANOtherNames
exts.IssuerAltName.RegisteredIDs = c.IANRegisteredIDs
exts.IssuerAltName.URIs = c.IANURIs
} else if e.Id.Equal(oidExtNameConstraints) {
exts.NameConstraints = new(NameConstraints)
exts.NameConstraints.Critical = c.NameConstraintsCritical
exts.NameConstraints.PermittedDNSNames = c.PermittedDNSNames
exts.NameConstraints.PermittedEmailAddresses = c.PermittedEmailAddresses
exts.NameConstraints.PermittedURIs = c.PermittedURIs
exts.NameConstraints.PermittedIPAddresses = c.PermittedIPAddresses
exts.NameConstraints.PermittedDirectoryNames = c.PermittedDirectoryNames
exts.NameConstraints.PermittedEdiPartyNames = c.PermittedEdiPartyNames
exts.NameConstraints.PermittedRegisteredIDs = c.PermittedRegisteredIDs
exts.NameConstraints.ExcludedEmailAddresses = c.ExcludedEmailAddresses
exts.NameConstraints.ExcludedDNSNames = c.ExcludedDNSNames
exts.NameConstraints.ExcludedURIs = c.ExcludedURIs
exts.NameConstraints.ExcludedIPAddresses = c.ExcludedIPAddresses
exts.NameConstraints.ExcludedDirectoryNames = c.ExcludedDirectoryNames
exts.NameConstraints.ExcludedEdiPartyNames = c.ExcludedEdiPartyNames
exts.NameConstraints.ExcludedRegisteredIDs = c.ExcludedRegisteredIDs
} else if e.Id.Equal(oidCRLDistributionPoints) {
exts.CRLDistributionPoints = c.CRLDistributionPoints
} else if e.Id.Equal(oidExtAuthKeyId) {
exts.AuthKeyID = c.AuthorityKeyId
} else if e.Id.Equal(oidExtExtendedKeyUsage) {
exts.ExtendedKeyUsage = new(ExtendedKeyUsageExtension)
exts.ExtendedKeyUsage.Known = c.ExtKeyUsage
exts.ExtendedKeyUsage.Unknown = c.UnknownExtKeyUsage
} else if e.Id.Equal(oidExtCertificatePolicy) {
exts.CertificatePolicies = new(CertificatePoliciesData)
exts.CertificatePolicies.PolicyIdentifiers = c.PolicyIdentifiers
exts.CertificatePolicies.NoticeRefNumbers = c.NoticeRefNumbers
exts.CertificatePolicies.NoticeRefOrganization = c.ParsedNoticeRefOrganization
exts.CertificatePolicies.ExplicitTexts = c.ParsedExplicitTexts
exts.CertificatePolicies.QualifierId = c.QualifierId
exts.CertificatePolicies.CPSUri = c.CPSuri
} else if e.Id.Equal(oidExtAuthorityInfoAccess) {
exts.AuthorityInfoAccess = new(AuthorityInfoAccess)
exts.AuthorityInfoAccess.OCSPServer = c.OCSPServer
exts.AuthorityInfoAccess.IssuingCertificateURL = c.IssuingCertificateURL
} else if e.Id.Equal(oidExtSubjectKeyId) {
exts.SubjectKeyID = c.SubjectKeyId
} else if e.Id.Equal(oidExtSignedCertificateTimestampList) {
exts.SignedCertificateTimestampList = c.SignedCertificateTimestampList
} else if e.Id.Equal(oidExtensionCTPrecertificatePoison) {
exts.IsPrecert = true
} else if e.Id.Equal(oidBRTorServiceDescriptor) {
exts.TorServiceDescriptors = c.TorServiceDescriptors
} else if e.Id.Equal(oidExtCABFOrganizationID) {
exts.CABFOrganizationIdentifier = c.CABFOrganizationIdentifier
} else if e.Id.Equal(oidExtQCStatements) {
exts.QCStatements = c.QCStatements
} else {
// Unknown extension
unk = append(unk, e)
}
}
return exts, unk
}

61
vendor/github.com/zmap/zcrypto/x509/fingerprint.go generated vendored Normal file
View file

@ -0,0 +1,61 @@
// Copyright 2015 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 x509
import (
"bytes"
"crypto/md5"
"crypto/sha1"
"crypto/sha256"
"crypto/sha512"
"encoding/hex"
"encoding/json"
)
// CertificateFingerprint represents a digest/fingerprint of some data. It can
// easily be encoded to hex and JSON (as a hex string).
type CertificateFingerprint []byte
// MD5Fingerprint creates a fingerprint of data using the MD5 hash algorithm.
func MD5Fingerprint(data []byte) CertificateFingerprint {
sum := md5.Sum(data)
return sum[:]
}
// SHA1Fingerprint creates a fingerprint of data using the SHA1 hash algorithm.
func SHA1Fingerprint(data []byte) CertificateFingerprint {
sum := sha1.Sum(data)
return sum[:]
}
// SHA256Fingerprint creates a fingerprint of data using the SHA256 hash
// algorithm.
func SHA256Fingerprint(data []byte) CertificateFingerprint {
sum := sha256.Sum256(data)
return sum[:]
}
// SHA512Fingerprint creates a fingerprint of data using the SHA256 hash
// algorithm.
func SHA512Fingerprint(data []byte) CertificateFingerprint {
sum := sha512.Sum512(data)
return sum[:]
}
// Equal returns true if the fingerprints are bytewise-equal.
func (f CertificateFingerprint) Equal(other CertificateFingerprint) bool {
return bytes.Equal(f, other)
}
// Hex returns the given fingerprint encoded as a hex string.
func (f CertificateFingerprint) Hex() string {
return hex.EncodeToString(f)
}
// MarshalJSON implements the json.Marshaler interface, and marshals the
// fingerprint as a hex string.
func (f *CertificateFingerprint) MarshalJSON() ([]byte, error) {
return json.Marshal(f.Hex())
}

View file

@ -0,0 +1,16 @@
// Code generated by "stringer -type=CertValidationLevel -output=generated_certvalidationlevel_string.go"; DO NOT EDIT.
package x509
import "strconv"
const _CertValidationLevel_name = "UnknownValidationLevelDVOVEV"
var _CertValidationLevel_index = [...]uint8{0, 22, 24, 26, 28}
func (i CertValidationLevel) String() string {
if i < 0 || i >= CertValidationLevel(len(_CertValidationLevel_index)-1) {
return "CertValidationLevel(" + strconv.FormatInt(int64(i), 10) + ")"
}
return _CertValidationLevel_name[_CertValidationLevel_index[i]:_CertValidationLevel_index[i+1]]
}

652
vendor/github.com/zmap/zcrypto/x509/json.go generated vendored Normal file
View file

@ -0,0 +1,652 @@
// Copyright 2015 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 x509
import (
"crypto/ecdsa"
"crypto/rsa"
"encoding/asn1"
"encoding/json"
"errors"
"net"
"sort"
"github.com/zmap/zcrypto/dsa"
"strings"
"time"
jsonKeys "github.com/zmap/zcrypto/json"
"github.com/zmap/zcrypto/util"
"github.com/zmap/zcrypto/x509/pkix"
)
var kMinTime, kMaxTime time.Time
func init() {
var err error
kMinTime, err = time.Parse(time.RFC3339, "1970-01-01T00:00:00Z")
if err != nil {
panic(err)
}
kMaxTime, err = time.Parse(time.RFC3339, "9999-12-31T23:59:59Z")
if err != nil {
panic(err)
}
}
type auxKeyUsage struct {
DigitalSignature bool `json:"digital_signature,omitempty"`
ContentCommitment bool `json:"content_commitment,omitempty"`
KeyEncipherment bool `json:"key_encipherment,omitempty"`
DataEncipherment bool `json:"data_encipherment,omitempty"`
KeyAgreement bool `json:"key_agreement,omitempty"`
CertificateSign bool `json:"certificate_sign,omitempty"`
CRLSign bool `json:"crl_sign,omitempty"`
EncipherOnly bool `json:"encipher_only,omitempty"`
DecipherOnly bool `json:"decipher_only,omitempty"`
Value uint32 `json:"value"`
}
// MarshalJSON implements the json.Marshaler interface
func (k KeyUsage) MarshalJSON() ([]byte, error) {
var enc auxKeyUsage
enc.Value = uint32(k)
if k&KeyUsageDigitalSignature > 0 {
enc.DigitalSignature = true
}
if k&KeyUsageContentCommitment > 0 {
enc.ContentCommitment = true
}
if k&KeyUsageKeyEncipherment > 0 {
enc.KeyEncipherment = true
}
if k&KeyUsageDataEncipherment > 0 {
enc.DataEncipherment = true
}
if k&KeyUsageKeyAgreement > 0 {
enc.KeyAgreement = true
}
if k&KeyUsageCertSign > 0 {
enc.CertificateSign = true
}
if k&KeyUsageCRLSign > 0 {
enc.CRLSign = true
}
if k&KeyUsageEncipherOnly > 0 {
enc.EncipherOnly = true
}
if k&KeyUsageDecipherOnly > 0 {
enc.DecipherOnly = true
}
return json.Marshal(&enc)
}
// UnmarshalJSON implements the json.Unmarshler interface
func (k *KeyUsage) UnmarshalJSON(b []byte) error {
var aux auxKeyUsage
if err := json.Unmarshal(b, &aux); err != nil {
return err
}
// TODO: validate the flags match
v := int(aux.Value)
*k = KeyUsage(v)
return nil
}
// JSONSignatureAlgorithm is the intermediate type
// used when marshaling a PublicKeyAlgorithm out to JSON.
type JSONSignatureAlgorithm struct {
Name string `json:"name,omitempty"`
OID pkix.AuxOID `json:"oid"`
}
// MarshalJSON implements the json.Marshaler interface
// MAY NOT PRESERVE ORIGINAL OID FROM CERTIFICATE -
// CONSIDER USING jsonifySignatureAlgorithm INSTEAD!
func (s *SignatureAlgorithm) MarshalJSON() ([]byte, error) {
aux := JSONSignatureAlgorithm{
Name: s.String(),
}
for _, val := range signatureAlgorithmDetails {
if val.algo == *s {
aux.OID = make([]int, len(val.oid))
for idx := range val.oid {
aux.OID[idx] = val.oid[idx]
}
}
}
return json.Marshal(&aux)
}
// UnmarshalJSON implements the json.Unmarshler interface
func (s *SignatureAlgorithm) UnmarshalJSON(b []byte) error {
var aux JSONSignatureAlgorithm
if err := json.Unmarshal(b, &aux); err != nil {
return err
}
*s = UnknownSignatureAlgorithm
oid := asn1.ObjectIdentifier(aux.OID.AsSlice())
if oid.Equal(oidSignatureRSAPSS) {
pssAlgs := []SignatureAlgorithm{SHA256WithRSAPSS, SHA384WithRSAPSS, SHA512WithRSAPSS}
for _, alg := range pssAlgs {
if strings.Compare(alg.String(), aux.Name) == 0 {
*s = alg
break
}
}
} else {
for _, val := range signatureAlgorithmDetails {
if val.oid.Equal(oid) {
*s = val.algo
break
}
}
}
return nil
}
// jsonifySignatureAlgorithm gathers the necessary fields in a Certificate
// into a JSONSignatureAlgorithm, which can then use the default
// JSON marhsalers and unmarshalers. THIS FUNCTION IS PREFERED OVER
// THE CUSTOM JSON MARSHALER PRESENTED ABOVE FOR SIGNATUREALGORITHM
// BECAUSE THIS METHOD PRESERVES THE OID ORIGINALLY IN THE CERTIFICATE!
// This reason also explains why we need this function -
// the OID is unfortunately stored outside the scope of a
// SignatureAlgorithm struct and cannot be recovered without access to the
// entire Certificate if we do not know the signature algorithm.
func (c *Certificate) jsonifySignatureAlgorithm() JSONSignatureAlgorithm {
aux := JSONSignatureAlgorithm{}
if c.SignatureAlgorithm == 0 {
aux.Name = "unknown_algorithm"
} else {
aux.Name = c.SignatureAlgorithm.String()
}
aux.OID = make([]int, len(c.SignatureAlgorithmOID))
for idx := range c.SignatureAlgorithmOID {
aux.OID[idx] = c.SignatureAlgorithmOID[idx]
}
return aux
}
type auxPublicKeyAlgorithm struct {
Name string `json:"name,omitempty"`
OID *pkix.AuxOID `json:"oid,omitempty"`
}
var publicKeyNameToAlgorithm = map[string]PublicKeyAlgorithm{
"RSA": RSA,
"DSA": DSA,
"ECDSA": ECDSA,
}
// MarshalJSON implements the json.Marshaler interface
func (p *PublicKeyAlgorithm) MarshalJSON() ([]byte, error) {
aux := auxPublicKeyAlgorithm{
Name: p.String(),
}
return json.Marshal(&aux)
}
// UnmarshalJSON implements the json.Unmarshaler interface
func (p *PublicKeyAlgorithm) UnmarshalJSON(b []byte) error {
var aux auxPublicKeyAlgorithm
if err := json.Unmarshal(b, &aux); err != nil {
return err
}
*p = publicKeyNameToAlgorithm[aux.Name]
return nil
}
func clampTime(t time.Time) time.Time {
if t.Before(kMinTime) {
return kMinTime
}
if t.After(kMaxTime) {
return kMaxTime
}
return t
}
type auxValidity struct {
Start string `json:"start"`
End string `json:"end"`
ValidityPeriod int `json:"length"`
}
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()),
}
return json.Marshal(&aux)
}
func (v *validity) UnmarshalJSON(b []byte) error {
var aux auxValidity
if err := json.Unmarshal(b, &aux); err != nil {
return err
}
var err error
if v.NotBefore, err = time.Parse(time.RFC3339, aux.Start); err != nil {
return err
}
if v.NotAfter, err = time.Parse(time.RFC3339, aux.End); err != nil {
return err
}
return nil
}
// ECDSAPublicKeyJSON - used to condense several fields from a
// ECDSA public key into one field for use in JSONCertificate.
// Uses default JSON marshal and unmarshal methods
type ECDSAPublicKeyJSON struct {
B []byte `json:"b"`
Curve string `json:"curve"`
Gx []byte `json:"gx"`
Gy []byte `json:"gy"`
Length int `json:"length"`
N []byte `json:"n"`
P []byte `json:"p"`
Pub []byte `json:"pub,omitempty"`
X []byte `json:"x"`
Y []byte `json:"y"`
}
// DSAPublicKeyJSON - used to condense several fields from a
// DSA public key into one field for use in JSONCertificate.
// Uses default JSON marshal and unmarshal methods
type DSAPublicKeyJSON struct {
G []byte `json:"g"`
P []byte `json:"p"`
Q []byte `json:"q"`
Y []byte `json:"y"`
}
// GetDSAPublicKeyJSON - get the DSAPublicKeyJSON for the given standard DSA PublicKey.
func GetDSAPublicKeyJSON(key *dsa.PublicKey) *DSAPublicKeyJSON {
return &DSAPublicKeyJSON{
P: key.P.Bytes(),
Q: key.Q.Bytes(),
G: key.G.Bytes(),
Y: key.Y.Bytes(),
}
}
// GetRSAPublicKeyJSON - get the jsonKeys.RSAPublicKey for the given standard RSA PublicKey.
func GetRSAPublicKeyJSON(key *rsa.PublicKey) *jsonKeys.RSAPublicKey {
rsaKey := new(jsonKeys.RSAPublicKey)
rsaKey.PublicKey = key
return rsaKey
}
// GetECDSAPublicKeyJSON - get the GetECDSAPublicKeyJSON for the given standard ECDSA PublicKey.
func GetECDSAPublicKeyJSON(key *ecdsa.PublicKey) *ECDSAPublicKeyJSON {
params := key.Params()
return &ECDSAPublicKeyJSON{
P: params.P.Bytes(),
N: params.N.Bytes(),
B: params.B.Bytes(),
Gx: params.Gx.Bytes(),
Gy: params.Gy.Bytes(),
X: key.X.Bytes(),
Y: key.Y.Bytes(),
Curve: key.Curve.Params().Name,
Length: key.Curve.Params().BitSize,
}
}
// GetAugmentedECDSAPublicKeyJSON - get the GetECDSAPublicKeyJSON for the given "augmented"
// ECDSA PublicKey.
func GetAugmentedECDSAPublicKeyJSON(key *AugmentedECDSA) *ECDSAPublicKeyJSON {
params := key.Pub.Params()
return &ECDSAPublicKeyJSON{
P: params.P.Bytes(),
N: params.N.Bytes(),
B: params.B.Bytes(),
Gx: params.Gx.Bytes(),
Gy: params.Gy.Bytes(),
X: key.Pub.X.Bytes(),
Y: key.Pub.Y.Bytes(),
Curve: key.Pub.Curve.Params().Name,
Length: key.Pub.Curve.Params().BitSize,
Pub: key.Raw.Bytes,
}
}
// jsonifySubjectKey - Convert public key data in a Certificate
// into json output format for JSONCertificate
func (c *Certificate) jsonifySubjectKey() JSONSubjectKeyInfo {
j := JSONSubjectKeyInfo{
KeyAlgorithm: c.PublicKeyAlgorithm,
SPKIFingerprint: c.SPKIFingerprint,
}
switch key := c.PublicKey.(type) {
case *rsa.PublicKey:
rsaKey := new(jsonKeys.RSAPublicKey)
rsaKey.PublicKey = key
j.RSAPublicKey = rsaKey
case *dsa.PublicKey:
j.DSAPublicKey = &DSAPublicKeyJSON{
P: key.P.Bytes(),
Q: key.Q.Bytes(),
G: key.G.Bytes(),
Y: key.Y.Bytes(),
}
case *ecdsa.PublicKey:
params := key.Params()
j.ECDSAPublicKey = &ECDSAPublicKeyJSON{
P: params.P.Bytes(),
N: params.N.Bytes(),
B: params.B.Bytes(),
Gx: params.Gx.Bytes(),
Gy: params.Gy.Bytes(),
X: key.X.Bytes(),
Y: key.Y.Bytes(),
Curve: key.Curve.Params().Name,
Length: key.Curve.Params().BitSize,
}
case *AugmentedECDSA:
params := key.Pub.Params()
j.ECDSAPublicKey = &ECDSAPublicKeyJSON{
P: params.P.Bytes(),
N: params.N.Bytes(),
B: params.B.Bytes(),
Gx: params.Gx.Bytes(),
Gy: params.Gy.Bytes(),
X: key.Pub.X.Bytes(),
Y: key.Pub.Y.Bytes(),
Curve: key.Pub.Curve.Params().Name,
Length: key.Pub.Curve.Params().BitSize,
Pub: key.Raw.Bytes,
}
}
return j
}
// JSONSubjectKeyInfo - used to condense several fields from x509.Certificate
// related to the subject public key into one field within JSONCertificate
// Unfortunately, this struct cannot have its own Marshal method since it
// needs information from multiple fields in x509.Certificate
type JSONSubjectKeyInfo struct {
KeyAlgorithm PublicKeyAlgorithm `json:"key_algorithm"`
RSAPublicKey *jsonKeys.RSAPublicKey `json:"rsa_public_key,omitempty"`
DSAPublicKey *DSAPublicKeyJSON `json:"dsa_public_key,omitempty"`
ECDSAPublicKey *ECDSAPublicKeyJSON `json:"ecdsa_public_key,omitempty"`
SPKIFingerprint CertificateFingerprint `json:"fingerprint_sha256"`
}
// JSONSignature - used to condense several fields from x509.Certificate
// related to the signature into one field within JSONCertificate
// Unfortunately, this struct cannot have its own Marshal method since it
// needs information from multiple fields in x509.Certificate
type JSONSignature struct {
SignatureAlgorithm JSONSignatureAlgorithm `json:"signature_algorithm"`
Value []byte `json:"value"`
Valid bool `json:"valid"`
SelfSigned bool `json:"self_signed"`
}
// JSONValidity - used to condense several fields related
// to validity in x509.Certificate into one field within JSONCertificate
// Unfortunately, this struct cannot have its own Marshal method since it
// needs information from multiple fields in x509.Certificate
type JSONValidity struct {
validity
ValidityPeriod int
}
// JSONCertificate - used to condense data from x509.Certificate when marhsaling
// into JSON. This struct has a distinct and independent layout from
// x509.Certificate, mostly for condensing data across repetitive
// fields and making it more presentable.
type JSONCertificate struct {
Version int `json:"version"`
SerialNumber string `json:"serial_number"`
SignatureAlgorithm JSONSignatureAlgorithm `json:"signature_algorithm"`
Issuer pkix.Name `json:"issuer"`
IssuerDN string `json:"issuer_dn,omitempty"`
Validity JSONValidity `json:"validity"`
Subject pkix.Name `json:"subject"`
SubjectDN string `json:"subject_dn,omitempty"`
SubjectKeyInfo JSONSubjectKeyInfo `json:"subject_key_info"`
Extensions *CertificateExtensions `json:"extensions,omitempty"`
UnknownExtensions UnknownCertificateExtensions `json:"unknown_extensions,omitempty"`
Signature JSONSignature `json:"signature"`
FingerprintMD5 CertificateFingerprint `json:"fingerprint_md5"`
FingerprintSHA1 CertificateFingerprint `json:"fingerprint_sha1"`
FingerprintSHA256 CertificateFingerprint `json:"fingerprint_sha256"`
FingerprintNoCT CertificateFingerprint `json:"tbs_noct_fingerprint"`
SPKISubjectFingerprint CertificateFingerprint `json:"spki_subject_fingerprint"`
TBSCertificateFingerprint CertificateFingerprint `json:"tbs_fingerprint"`
ValidationLevel CertValidationLevel `json:"validation_level"`
Names []string `json:"names,omitempty"`
Redacted bool `json:"redacted"`
}
// CollectAllNames - Collect and validate all DNS / URI / IP Address names for a given certificate
func (c *Certificate) CollectAllNames() []string {
var names []string
if isValidName(c.Subject.CommonName) {
names = append(names, c.Subject.CommonName)
}
for _, name := range c.DNSNames {
if isValidName(name) {
names = append(names, name)
} else if !strings.Contains(name, ".") { //just a TLD
names = append(names, name)
}
}
for _, name := range c.URIs {
if util.IsURL(name) {
names = append(names, name)
}
}
for _, name := range c.IPAddresses {
str := name.String()
if util.IsURL(str) {
names = append(names, str)
}
}
return purgeNameDuplicates(names)
}
func (c *Certificate) MarshalJSON() ([]byte, error) {
// Fill out the certificate
jc := new(JSONCertificate)
jc.Version = c.Version
jc.SerialNumber = c.SerialNumber.String()
jc.Issuer = c.Issuer
jc.IssuerDN = c.Issuer.String()
jc.Validity.NotBefore = c.NotBefore
jc.Validity.NotAfter = c.NotAfter
jc.Validity.ValidityPeriod = c.ValidityPeriod
jc.Subject = c.Subject
jc.SubjectDN = c.Subject.String()
jc.Names = c.CollectAllNames()
jc.Redacted = false
for _, name := range jc.Names {
if strings.HasPrefix(name, "?") {
jc.Redacted = true
}
}
jc.SubjectKeyInfo = c.jsonifySubjectKey()
jc.Extensions, jc.UnknownExtensions = c.jsonifyExtensions()
// TODO: Handle the fact this might not match
jc.SignatureAlgorithm = c.jsonifySignatureAlgorithm()
jc.Signature.SignatureAlgorithm = jc.SignatureAlgorithm
jc.Signature.Value = c.Signature
jc.Signature.Valid = c.validSignature
jc.Signature.SelfSigned = c.SelfSigned
if c.SelfSigned {
jc.Signature.Valid = true
}
jc.FingerprintMD5 = c.FingerprintMD5
jc.FingerprintSHA1 = c.FingerprintSHA1
jc.FingerprintSHA256 = c.FingerprintSHA256
jc.FingerprintNoCT = c.FingerprintNoCT
jc.SPKISubjectFingerprint = c.SPKISubjectFingerprint
jc.TBSCertificateFingerprint = c.TBSCertificateFingerprint
jc.ValidationLevel = c.ValidationLevel
return json.Marshal(jc)
}
// UnmarshalJSON - intentionally implimented to always error,
// as this method should not be used. The MarshalJSON method
// on Certificate condenses data in a way that is not recoverable.
// Use the x509.ParseCertificate function instead or
// JSONCertificateWithRaw Marshal method
func (jc *JSONCertificate) UnmarshalJSON(b []byte) error {
return errors.New("Do not unmarshal cert JSON directly, use JSONCertificateWithRaw or x509.ParseCertificate function")
}
// UnmarshalJSON - intentionally implimented to always error,
// as this method should not be used. The MarshalJSON method
// on Certificate condenses data in a way that is not recoverable.
// Use the x509.ParseCertificate function instead or
// JSONCertificateWithRaw Marshal method
func (c *Certificate) UnmarshalJSON(b []byte) error {
return errors.New("Do not unmarshal cert JSON directly, use JSONCertificateWithRaw or x509.ParseCertificate function")
}
// JSONCertificateWithRaw - intermediate struct for unmarshaling json
// of a certificate - the raw is require since the
// MarshalJSON method on Certificate condenses data in a way that
// makes extraction to the original in Unmarshal impossible.
// The JSON output of Marshal is not even used to construct
// a certificate, all we need is raw
type JSONCertificateWithRaw struct {
Raw []byte `json:"raw,omitempty"`
}
// ParseRaw - for converting the intermediate object
// JSONCertificateWithRaw into a parsed Certificate
// see description of JSONCertificateWithRaw for
// why this is used instead of UnmarshalJSON methods
func (c *JSONCertificateWithRaw) ParseRaw() (*Certificate, error) {
return ParseCertificate(c.Raw)
}
func purgeNameDuplicates(names []string) (out []string) {
hashset := make(map[string]bool, len(names))
for _, name := range names {
if _, inc := hashset[name]; !inc {
hashset[name] = true
}
}
out = make([]string, 0, len(hashset))
for key := range hashset {
out = append(out, key)
}
sort.Strings(out) // must sort to ensure output is deterministic!
return
}
func isValidName(name string) (ret bool) {
// Check for wildcards and redacts, ignore malformed urls
if strings.HasPrefix(name, "?.") || strings.HasPrefix(name, "*.") {
ret = isValidName(name[2:])
} else {
ret = util.IsURL(name)
}
return
}
func orMask(ip net.IP, mask net.IPMask) net.IP {
if len(ip) == 0 || len(mask) == 0 {
return nil
}
if len(ip) != net.IPv4len && len(ip) != net.IPv6len {
return nil
}
if len(ip) != len(mask) {
return nil
}
out := make([]byte, len(ip))
for idx := range ip {
out[idx] = ip[idx] | mask[idx]
}
return out
}
func invertMask(mask net.IPMask) net.IPMask {
if mask == nil {
return nil
}
out := make([]byte, len(mask))
for idx := range mask {
out[idx] = ^mask[idx]
}
return out
}
type auxGeneralSubtreeIP struct {
CIDR string `json:"cidr,omitempty"`
Begin string `json:"begin,omitempty"`
End string `json:"end,omitempty"`
Mask string `json:"mask,omitempty"`
}
func (g *GeneralSubtreeIP) MarshalJSON() ([]byte, error) {
aux := auxGeneralSubtreeIP{}
aux.CIDR = g.Data.String()
// Check to see if the subnet is valid. An invalid subnet will return 0,0
// from Size(). If the subnet is invalid, only output the CIDR.
ones, bits := g.Data.Mask.Size()
if ones == 0 && bits == 0 {
return json.Marshal(&aux)
}
// The first IP in the range should be `ip & mask`.
begin := g.Data.IP.Mask(g.Data.Mask)
if begin != nil {
aux.Begin = begin.String()
}
// The last IP (inclusive) is `ip & (^mask)`.
inverseMask := invertMask(g.Data.Mask)
end := orMask(g.Data.IP, inverseMask)
if end != nil {
aux.End = end.String()
}
// Output the mask as an IP, but enforce it can be formatted correctly.
// net.IP.String() only works on byte arrays of the correct length.
maskLen := len(g.Data.Mask)
if maskLen == net.IPv4len || maskLen == net.IPv6len {
maskAsIP := net.IP(g.Data.Mask)
aux.Mask = maskAsIP.String()
}
return json.Marshal(&aux)
}
func (g *GeneralSubtreeIP) UnmarshalJSON(b []byte) error {
aux := auxGeneralSubtreeIP{}
if err := json.Unmarshal(b, &aux); err != nil {
return err
}
ip, ipNet, err := net.ParseCIDR(aux.CIDR)
if err != nil {
return err
}
g.Data.IP = ip
g.Data.Mask = ipNet.Mask
g.Min = 0
g.Max = 0
return nil
}

30
vendor/github.com/zmap/zcrypto/x509/names.go generated vendored Normal file
View file

@ -0,0 +1,30 @@
// Copyright 2015 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 x509
func (p PublicKeyAlgorithm) String() string {
if p >= total_key_algorithms || p < 0 {
p = UnknownPublicKeyAlgorithm
}
return keyAlgorithmNames[p]
}
func (c *Certificate) SignatureAlgorithmName() string {
switch c.SignatureAlgorithm {
case UnknownSignatureAlgorithm:
return c.SignatureAlgorithmOID.String()
default:
return c.SignatureAlgorithm.String()
}
}
func (c *Certificate) PublicKeyAlgorithmName() string {
switch c.PublicKeyAlgorithm {
case UnknownPublicKeyAlgorithm:
return c.PublicKeyAlgorithmOID.String()
default:
return c.PublicKeyAlgorithm.String()
}
}

240
vendor/github.com/zmap/zcrypto/x509/pem_decrypt.go generated vendored Normal file
View file

@ -0,0 +1,240 @@
// Copyright 2012 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 x509
// RFC 1423 describes the encryption of PEM blocks. The algorithm used to
// generate a key from the password was derived by looking at the OpenSSL
// implementation.
import (
"crypto/aes"
"crypto/cipher"
"crypto/des"
"crypto/md5"
"encoding/hex"
"encoding/pem"
"errors"
"io"
"strings"
)
type PEMCipher int
// Possible values for the EncryptPEMBlock encryption algorithm.
const (
_ PEMCipher = iota
PEMCipherDES
PEMCipher3DES
PEMCipherAES128
PEMCipherAES192
PEMCipherAES256
)
// rfc1423Algo holds a method for enciphering a PEM block.
type rfc1423Algo struct {
cipher PEMCipher
name string
cipherFunc func(key []byte) (cipher.Block, error)
keySize int
blockSize int
}
// rfc1423Algos holds a slice of the possible ways to encrypt a PEM
// block. The ivSize numbers were taken from the OpenSSL source.
var rfc1423Algos = []rfc1423Algo{{
cipher: PEMCipherDES,
name: "DES-CBC",
cipherFunc: des.NewCipher,
keySize: 8,
blockSize: des.BlockSize,
}, {
cipher: PEMCipher3DES,
name: "DES-EDE3-CBC",
cipherFunc: des.NewTripleDESCipher,
keySize: 24,
blockSize: des.BlockSize,
}, {
cipher: PEMCipherAES128,
name: "AES-128-CBC",
cipherFunc: aes.NewCipher,
keySize: 16,
blockSize: aes.BlockSize,
}, {
cipher: PEMCipherAES192,
name: "AES-192-CBC",
cipherFunc: aes.NewCipher,
keySize: 24,
blockSize: aes.BlockSize,
}, {
cipher: PEMCipherAES256,
name: "AES-256-CBC",
cipherFunc: aes.NewCipher,
keySize: 32,
blockSize: aes.BlockSize,
},
}
// deriveKey uses a key derivation function to stretch the password into a key
// with the number of bits our cipher requires. This algorithm was derived from
// the OpenSSL source.
func (c rfc1423Algo) deriveKey(password, salt []byte) []byte {
hash := md5.New()
out := make([]byte, c.keySize)
var digest []byte
for i := 0; i < len(out); i += len(digest) {
hash.Reset()
hash.Write(digest)
hash.Write(password)
hash.Write(salt)
digest = hash.Sum(digest[:0])
copy(out[i:], digest)
}
return out
}
// IsEncryptedPEMBlock returns if the PEM block is password encrypted.
func IsEncryptedPEMBlock(b *pem.Block) bool {
_, ok := b.Headers["DEK-Info"]
return ok
}
// IncorrectPasswordError is returned when an incorrect password is detected.
var IncorrectPasswordError = errors.New("x509: decryption password incorrect")
// DecryptPEMBlock takes a password encrypted PEM block and the password used to
// encrypt it and returns a slice of decrypted DER encoded bytes. It inspects
// the DEK-Info header to determine the algorithm used for decryption. If no
// DEK-Info header is present, an error is returned. If an incorrect password
// is detected an IncorrectPasswordError is returned. Because of deficiencies
// in the encrypted-PEM format, it's not always possible to detect an incorrect
// password. In these cases no error will be returned but the decrypted DER
// bytes will be random noise.
func DecryptPEMBlock(b *pem.Block, password []byte) ([]byte, error) {
dek, ok := b.Headers["DEK-Info"]
if !ok {
return nil, errors.New("x509: no DEK-Info header in block")
}
idx := strings.Index(dek, ",")
if idx == -1 {
return nil, errors.New("x509: malformed DEK-Info header")
}
mode, hexIV := dek[:idx], dek[idx+1:]
ciph := cipherByName(mode)
if ciph == nil {
return nil, errors.New("x509: unknown encryption mode")
}
iv, err := hex.DecodeString(hexIV)
if err != nil {
return nil, err
}
if len(iv) != ciph.blockSize {
return nil, errors.New("x509: incorrect IV size")
}
// Based on the OpenSSL implementation. The salt is the first 8 bytes
// of the initialization vector.
key := ciph.deriveKey(password, iv[:8])
block, err := ciph.cipherFunc(key)
if err != nil {
return nil, err
}
if len(b.Bytes)%block.BlockSize() != 0 {
return nil, errors.New("x509: encrypted PEM data is not a multiple of the block size")
}
data := make([]byte, len(b.Bytes))
dec := cipher.NewCBCDecrypter(block, iv)
dec.CryptBlocks(data, b.Bytes)
// Blocks are padded using a scheme where the last n bytes of padding are all
// equal to n. It can pad from 1 to blocksize bytes inclusive. See RFC 1423.
// For example:
// [x y z 2 2]
// [x y 7 7 7 7 7 7 7]
// If we detect a bad padding, we assume it is an invalid password.
dlen := len(data)
if dlen == 0 || dlen%ciph.blockSize != 0 {
return nil, errors.New("x509: invalid padding")
}
last := int(data[dlen-1])
if dlen < last {
return nil, IncorrectPasswordError
}
if last == 0 || last > ciph.blockSize {
return nil, IncorrectPasswordError
}
for _, val := range data[dlen-last:] {
if int(val) != last {
return nil, IncorrectPasswordError
}
}
return data[:dlen-last], nil
}
// EncryptPEMBlock returns a PEM block of the specified type holding the
// given DER-encoded data encrypted with the specified algorithm and
// password.
func EncryptPEMBlock(rand io.Reader, blockType string, data, password []byte, alg PEMCipher) (*pem.Block, error) {
ciph := cipherByKey(alg)
if ciph == nil {
return nil, errors.New("x509: unknown encryption mode")
}
iv := make([]byte, ciph.blockSize)
if _, err := io.ReadFull(rand, iv); err != nil {
return nil, errors.New("x509: cannot generate IV: " + err.Error())
}
// The salt is the first 8 bytes of the initialization vector,
// matching the key derivation in DecryptPEMBlock.
key := ciph.deriveKey(password, iv[:8])
block, err := ciph.cipherFunc(key)
if err != nil {
return nil, err
}
enc := cipher.NewCBCEncrypter(block, iv)
pad := ciph.blockSize - len(data)%ciph.blockSize
encrypted := make([]byte, len(data), len(data)+pad)
// We could save this copy by encrypting all the whole blocks in
// the data separately, but it doesn't seem worth the additional
// code.
copy(encrypted, data)
// See RFC 1423, section 1.1
for i := 0; i < pad; i++ {
encrypted = append(encrypted, byte(pad))
}
enc.CryptBlocks(encrypted, encrypted)
return &pem.Block{
Type: blockType,
Headers: map[string]string{
"Proc-Type": "4,ENCRYPTED",
"DEK-Info": ciph.name + "," + hex.EncodeToString(iv),
},
Bytes: encrypted,
}, nil
}
func cipherByName(name string) *rfc1423Algo {
for i := range rfc1423Algos {
alg := &rfc1423Algos[i]
if alg.name == name {
return alg
}
}
return nil
}
func cipherByKey(key PEMCipher) *rfc1423Algo {
for i := range rfc1423Algos {
alg := &rfc1423Algos[i]
if alg.cipher == key {
return alg
}
}
return nil
}

121
vendor/github.com/zmap/zcrypto/x509/pkcs1.go generated vendored Normal file
View file

@ -0,0 +1,121 @@
// Copyright 2011 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 x509
import (
"crypto/rsa"
"encoding/asn1"
"errors"
"math/big"
)
// pkcs1PrivateKey is a structure which mirrors the PKCS#1 ASN.1 for an RSA private key.
type pkcs1PrivateKey struct {
Version int
N *big.Int
E int
D *big.Int
P *big.Int
Q *big.Int
// We ignore these values, if present, because rsa will calculate them.
Dp *big.Int `asn1:"optional"`
Dq *big.Int `asn1:"optional"`
Qinv *big.Int `asn1:"optional"`
AdditionalPrimes []pkcs1AdditionalRSAPrime `asn1:"optional,omitempty"`
}
type pkcs1AdditionalRSAPrime struct {
Prime *big.Int
// We ignore these values because rsa will calculate them.
Exp *big.Int
Coeff *big.Int
}
// pkcs1PublicKey reflects the ASN.1 structure of a PKCS#1 public key.
type pkcs1PublicKey struct {
N *big.Int
E int
}
// ParsePKCS1PrivateKey returns an RSA private key from its ASN.1 PKCS#1 DER encoded form.
func ParsePKCS1PrivateKey(der []byte) (*rsa.PrivateKey, error) {
var priv pkcs1PrivateKey
rest, err := asn1.Unmarshal(der, &priv)
if len(rest) > 0 {
return nil, asn1.SyntaxError{Msg: "trailing data"}
}
if err != nil {
return nil, err
}
if priv.Version > 1 {
return nil, errors.New("x509: unsupported private key version")
}
if priv.N.Sign() <= 0 || priv.D.Sign() <= 0 || priv.P.Sign() <= 0 || priv.Q.Sign() <= 0 {
return nil, errors.New("x509: private key contains zero or negative value")
}
key := new(rsa.PrivateKey)
key.PublicKey = rsa.PublicKey{
E: priv.E,
N: priv.N,
}
key.D = priv.D
key.Primes = make([]*big.Int, 2+len(priv.AdditionalPrimes))
key.Primes[0] = priv.P
key.Primes[1] = priv.Q
for i, a := range priv.AdditionalPrimes {
if a.Prime.Sign() <= 0 {
return nil, errors.New("x509: private key contains zero or negative prime")
}
key.Primes[i+2] = a.Prime
// We ignore the other two values because rsa will calculate
// them as needed.
}
err = key.Validate()
if err != nil {
return nil, err
}
key.Precompute()
return key, nil
}
// MarshalPKCS1PrivateKey converts a private key to ASN.1 DER encoded form.
func MarshalPKCS1PrivateKey(key *rsa.PrivateKey) []byte {
key.Precompute()
version := 0
if len(key.Primes) > 2 {
version = 1
}
priv := pkcs1PrivateKey{
Version: version,
N: key.N,
E: key.PublicKey.E,
D: key.D,
P: key.Primes[0],
Q: key.Primes[1],
Dp: key.Precomputed.Dp,
Dq: key.Precomputed.Dq,
Qinv: key.Precomputed.Qinv,
}
priv.AdditionalPrimes = make([]pkcs1AdditionalRSAPrime, len(key.Precomputed.CRTValues))
for i, values := range key.Precomputed.CRTValues {
priv.AdditionalPrimes[i].Prime = key.Primes[2+i]
priv.AdditionalPrimes[i].Exp = values.Exp
priv.AdditionalPrimes[i].Coeff = values.Coeff
}
b, _ := asn1.Marshal(priv)
return b
}

54
vendor/github.com/zmap/zcrypto/x509/pkcs8.go generated vendored Normal file
View file

@ -0,0 +1,54 @@
// Copyright 2011 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 x509
import (
"encoding/asn1"
"errors"
"fmt"
"github.com/zmap/zcrypto/x509/pkix"
)
// pkcs8 reflects an ASN.1, PKCS#8 PrivateKey. See
// ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-8/pkcs-8v1_2.asn
// and RFC 5208.
type pkcs8 struct {
Version int
Algo pkix.AlgorithmIdentifier
PrivateKey []byte
// optional attributes omitted.
}
// ParsePKCS8PrivateKey parses an unencrypted, PKCS#8 private key.
// See RFC 5208.
func ParsePKCS8PrivateKey(der []byte) (key interface{}, err error) {
var privKey pkcs8
if _, err := asn1.Unmarshal(der, &privKey); err != nil {
return nil, err
}
switch {
case privKey.Algo.Algorithm.Equal(oidPublicKeyRSA):
key, err = ParsePKCS1PrivateKey(privKey.PrivateKey)
if err != nil {
return nil, errors.New("x509: failed to parse RSA private key embedded in PKCS#8: " + err.Error())
}
return key, nil
case privKey.Algo.Algorithm.Equal(oidPublicKeyECDSA):
bytes := privKey.Algo.Parameters.FullBytes
namedCurveOID := new(asn1.ObjectIdentifier)
if _, err := asn1.Unmarshal(bytes, namedCurveOID); err != nil {
namedCurveOID = nil
}
key, err = parseECPrivateKey(namedCurveOID, privKey.PrivateKey)
if err != nil {
return nil, errors.New("x509: failed to parse EC private key embedded in PKCS#8: " + err.Error())
}
return key, nil
default:
return nil, fmt.Errorf("x509: PKCS#8 wrapping contained private key with unknown algorithm: %v", privKey.Algo.Algorithm)
}
}

279
vendor/github.com/zmap/zcrypto/x509/pkix/json.go generated vendored Normal file
View file

@ -0,0 +1,279 @@
// Copyright 2014 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 pkix
import (
"encoding/asn1"
"encoding/json"
"errors"
"strconv"
"strings"
)
type auxAttributeTypeAndValue struct {
Type string `json:"type,omitempty"`
Value string `json:"value,omitempty"`
}
// MarshalJSON implements the json.Marshaler interface.
func (a *AttributeTypeAndValue) MarshalJSON() ([]byte, error) {
aux := auxAttributeTypeAndValue{}
aux.Type = a.Type.String()
if s, ok := a.Value.(string); ok {
aux.Value = s
}
return json.Marshal(&aux)
}
// UnmarshalJSON implements the json.Unmarshaler interface.
func (a *AttributeTypeAndValue) UnmarshalJSON(b []byte) error {
aux := auxAttributeTypeAndValue{}
if err := json.Unmarshal(b, &aux); err != nil {
return err
}
a.Type = nil
if len(aux.Type) > 0 {
parts := strings.Split(aux.Type, ".")
for _, part := range parts {
i, err := strconv.Atoi(part)
if err != nil {
return err
}
a.Type = append(a.Type, i)
}
}
a.Value = aux.Value
return nil
}
type auxOtherName struct {
ID string `json:"id,omitempty"`
Value []byte `json:"value,omitempty"`
}
// MarshalJSON implements the json.Marshaler interface.
func (o *OtherName) MarshalJSON() ([]byte, error) {
aux := auxOtherName{
ID: o.TypeID.String(),
Value: o.Value.Bytes,
}
return json.Marshal(&aux)
}
// UnmarshalJSON implements the json.Unmarshaler interface.
func (o *OtherName) UnmarshalJSON(b []byte) (err error) {
aux := auxOtherName{}
if err = json.Unmarshal(b, &aux); err != nil {
return
}
// Turn dot-notation back into an OID
if len(aux.ID) == 0 {
return errors.New("empty type ID")
}
parts := strings.Split(aux.ID, ".")
o.TypeID = nil
for _, part := range parts {
i, err := strconv.Atoi(part)
if err != nil {
return err
}
o.TypeID = append(o.TypeID, i)
}
// Build the ASN.1 value
o.Value = asn1.RawValue{
Tag: 0,
Class: asn1.ClassContextSpecific,
IsCompound: true,
Bytes: aux.Value,
}
o.Value.FullBytes, err = asn1.Marshal(o.Value)
return
}
type auxExtension struct {
ID string `json:"id,omitempty"`
Critical bool `json:"critical"`
Value []byte `json:"value,omitempty"`
}
// MarshalJSON implements the json.Marshaler interface.
func (ext *Extension) MarshalJSON() ([]byte, error) {
aux := auxExtension{
ID: ext.Id.String(),
Critical: ext.Critical,
Value: ext.Value,
}
return json.Marshal(&aux)
}
// UnmarshalJSON implements the json.Unmarshaler interface.
func (ext *Extension) UnmarshalJSON(b []byte) (err error) {
aux := auxExtension{}
if err = json.Unmarshal(b, &aux); err != nil {
return
}
parts := strings.Split(aux.ID, ".")
for _, part := range parts {
i, err := strconv.Atoi(part)
if err != nil {
return err
}
ext.Id = append(ext.Id, i)
}
ext.Critical = aux.Critical
ext.Value = aux.Value
return
}
type auxName struct {
CommonName []string `json:"common_name,omitempty"`
SerialNumber []string `json:"serial_number,omitempty"`
Country []string `json:"country,omitempty"`
Locality []string `json:"locality,omitempty"`
Province []string `json:"province,omitempty"`
StreetAddress []string `json:"street_address,omitempty"`
Organization []string `json:"organization,omitempty"`
OrganizationalUnit []string `json:"organizational_unit,omitempty"`
PostalCode []string `json:"postal_code,omitempty"`
DomainComponent []string `json:"domain_component,omitempty"`
EmailAddress []string `json:"email_address,omitempty"`
GivenName []string `json:"given_name,omitempty"`
Surname []string `json:"surname,omitempty"`
// EV
JurisdictionCountry []string `json:"jurisdiction_country,omitempty"`
JurisdictionLocality []string `json:"jurisdiction_locality,omitempty"`
JurisdictionProvince []string `json:"jurisdiction_province,omitempty"`
// QWACS
OrganizationID []string `json:"organization_id,omitempty"`
UnknownAttributes []AttributeTypeAndValue `json:"-"`
}
// MarshalJSON implements the json.Marshaler interface.
func (n *Name) MarshalJSON() ([]byte, error) {
aux := auxName{}
attrs := n.ToRDNSequence()
for _, attrSet := range attrs {
for _, a := range attrSet {
s, ok := a.Value.(string)
if !ok {
continue
}
if a.Type.Equal(oidCommonName) {
aux.CommonName = append(aux.CommonName, s)
} else if a.Type.Equal(oidSurname) {
aux.Surname = append(aux.Surname, s)
} else if a.Type.Equal(oidSerialNumber) {
aux.SerialNumber = append(aux.SerialNumber, s)
} else if a.Type.Equal(oidCountry) {
aux.Country = append(aux.Country, s)
} else if a.Type.Equal(oidLocality) {
aux.Locality = append(aux.Locality, s)
} else if a.Type.Equal(oidProvince) {
aux.Province = append(aux.Province, s)
} else if a.Type.Equal(oidStreetAddress) {
aux.StreetAddress = append(aux.StreetAddress, s)
} else if a.Type.Equal(oidOrganization) {
aux.Organization = append(aux.Organization, s)
} else if a.Type.Equal(oidGivenName) {
aux.GivenName = append(aux.GivenName, s)
} else if a.Type.Equal(oidOrganizationalUnit) {
aux.OrganizationalUnit = append(aux.OrganizationalUnit, s)
} else if a.Type.Equal(oidPostalCode) {
aux.PostalCode = append(aux.PostalCode, s)
} else if a.Type.Equal(oidDomainComponent) {
aux.DomainComponent = append(aux.DomainComponent, s)
} else if a.Type.Equal(oidDNEmailAddress) {
aux.EmailAddress = append(aux.EmailAddress, s)
// EV
} else if a.Type.Equal(oidJurisdictionCountry) {
aux.JurisdictionCountry = append(aux.JurisdictionCountry, s)
} else if a.Type.Equal(oidJurisdictionLocality) {
aux.JurisdictionLocality = append(aux.JurisdictionLocality, s)
} else if a.Type.Equal(oidJurisdictionProvince) {
aux.JurisdictionProvince = append(aux.JurisdictionProvince, s)
} else if a.Type.Equal(oidOrganizationID) {
aux.OrganizationID = append(aux.OrganizationID, s)
} else {
aux.UnknownAttributes = append(aux.UnknownAttributes, a)
}
}
}
return json.Marshal(&aux)
}
func appendATV(names []AttributeTypeAndValue, fieldVals []string, asn1Id asn1.ObjectIdentifier) []AttributeTypeAndValue {
if len(fieldVals) == 0 {
return names
}
for _, val := range fieldVals {
names = append(names, AttributeTypeAndValue{Type: asn1Id, Value: val})
}
return names
}
// UnmarshalJSON implements the json.Unmarshaler interface.
func (n *Name) UnmarshalJSON(b []byte) error {
aux := auxName{}
if err := json.Unmarshal(b, &aux); err != nil {
return err
}
// Populate Names as []AttributeTypeAndValue
n.Names = appendATV(n.Names, aux.Country, oidCountry)
n.Names = appendATV(n.Names, aux.Organization, oidOrganization)
n.Names = appendATV(n.Names, aux.OrganizationalUnit, oidOrganizationalUnit)
n.Names = appendATV(n.Names, aux.Locality, oidLocality)
n.Names = appendATV(n.Names, aux.Province, oidProvince)
n.Names = appendATV(n.Names, aux.StreetAddress, oidStreetAddress)
n.Names = appendATV(n.Names, aux.PostalCode, oidPostalCode)
n.Names = appendATV(n.Names, aux.DomainComponent, oidDomainComponent)
n.Names = appendATV(n.Names, aux.EmailAddress, oidDNEmailAddress)
// EV
n.Names = appendATV(n.Names, aux.JurisdictionCountry, oidJurisdictionCountry)
n.Names = appendATV(n.Names, aux.JurisdictionLocality, oidJurisdictionLocality)
n.Names = appendATV(n.Names, aux.JurisdictionProvince, oidJurisdictionProvince)
n.Names = appendATV(n.Names, aux.CommonName, oidCommonName)
n.Names = appendATV(n.Names, aux.SerialNumber, oidSerialNumber)
// Populate specific fields as []string
n.Country = aux.Country
n.Organization = aux.Organization
n.OrganizationalUnit = aux.OrganizationalUnit
n.Locality = aux.Locality
n.Province = aux.Province
n.StreetAddress = aux.StreetAddress
n.PostalCode = aux.PostalCode
n.DomainComponent = aux.DomainComponent
// EV
n.JurisdictionCountry = aux.JurisdictionCountry
n.JurisdictionLocality = aux.JurisdictionLocality
n.JurisdictionProvince = aux.JurisdictionProvince
// CommonName and SerialNumber are not arrays.
if len(aux.CommonName) > 0 {
n.CommonName = aux.CommonName[0]
}
if len(aux.SerialNumber) > 0 {
n.SerialNumber = aux.SerialNumber[0]
}
// Add "extra" commonNames and serialNumbers to ExtraNames.
if len(aux.CommonName) > 1 {
n.ExtraNames = appendATV(n.ExtraNames, aux.CommonName[1:], oidCommonName)
}
if len(aux.SerialNumber) > 1 {
n.ExtraNames = appendATV(n.ExtraNames, aux.SerialNumber[1:], oidSerialNumber)
}
return nil
}

74
vendor/github.com/zmap/zcrypto/x509/pkix/oid.go generated vendored Normal file
View file

@ -0,0 +1,74 @@
// Copyright 2015 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 pkix
import (
"encoding/asn1"
"encoding/json"
"fmt"
"strconv"
"strings"
)
// AuxOID behaves similar to asn1.ObjectIdentifier, except encodes to JSON as a
// string in dot notation. It is a type synonym for []int, and can be converted
// to an asn1.ObjectIdentifier by going through []int and back.
type AuxOID []int
// AsSlice returns a slice over the inner-representation
func (aux *AuxOID) AsSlice() []int {
return *aux
}
// CopyAsSlice returns a copy of the inter-representation as a slice
func (aux *AuxOID) CopyAsSlice() []int {
out := make([]int, len(*aux))
copy(out, *aux)
return out
}
// Equal tests (deep) equality of two AuxOIDs
func (aux *AuxOID) Equal(other *AuxOID) bool {
var a []int = *aux
var b []int = *other
if len(a) != len(b) {
return false
}
for idx := range a {
if a[idx] != b[idx] {
return false
}
}
return true
}
// MarshalJSON implements the json.Marshaler interface
func (aux *AuxOID) MarshalJSON() ([]byte, error) {
var oid asn1.ObjectIdentifier
oid = []int(*aux)
return json.Marshal(oid.String())
}
// UnmarshalJSON implements the json.Unmarshaler interface
func (aux *AuxOID) UnmarshalJSON(b []byte) error {
var s string
if err := json.Unmarshal(b, &s); err != nil {
return err
}
parts := strings.Split(s, ".")
if len(parts) < 1 {
return fmt.Errorf("Invalid OID string %s", s)
}
slice := make([]int, len(parts))
for idx := range parts {
n, err := strconv.Atoi(parts[idx])
if err != nil || n < 0 {
return fmt.Errorf("Invalid OID integer %s", parts[idx])
}
slice[idx] = n
}
*aux = slice
return nil
}

1014
vendor/github.com/zmap/zcrypto/x509/pkix/oid_names.go generated vendored Normal file

File diff suppressed because it is too large Load diff

299
vendor/github.com/zmap/zcrypto/x509/pkix/pkix.go generated vendored Normal file
View file

@ -0,0 +1,299 @@
// Copyright 2011 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 pkix contains shared, low level structures used for ASN.1 parsing
// and serialization of X.509 certificates, CRL and OCSP.
package pkix
import (
"encoding/asn1"
"math/big"
"strings"
"time"
)
// AlgorithmIdentifier represents the ASN.1 structure of the same name. See RFC
// 5280, section 4.1.1.2.
type AlgorithmIdentifier struct {
Algorithm asn1.ObjectIdentifier
Parameters asn1.RawValue `asn1:"optional"`
}
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
type AttributeTypeAndValue struct {
Type asn1.ObjectIdentifier `json:"type"`
Value interface{} `json:"value"`
}
// AttributeTypeAndValueSET represents a set of ASN.1 sequences of
// AttributeTypeAndValue sequences from RFC 2986 (PKCS #10).
type AttributeTypeAndValueSET struct {
Type asn1.ObjectIdentifier
Value [][]AttributeTypeAndValue `asn1:"set"`
}
// Extension represents the ASN.1 structure of the same name. See RFC
// 5280, section 4.2.
type Extension struct {
Id asn1.ObjectIdentifier
Critical bool `asn1:"optional"`
Value []byte
}
// Name represents an X.509 distinguished name. This only includes the common
// elements of a DN. Additional elements in the name are ignored.
type Name struct {
Country, Organization, OrganizationalUnit []string
Locality, Province []string
StreetAddress, PostalCode, DomainComponent []string
EmailAddress []string
SerialNumber, CommonName string
SerialNumbers, CommonNames []string
GivenName, Surname []string
OrganizationIDs []string
// EV Components
JurisdictionLocality, JurisdictionProvince, JurisdictionCountry []string
Names []AttributeTypeAndValue
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.
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)
}
} 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)
}
}
}
var (
oidCountry = []int{2, 5, 4, 6}
oidOrganization = []int{2, 5, 4, 10}
oidOrganizationalUnit = []int{2, 5, 4, 11}
oidCommonName = []int{2, 5, 4, 3}
oidSurname = []int{2, 5, 4, 4}
oidSerialNumber = []int{2, 5, 4, 5}
oidLocality = []int{2, 5, 4, 7}
oidProvince = []int{2, 5, 4, 8}
oidStreetAddress = []int{2, 5, 4, 9}
oidPostalCode = []int{2, 5, 4, 17}
oidGivenName = []int{2, 5, 4, 42}
oidDomainComponent = []int{0, 9, 2342, 19200300, 100, 1, 25}
oidDNEmailAddress = []int{1, 2, 840, 113549, 1, 9, 1}
// EV
oidJurisdictionLocality = []int{1, 3, 6, 1, 4, 1, 311, 60, 2, 1, 1}
oidJurisdictionProvince = []int{1, 3, 6, 1, 4, 1, 311, 60, 2, 1, 2}
oidJurisdictionCountry = []int{1, 3, 6, 1, 4, 1, 311, 60, 2, 1, 3}
// QWACS
oidOrganizationID = []int{2, 5, 4, 97}
)
// appendRDNs appends a relativeDistinguishedNameSET to the given RDNSequence
// and returns the new value. The relativeDistinguishedNameSET contains an
// attributeTypeAndValue for each of the given values. See RFC 5280, A.1, and
// search for AttributeTypeAndValue.
func (n Name) appendRDNs(in RDNSequence, values []string, oid asn1.ObjectIdentifier) RDNSequence {
// NOTE: stdlib prevents adding if the oid is already present in n.ExtraNames
//if len(values) == 0 || oidInAttributeTypeAndValue(oid, n.ExtraNames) {
if len(values) == 0 {
return in
}
s := make([]AttributeTypeAndValue, len(values))
for i, value := range values {
s[i].Type = oid
s[i].Value = value
}
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)
}
switch value := atv.Value.(type) {
case string:
attrParts = append(attrParts, value)
case []byte:
attrParts = append(attrParts, string(value))
default:
continue
}
attrString := strings.Join(attrParts, "=")
out = append(out, attrString)
}
}
return strings.Join(out, ", ")
}
// ToRDNSequence returns OriginalRDNS is populated. Otherwise, it builds an
// RDNSequence in canonical order.
func (n Name) ToRDNSequence() (ret RDNSequence) {
if n.OriginalRDNS != nil {
return n.OriginalRDNS
}
if len(n.CommonName) > 0 {
ret = n.appendRDNs(ret, []string{n.CommonName}, oidCommonName)
}
ret = n.appendRDNs(ret, n.OrganizationalUnit, oidOrganizationalUnit)
ret = n.appendRDNs(ret, n.Organization, oidOrganization)
ret = n.appendRDNs(ret, n.StreetAddress, oidStreetAddress)
ret = n.appendRDNs(ret, n.Locality, oidLocality)
ret = n.appendRDNs(ret, n.Province, oidProvince)
ret = n.appendRDNs(ret, n.PostalCode, oidPostalCode)
ret = n.appendRDNs(ret, n.Country, oidCountry)
ret = n.appendRDNs(ret, n.DomainComponent, oidDomainComponent)
// EV Components
ret = n.appendRDNs(ret, n.JurisdictionLocality, oidJurisdictionLocality)
ret = n.appendRDNs(ret, n.JurisdictionProvince, oidJurisdictionProvince)
ret = n.appendRDNs(ret, n.JurisdictionCountry, oidJurisdictionCountry)
// QWACS
ret = n.appendRDNs(ret, n.OrganizationIDs, oidOrganizationID)
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
}
}
return false
}
// CertificateList represents the ASN.1 structure of the same name. See RFC
// 5280, section 5.1. Use Certificate.CheckCRLSignature to verify the
// signature.
type CertificateList struct {
TBSCertList TBSCertificateList
SignatureAlgorithm AlgorithmIdentifier
SignatureValue asn1.BitString
}
// HasExpired reports whether now is past the expiry time of certList.
func (certList *CertificateList) HasExpired(now time.Time) bool {
return now.After(certList.TBSCertList.NextUpdate)
}
// String returns a canonical representation of a DistinguishedName
func (n *Name) String() string {
seq := n.ToRDNSequence()
return seq.String()
}
// OtherName represents the ASN.1 structure of the same name. See RFC
// 5280, section 4.2.1.6.
type OtherName struct {
TypeID asn1.ObjectIdentifier
Value asn1.RawValue `asn1:"explicit"`
}
// EDIPartyName represents the ASN.1 structure of the same name. See RFC
// 5280, section 4.2.1.6.
type EDIPartyName struct {
NameAssigner string `asn1:"tag:0,optional,explicit" json:"name_assigner,omitempty"`
PartyName string `asn1:"tag:1,explicit" json:"party_name"`
}
// TBSCertificateList represents the ASN.1 structure of the same name. See RFC
// 5280, section 5.1.
type TBSCertificateList struct {
Raw asn1.RawContent
Version int `asn1:"optional,default:0"`
Signature AlgorithmIdentifier
Issuer RDNSequence
ThisUpdate time.Time
NextUpdate time.Time `asn1:"optional"`
RevokedCertificates []RevokedCertificate `asn1:"optional"`
Extensions []Extension `asn1:"tag:0,optional,explicit"`
}
// RevokedCertificate represents the ASN.1 structure of the same name. See RFC
// 5280, section 5.1.
type RevokedCertificate struct {
SerialNumber *big.Int
RevocationTime time.Time
Extensions []Extension `asn1:"optional"`
}

173
vendor/github.com/zmap/zcrypto/x509/qc_statements.go generated vendored Normal file
View file

@ -0,0 +1,173 @@
package x509
import (
"encoding/asn1"
"encoding/json"
"errors"
)
type QCStatementASN struct {
StatementID asn1.ObjectIdentifier
StatementInfo asn1.RawValue `asn1:"optional"`
}
func (s *QCStatementASN) MarshalJSON() ([]byte, error) {
aux := struct {
ID string `json:"id,omitempty"`
Value []byte `json:"value,omitempty"`
}{
ID: s.StatementID.String(),
Value: s.StatementInfo.Bytes,
}
return json.Marshal(&aux)
}
type QCStatementsASN struct {
QCStatements []QCStatementASN
}
// ETSI OIDS from https://www.etsi.org/deliver/etsi_en/319400_319499/31941205/02.02.03_20/en_31941205v020203a.pdf
var (
oidEtsiQcsQcCompliance = asn1.ObjectIdentifier{0, 4, 0, 1862, 1, 1}
oidEtsiQcsQcLimitValue = asn1.ObjectIdentifier{0, 4, 0, 1862, 1, 2}
oidEtsiQcsQcRetentionPeriod = asn1.ObjectIdentifier{0, 4, 0, 1862, 1, 3}
oidEtsiQcsQcSSCD = asn1.ObjectIdentifier{0, 4, 0, 1862, 1, 4}
oidEtsiQcsQcEuPDS = asn1.ObjectIdentifier{0, 4, 0, 1862, 1, 5}
oidEtsiQcsQcType = asn1.ObjectIdentifier{0, 4, 0, 1862, 1, 6}
oidEtsiQcsQcCCLegislation = asn1.ObjectIdentifier{0, 4, 0, 1862, 1, 7}
oidEtsiQcsQctEsign = asn1.ObjectIdentifier{0, 4, 0, 1862, 1, 6, 1}
oidEtsiQcsQctEseal = asn1.ObjectIdentifier{0, 4, 0, 1862, 1, 6, 2}
oidEtsiQcsQctWeb = asn1.ObjectIdentifier{0, 4, 0, 1862, 1, 6, 3}
)
type QCStatements struct {
StatementIDs []string `json:"ids,omitempty"`
ParsedStatements *ParsedQCStatements `json:"parsed,omitempty"`
}
type ParsedQCStatements struct {
ETSICompliance []bool `json:"etsi_compliance,omitempty"`
SSCD []bool `json:"sscd,omitempty"`
Types []QCType `json:"types,omitempty"`
Limit []MonetaryValue `json:"limit,omitempty"`
PDSLocations []PDSLocations `json:"pds_locations,omitempty"`
RetentionPeriod []int `json:"retention_period,omitempty"`
Legislation []QCLegistation `json:"legislation,omitempty"`
}
type MonetaryValue struct {
Currency string `json:"currency,omitempty"`
CurrencyNumber int `json:"currency_number,omitempty"`
Amount int `json:"amount,omitempty"`
Exponent int `json:"exponent,omitempty"`
}
type monetaryValueASNString struct {
Currency string `asn1:"printable"`
Amount int
Exponent int
}
type monetaryValueASNNumber struct {
Currency int
Amount int
Exponent int
}
type PDSLocations struct {
Locations []PDSLocation `json:"locations,omitempty"`
}
type PDSLocation struct {
URL string `json:"url,omitempty" asn1:"ia5"`
Language string `json:"language,omitempty" asn1:"printable"`
}
type QCType struct {
TypeIdentifiers []asn1.ObjectIdentifier
}
type QCLegistation struct {
CountryCodes []string `json:"country_codes,omitempty"`
}
func (qt *QCType) MarshalJSON() ([]byte, error) {
aux := struct {
Types []string `json:"ids,omitempty"`
}{
Types: make([]string, len(qt.TypeIdentifiers)),
}
for idx := range qt.TypeIdentifiers {
aux.Types[idx] = qt.TypeIdentifiers[idx].String()
}
return json.Marshal(&aux)
}
func (q *QCStatements) Parse(in *QCStatementsASN) error {
q.StatementIDs = make([]string, len(in.QCStatements))
known := ParsedQCStatements{}
for i, s := range in.QCStatements {
val := in.QCStatements[i].StatementInfo.FullBytes
q.StatementIDs[i] = s.StatementID.String()
if s.StatementID.Equal(oidEtsiQcsQcCompliance) {
known.ETSICompliance = append(known.ETSICompliance, true)
if val != nil {
return errors.New("EtsiQcsQcCompliance QCStatement must not contain a statementInfo")
}
} else if s.StatementID.Equal(oidEtsiQcsQcLimitValue) {
// TODO
mvs := monetaryValueASNString{}
mvn := monetaryValueASNNumber{}
out := MonetaryValue{}
if _, err := asn1.Unmarshal(val, &mvs); err == nil {
out.Currency = mvs.Currency
out.Amount = mvs.Amount
out.Exponent = mvs.Exponent
} else if _, err := asn1.Unmarshal(val, &mvn); err == nil {
out.CurrencyNumber = mvn.Currency
out.Amount = mvn.Amount
out.Exponent = mvn.Exponent
} else {
return err
}
known.Limit = append(known.Limit, out)
} else if s.StatementID.Equal(oidEtsiQcsQcRetentionPeriod) {
var retentionPeriod int
if _, err := asn1.Unmarshal(val, &retentionPeriod); err != nil {
return err
}
known.RetentionPeriod = append(known.RetentionPeriod, retentionPeriod)
} else if s.StatementID.Equal(oidEtsiQcsQcSSCD) {
known.SSCD = append(known.SSCD, true)
if val != nil {
return errors.New("EtsiQcsQcSSCD QCStatement must not contain a statementInfo")
}
} else if s.StatementID.Equal(oidEtsiQcsQcEuPDS) {
locations := make([]PDSLocation, 0)
if _, err := asn1.Unmarshal(val, &locations); err != nil {
return err
}
known.PDSLocations = append(known.PDSLocations, PDSLocations{
Locations: locations,
})
} else if s.StatementID.Equal(oidEtsiQcsQcType) {
typeIds := make([]asn1.ObjectIdentifier, 0)
if _, err := asn1.Unmarshal(val, &typeIds); err != nil {
return err
}
known.Types = append(known.Types, QCType{
TypeIdentifiers: typeIds,
})
} else if s.StatementID.Equal(oidEtsiQcsQcCCLegislation) {
countryCodes := make([]string, 0)
if _, err := asn1.Unmarshal(val, &countryCodes); err != nil {
return err
}
known.Legislation = append(known.Legislation, QCLegistation{
CountryCodes: countryCodes,
})
}
}
q.ParsedStatements = &known
return nil
}

105
vendor/github.com/zmap/zcrypto/x509/sec1.go generated vendored Normal file
View file

@ -0,0 +1,105 @@
// Copyright 2012 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 x509
import (
"crypto/ecdsa"
"crypto/elliptic"
"encoding/asn1"
"errors"
"fmt"
"math/big"
)
const ecPrivKeyVersion = 1
// ecPrivateKey reflects an ASN.1 Elliptic Curve Private Key Structure.
// References:
// RFC 5915
// SEC1 - http://www.secg.org/sec1-v2.pdf
// Per RFC 5915 the NamedCurveOID is marked as ASN.1 OPTIONAL, however in
// most cases it is not.
type ecPrivateKey struct {
Version int
PrivateKey []byte
NamedCurveOID asn1.ObjectIdentifier `asn1:"optional,explicit,tag:0"`
PublicKey asn1.BitString `asn1:"optional,explicit,tag:1"`
}
// ParseECPrivateKey parses an ASN.1 Elliptic Curve Private Key Structure.
func ParseECPrivateKey(der []byte) (*ecdsa.PrivateKey, error) {
return parseECPrivateKey(nil, der)
}
// MarshalECPrivateKey marshals an EC private key into ASN.1, DER format.
func MarshalECPrivateKey(key *ecdsa.PrivateKey) ([]byte, error) {
oid, ok := oidFromNamedCurve(key.Curve)
if !ok {
return nil, errors.New("x509: unknown elliptic curve")
}
privateKeyBytes := key.D.Bytes()
paddedPrivateKey := make([]byte, (key.Curve.Params().N.BitLen()+7)/8)
copy(paddedPrivateKey[len(paddedPrivateKey)-len(privateKeyBytes):], privateKeyBytes)
return asn1.Marshal(ecPrivateKey{
Version: 1,
PrivateKey: paddedPrivateKey,
NamedCurveOID: oid,
PublicKey: asn1.BitString{Bytes: elliptic.Marshal(key.Curve, key.X, key.Y)},
})
}
// parseECPrivateKey parses an ASN.1 Elliptic Curve Private Key Structure.
// The OID for the named curve may be provided from another source (such as
// the PKCS8 container) - if it is provided then use this instead of the OID
// that may exist in the EC private key structure.
func parseECPrivateKey(namedCurveOID *asn1.ObjectIdentifier, der []byte) (key *ecdsa.PrivateKey, err error) {
var privKey ecPrivateKey
if _, err := asn1.Unmarshal(der, &privKey); err != nil {
return nil, errors.New("x509: failed to parse EC private key: " + err.Error())
}
if privKey.Version != ecPrivKeyVersion {
return nil, fmt.Errorf("x509: unknown EC private key version %d", privKey.Version)
}
var curve elliptic.Curve
if namedCurveOID != nil {
curve = namedCurveFromOID(*namedCurveOID)
} else {
curve = namedCurveFromOID(privKey.NamedCurveOID)
}
if curve == nil {
return nil, errors.New("x509: unknown elliptic curve")
}
k := new(big.Int).SetBytes(privKey.PrivateKey)
curveOrder := curve.Params().N
if k.Cmp(curveOrder) >= 0 {
return nil, errors.New("x509: invalid elliptic curve private key value")
}
priv := new(ecdsa.PrivateKey)
priv.Curve = curve
priv.D = k
privateKey := make([]byte, (curveOrder.BitLen()+7)/8)
// Some private keys have leading zero padding. This is invalid
// according to [SEC1], but this code will ignore it.
for len(privKey.PrivateKey) > len(privateKey) {
if privKey.PrivateKey[0] != 0 {
return nil, errors.New("x509: invalid private key length")
}
privKey.PrivateKey = privKey.PrivateKey[1:]
}
// Some private keys remove all leading zeros, this is also invalid
// according to [SEC1] but since OpenSSL used to do this, we ignore
// this too.
copy(privateKey[len(privateKey)-len(privKey.PrivateKey):], privKey.PrivateKey)
priv.X, priv.Y = curve.ScalarBaseMult(privateKey)
return priv, nil
}

View file

@ -0,0 +1,158 @@
package x509
import (
"encoding/asn1"
"github.com/zmap/zcrypto/x509/pkix"
)
var (
// oidBRTorServiceDescriptor is the assigned OID for the CAB Forum Tor Service
// Descriptor Hash extension (see EV Guidelines Appendix F)
oidBRTorServiceDescriptor = asn1.ObjectIdentifier{2, 23, 140, 1, 31}
)
// TorServiceDescriptorHash is a structure corrsponding to the
// TorServiceDescriptorHash SEQUENCE described in Appendix F ("Issuance of
// Certificates for .onion Domain Names").
//
// Each TorServiceDescriptorHash holds an onion URI (a utf8 string with the
// .onion address that was validated), a hash algorithm name (computed based on
// the pkix.AlgorithmIdentifier in the TorServiceDescriptorHash), the hash bytes
// (computed over the DER encoding of the ASN.1 SubjectPublicKey of the .onion
// service), and the number of bits in the hash bytes.
type TorServiceDescriptorHash struct {
Onion string `json:"onion"`
Algorithm pkix.AlgorithmIdentifier `json:"-"`
AlgorithmName string `json:"algorithm_name"`
Hash CertificateFingerprint `json:"hash"`
HashBits int `json:"hash_bits"`
}
// parseTorServiceDescriptorSyntax parses the given pkix.Extension (assumed to
// have OID == oidBRTorServiceDescriptor) and returns a slice of parsed
// TorServiceDescriptorHash objects, or an error. An error will be returned if
// there are any structural errors related to the ASN.1 content (wrong tags,
// trailing data, missing fields, etc).
func parseTorServiceDescriptorSyntax(ext pkix.Extension) ([]*TorServiceDescriptorHash, error) {
// TorServiceDescriptorSyntax ::=
// SEQUENCE ( 1..MAX ) of TorServiceDescriptorHash
var seq asn1.RawValue
rest, err := asn1.Unmarshal(ext.Value, &seq)
if err != nil {
return nil, asn1.SyntaxError{
Msg: "unable to unmarshal outer TorServiceDescriptor SEQUENCE",
}
}
if len(rest) != 0 {
return nil, asn1.SyntaxError{
Msg: "trailing data after outer TorServiceDescriptor SEQUENCE",
}
}
if seq.Tag != asn1.TagSequence || seq.Class != asn1.ClassUniversal || !seq.IsCompound {
return nil, asn1.SyntaxError{
Msg: "invalid outer TorServiceDescriptor SEQUENCE",
}
}
var descriptors []*TorServiceDescriptorHash
rest = seq.Bytes
for len(rest) > 0 {
var descriptor *TorServiceDescriptorHash
descriptor, rest, err = parseTorServiceDescriptorHash(rest)
if err != nil {
return nil, err
}
descriptors = append(descriptors, descriptor)
}
return descriptors, nil
}
// parseTorServiceDescriptorHash unmarshals a SEQUENCE from the provided data
// and parses a TorServiceDescriptorHash using the data contained in the
// sequence. The TorServiceDescriptorHash object and the remaining data are
// returned if no error occurs.
func parseTorServiceDescriptorHash(data []byte) (*TorServiceDescriptorHash, []byte, error) {
// TorServiceDescriptorHash:: = SEQUENCE {
// onionURI UTF8String
// algorithm AlgorithmIdentifier
// subjectPublicKeyHash BIT STRING
// }
var outerSeq asn1.RawValue
var err error
data, err = asn1.Unmarshal(data, &outerSeq)
if err != nil {
return nil, data, asn1.SyntaxError{
Msg: "error unmarshaling TorServiceDescriptorHash SEQUENCE",
}
}
if outerSeq.Tag != asn1.TagSequence ||
outerSeq.Class != asn1.ClassUniversal ||
!outerSeq.IsCompound {
return nil, data, asn1.SyntaxError{
Msg: "TorServiceDescriptorHash missing compound SEQUENCE tag",
}
}
fieldData := outerSeq.Bytes
// Unmarshal and verify the structure of the onionURI UTF8String field.
var rawOnionURI asn1.RawValue
fieldData, err = asn1.Unmarshal(fieldData, &rawOnionURI)
if err != nil {
return nil, data, asn1.SyntaxError{
Msg: "error unmarshaling TorServiceDescriptorHash onionURI",
}
}
if rawOnionURI.Tag != asn1.TagUTF8String ||
rawOnionURI.Class != asn1.ClassUniversal ||
rawOnionURI.IsCompound {
return nil, data, asn1.SyntaxError{
Msg: "TorServiceDescriptorHash missing non-compound UTF8String tag",
}
}
// Unmarshal and verify the structure of the algorithm UTF8String field.
var algorithm pkix.AlgorithmIdentifier
fieldData, err = asn1.Unmarshal(fieldData, &algorithm)
if err != nil {
return nil, nil, asn1.SyntaxError{
Msg: "error unmarshaling TorServiceDescriptorHash algorithm",
}
}
var algorithmName string
if algorithm.Algorithm.Equal(oidSHA256) {
algorithmName = "SHA256"
} else if algorithm.Algorithm.Equal(oidSHA384) {
algorithmName = "SHA384"
} else if algorithm.Algorithm.Equal(oidSHA512) {
algorithmName = "SHA512"
} else {
algorithmName = "Unknown"
}
// Unmarshal and verify the structure of the Subject Public Key Hash BitString
// field.
var spkh asn1.BitString
fieldData, err = asn1.Unmarshal(fieldData, &spkh)
if err != nil {
return nil, data, asn1.SyntaxError{
Msg: "error unmarshaling TorServiceDescriptorHash Hash",
}
}
// There should be no trailing data after the TorServiceDescriptorHash
// SEQUENCE.
if len(fieldData) > 0 {
return nil, data, asn1.SyntaxError{
Msg: "trailing data after TorServiceDescriptorHash",
}
}
return &TorServiceDescriptorHash{
Onion: string(rawOnionURI.Bytes),
Algorithm: algorithm,
AlgorithmName: algorithmName,
HashBits: spkh.BitLength,
Hash: CertificateFingerprint(spkh.Bytes),
}, data, nil
}

60
vendor/github.com/zmap/zcrypto/x509/validation.go generated vendored Normal file
View file

@ -0,0 +1,60 @@
// Copyright 2015 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 x509
import "time"
// Validation stores different validation levels for a given certificate
type Validation struct {
BrowserTrusted bool `json:"browser_trusted"`
BrowserError string `json:"browser_error,omitempty"`
MatchesDomain bool `json:"matches_domain,omitempty"`
Domain string `json:"-"`
}
// ValidateWithStupidDetail fills out a Validation struct given a leaf
// certificate and intermediates / roots. If opts.DNSName is set, then it will
// also check if the domain matches.
//
// Deprecated: Use verifier.Verify() instead.
func (c *Certificate) ValidateWithStupidDetail(opts VerifyOptions) (chains []CertificateChain, validation *Validation, err error) {
// Manually set the time, so that all verifies we do get the same time
if opts.CurrentTime.IsZero() {
opts.CurrentTime = time.Now()
}
// XXX: Don't pass a KeyUsage to the Verify API
opts.KeyUsages = nil
domain := opts.DNSName
opts.DNSName = ""
out := new(Validation)
out.Domain = domain
if chains, _, _, err = c.Verify(opts); err != nil {
out.BrowserError = err.Error()
} else {
out.BrowserTrusted = true
}
if domain != "" {
nameErr := c.VerifyHostname(domain)
if nameErr != nil {
out.MatchesDomain = false
} else {
out.MatchesDomain = true
}
// Make sure we return an error if either chain building or hostname
// verification fails.
if err == nil && nameErr != nil {
err = nameErr
}
}
validation = out
return
}

635
vendor/github.com/zmap/zcrypto/x509/verify.go generated vendored Normal file
View file

@ -0,0 +1,635 @@
// Copyright 2011 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 x509
import (
"errors"
"fmt"
"net"
"strings"
"time"
"unicode/utf8"
)
type InvalidReason int
const (
// NotAuthorizedToSign results when a certificate is signed by another
// which isn't marked as a CA certificate.
NotAuthorizedToSign InvalidReason = iota
// Expired results when a certificate has expired, based on the time
// given in the VerifyOptions.
Expired
// CANotAuthorizedForThisName results when an intermediate or root
// certificate has a name constraint which doesn't include the name
// being checked.
CANotAuthorizedForThisName
// CANotAuthorizedForThisEmail results when an intermediate or root
// certificate has a name constraint which doesn't include the email
// being checked.
CANotAuthorizedForThisEmail
// CANotAuthorizedForThisIP results when an intermediate or root
// certificate has a name constraint which doesn't include the IP
// being checked.
CANotAuthorizedForThisIP
// CANotAuthorizedForThisDirectory results when an intermediate or root
// certificate has a name constraint which doesn't include the directory
// being checked.
CANotAuthorizedForThisDirectory
// TooManyIntermediates results when a path length constraint is
// violated.
TooManyIntermediates
// IncompatibleUsage results when the certificate's key usage indicates
// that it may only be used for a different purpose.
IncompatibleUsage
// NameMismatch results when the subject name of a parent certificate
// does not match the issuer name in the child.
NameMismatch
// NeverValid results when the certificate could never have been valid due to
// some date-related issue, e.g. NotBefore > NotAfter.
NeverValid
// IsSelfSigned results when the certificate is self-signed and not a trusted
// root.
IsSelfSigned
)
// CertificateInvalidError results when an odd error occurs. Users of this
// library probably want to handle all these errors uniformly.
type CertificateInvalidError struct {
Cert *Certificate
Reason InvalidReason
}
func (e CertificateInvalidError) Error() string {
switch e.Reason {
case NotAuthorizedToSign:
return "x509: certificate is not authorized to sign other certificates"
case Expired:
return "x509: certificate has expired or is not yet valid"
case CANotAuthorizedForThisName:
return "x509: a root or intermediate certificate is not authorized to sign in this domain"
case CANotAuthorizedForThisEmail:
return "x509: a root or intermediate certificate is not authorized to sign this email address"
case CANotAuthorizedForThisIP:
return "x509: a root or intermediate certificate is not authorized to sign this IP address"
case CANotAuthorizedForThisDirectory:
return "x509: a root or intermediate certificate is not authorized to sign in this directory"
case TooManyIntermediates:
return "x509: too many intermediates for path length constraint"
case IncompatibleUsage:
return "x509: certificate specifies an incompatible key usage"
case NameMismatch:
return "x509: issuer name does not match subject from issuing certificate"
case NeverValid:
return "x509: certificate will never be valid"
}
return "x509: unknown error"
}
// HostnameError results when the set of authorized names doesn't match the
// requested name.
type HostnameError struct {
Certificate *Certificate
Host string
}
func (h HostnameError) Error() string {
c := h.Certificate
var valid string
if ip := net.ParseIP(h.Host); ip != nil {
// Trying to validate an IP
if len(c.IPAddresses) == 0 {
return "x509: cannot validate certificate for " + h.Host + " because it doesn't contain any IP SANs"
}
for _, san := range c.IPAddresses {
if len(valid) > 0 {
valid += ", "
}
valid += san.String()
}
} else {
if c.hasSANExtension() {
valid = strings.Join(c.DNSNames, ", ")
} else {
valid = c.Subject.CommonName
}
}
if len(valid) == 0 {
return "x509: certificate is not valid for any names, but wanted to match " + h.Host
}
return "x509: certificate is valid for " + valid + ", not " + h.Host
}
// UnknownAuthorityError results when the certificate issuer is unknown
type UnknownAuthorityError struct {
Cert *Certificate
// hintErr contains an error that may be helpful in determining why an
// authority wasn't found.
hintErr error
// hintCert contains a possible authority certificate that was rejected
// because of the error in hintErr.
hintCert *Certificate
}
func (e UnknownAuthorityError) Error() string {
s := "x509: certificate signed by unknown authority"
if e.hintErr != nil {
certName := e.hintCert.Subject.CommonName
if len(certName) == 0 {
if len(e.hintCert.Subject.Organization) > 0 {
certName = e.hintCert.Subject.Organization[0]
} else {
certName = "serial:" + e.hintCert.SerialNumber.String()
}
}
s += fmt.Sprintf(" (possibly because of %q while trying to verify candidate authority certificate %q)", e.hintErr, certName)
}
return s
}
// SystemRootsError results when we fail to load the system root certificates.
type SystemRootsError struct {
Err error
}
func (se SystemRootsError) Error() string {
msg := "x509: failed to load system roots and no roots provided"
if se.Err != nil {
return msg + "; " + se.Err.Error()
}
return msg
}
// errNotParsed is returned when a certificate without ASN.1 contents is
// verified. Platform-specific verification needs the ASN.1 contents.
var errNotParsed = errors.New("x509: missing ASN.1 contents; use ParseCertificate")
const maxIntermediateCount = 10
// VerifyOptions contains parameters for Certificate.Verify. It's a structure
// because other PKIX verification APIs have ended up needing many options.
type VerifyOptions struct {
DNSName string
EmailAddress string
IPAddress net.IP
Intermediates *CertPool
Roots *CertPool // if nil, the system roots are used
CurrentTime time.Time // if zero, the current time is used
// KeyUsage specifies which Extended Key Usage values are acceptable.
// An empty list means ExtKeyUsageServerAuth. Key usage is considered a
// constraint down the chain which mirrors Windows CryptoAPI behaviour,
// but not the spec. To accept any key usage, include ExtKeyUsageAny.
KeyUsages []ExtKeyUsage
}
const (
leafCertificate = iota
intermediateCertificate
rootCertificate
)
func matchNameConstraint(domain, constraint string) bool {
// The meaning of zero length constraints is not specified, but this
// code follows NSS and accepts them as matching everything.
if len(constraint) == 0 {
return true
}
if len(domain) < len(constraint) {
return false
}
prefixLen := len(domain) - len(constraint)
if !strings.EqualFold(domain[prefixLen:], constraint) {
return false
}
if prefixLen == 0 {
return true
}
isSubdomain := domain[prefixLen-1] == '.'
constraintHasLeadingDot := constraint[0] == '.'
return isSubdomain != constraintHasLeadingDot
}
// NOTE: the stdlib function does many more checks and is preferable. For backwards compatibility using this version
// isValid performs validity checks on the c. It will never return a
// date-related error.
func (c *Certificate) isValid(certType CertificateType, currentChain CertificateChain) error {
// KeyUsage status flags are ignored. From Engineering Security, Peter
// Gutmann: A European government CA marked its signing certificates as
// being valid for encryption only, but no-one noticed. Another
// European CA marked its signature keys as not being valid for
// signatures. A different CA marked its own trusted root certificate
// as being invalid for certificate signing. Another national CA
// distributed a certificate to be used to encrypt data for the
// countrys tax authority that was marked as only being usable for
// digital signatures but not for encryption. Yet another CA reversed
// the order of the bit flags in the keyUsage due to confusion over
// encoding endianness, essentially setting a random keyUsage in
// certificates that it issued. Another CA created a self-invalidating
// certificate by adding a certificate policy statement stipulating
// that the certificate had to be used strictly as specified in the
// keyUsage, and a keyUsage containing a flag indicating that the RSA
// encryption key could only be used for Diffie-Hellman key agreement.
if certType == CertificateTypeIntermediate && (!c.BasicConstraintsValid || !c.IsCA) {
return CertificateInvalidError{c, NotAuthorizedToSign}
}
if c.BasicConstraintsValid && c.MaxPathLen >= 0 {
numIntermediates := len(currentChain) - 1
if numIntermediates > c.MaxPathLen {
return CertificateInvalidError{c, TooManyIntermediates}
}
}
if len(currentChain) > maxIntermediateCount {
return CertificateInvalidError{c, TooManyIntermediates}
}
return nil
}
// Verify attempts to verify c by building one or more chains from c to a
// certificate in opts.Roots, using certificates in opts.Intermediates if
// needed. If successful, it returns one or more chains where the first
// element of the chain is c and the last element is from opts.Roots.
//
// If opts.Roots is nil and system roots are unavailable the returned error
// will be of type SystemRootsError.
//
// WARNING: this doesn't do any revocation checking.
func (c *Certificate) Verify(opts VerifyOptions) (current, expired, never []CertificateChain, err error) {
if opts.Roots == nil {
err = SystemRootsError{}
return
}
err = c.isValid(CertificateTypeLeaf, nil)
if err != nil {
return
}
candidateChains, err := c.buildChains(make(map[int][]CertificateChain), []*Certificate{c}, &opts)
if err != nil {
return
}
keyUsages := opts.KeyUsages
if len(keyUsages) == 0 {
keyUsages = []ExtKeyUsage{ExtKeyUsageServerAuth}
}
// If any key usage is acceptable then we're done.
hasKeyUsageAny := false
for _, usage := range keyUsages {
if usage == ExtKeyUsageAny {
hasKeyUsageAny = true
break
}
}
var chains []CertificateChain
if hasKeyUsageAny {
chains = candidateChains
} else {
for _, candidate := range candidateChains {
if checkChainForKeyUsage(candidate, keyUsages) {
chains = append(chains, candidate)
}
}
}
if len(chains) == 0 {
err = CertificateInvalidError{c, IncompatibleUsage}
return
}
current, expired, never = FilterByDate(chains, opts.CurrentTime)
if len(current) == 0 {
if len(expired) > 0 {
err = CertificateInvalidError{c, Expired}
} else if len(never) > 0 {
err = CertificateInvalidError{c, NeverValid}
}
return
}
if len(opts.DNSName) > 0 {
err = c.VerifyHostname(opts.DNSName)
if err != nil {
return
}
}
return
}
func appendToFreshChain(chain []*Certificate, cert *Certificate) []*Certificate {
n := make([]*Certificate, len(chain)+1)
copy(n, chain)
n[len(chain)] = cert
return n
}
// buildChains returns all chains of length < maxIntermediateCount. Chains begin
// the certificate being validated (chain[0] = c), and end at a root. It
// enforces that all intermediates can sign certificates, and checks signatures.
// It does not enforce expiration.
func (c *Certificate) buildChains(cache map[int][]CertificateChain, currentChain CertificateChain, opts *VerifyOptions) (chains []CertificateChain, err error) {
// If the certificate being validated is a root, add the chain of length one
// containing just the root. Only do this on the first call to buildChains,
// when the len(currentChain) = 1.
if len(currentChain) == 1 && opts.Roots.Contains(c) {
chains = append(chains, CertificateChain{c})
}
if len(chains) == 0 && c.SelfSigned {
err = CertificateInvalidError{c, IsSelfSigned}
}
// Find roots that signed c and have matching SKID/AKID and Subject/Issuer.
possibleRoots, failedRoot, rootErr := opts.Roots.findVerifiedParents(c)
// If any roots are parents of c, create new chain for each one of them.
for _, rootNum := range possibleRoots {
root := opts.Roots.certs[rootNum]
err = root.isValid(CertificateTypeRoot, currentChain)
if err != nil {
continue
}
if !currentChain.CertificateInChain(root) {
chains = append(chains, currentChain.AppendToFreshChain(root))
}
}
// The root chains of length N+1 are now "done". Now we'll look for any
// intermediates that issue this certificate, meaning that any chain to a root
// through these intermediates is at least length N+2.
possibleIntermediates, failedIntermediate, intermediateErr := opts.Intermediates.findVerifiedParents(c)
for _, intermediateNum := range possibleIntermediates {
intermediate := opts.Intermediates.certs[intermediateNum]
if opts.Roots.Contains(intermediate) {
continue
}
if currentChain.CertificateSubjectAndKeyInChain(intermediate) {
continue
}
err = intermediate.isValid(CertificateTypeIntermediate, currentChain)
if err != nil {
continue
}
// We don't want to add any certificate to chains that doesn't somehow get
// to a root. We don't know if all chains through the intermediates will end
// at a root, so we slice off the back half of the chain and try to build
// that part separately.
childChains, ok := cache[intermediateNum]
if !ok {
childChains, err = intermediate.buildChains(cache, currentChain.AppendToFreshChain(intermediate), opts)
cache[intermediateNum] = childChains
}
chains = append(chains, childChains...)
}
if len(chains) > 0 {
err = nil
}
if len(chains) == 0 && err == nil {
hintErr := rootErr
hintCert := failedRoot
if hintErr == nil {
hintErr = intermediateErr
hintCert = failedIntermediate
}
err = UnknownAuthorityError{c, hintErr, hintCert}
}
return
}
func matchHostnames(pattern, host string) bool {
host = strings.TrimSuffix(host, ".")
pattern = strings.TrimSuffix(pattern, ".")
if len(pattern) == 0 || len(host) == 0 {
return false
}
patternParts := strings.Split(pattern, ".")
hostParts := strings.Split(host, ".")
if len(patternParts) != len(hostParts) {
return false
}
for i, patternPart := range patternParts {
if /*i == 0 &&*/ patternPart == "*" {
continue
}
if patternPart != hostParts[i] {
return false
}
}
return true
}
// toLowerCaseASCII returns a lower-case version of in. See RFC 6125 6.4.1. We use
// an explicitly ASCII function to avoid any sharp corners resulting from
// performing Unicode operations on DNS labels.
func toLowerCaseASCII(in string) string {
// If the string is already lower-case then there's nothing to do.
isAlreadyLowerCase := true
for _, c := range in {
if c == utf8.RuneError {
// If we get a UTF-8 error then there might be
// upper-case ASCII bytes in the invalid sequence.
isAlreadyLowerCase = false
break
}
if 'A' <= c && c <= 'Z' {
isAlreadyLowerCase = false
break
}
}
if isAlreadyLowerCase {
return in
}
out := []byte(in)
for i, c := range out {
if 'A' <= c && c <= 'Z' {
out[i] += 'a' - 'A'
}
}
return string(out)
}
// VerifyHostname returns nil if c is a valid certificate for the named host.
// Otherwise it returns an error describing the mismatch.
func (c *Certificate) VerifyHostname(h string) error {
// IP addresses may be written in [ ].
candidateIP := h
if len(h) >= 3 && h[0] == '[' && h[len(h)-1] == ']' {
candidateIP = h[1 : len(h)-1]
}
if ip := net.ParseIP(candidateIP); ip != nil {
// We only match IP addresses against IP SANs.
// https://tools.ietf.org/html/rfc6125#appendix-B.2
for _, candidate := range c.IPAddresses {
if ip.Equal(candidate) {
return nil
}
}
return HostnameError{c, candidateIP}
}
lowered := toLowerCaseASCII(h)
if c.hasSANExtension() {
for _, match := range c.DNSNames {
if matchHostnames(toLowerCaseASCII(match), lowered) {
return nil
}
}
// If Subject Alt Name is given, we ignore the common name.
} else if matchHostnames(toLowerCaseASCII(c.Subject.CommonName), lowered) {
return nil
}
return HostnameError{c, h}
}
func checkChainForKeyUsage(chain []*Certificate, keyUsages []ExtKeyUsage) bool {
usages := make([]ExtKeyUsage, len(keyUsages))
copy(usages, keyUsages)
if len(chain) == 0 {
return false
}
usagesRemaining := len(usages)
// We walk down the list and cross out any usages that aren't supported
// by each certificate. If we cross out all the usages, then the chain
// is unacceptable.
NextCert:
for i := len(chain) - 1; i >= 0; i-- {
cert := chain[i]
if len(cert.ExtKeyUsage) == 0 && len(cert.UnknownExtKeyUsage) == 0 {
// The certificate doesn't have any extended key usage specified.
continue
}
for _, usage := range cert.ExtKeyUsage {
if usage == ExtKeyUsageAny {
// The certificate is explicitly good for any usage.
continue NextCert
}
}
const invalidUsage ExtKeyUsage = -1
NextRequestedUsage:
for i, requestedUsage := range usages {
if requestedUsage == invalidUsage {
continue
}
for _, usage := range cert.ExtKeyUsage {
if requestedUsage == usage {
continue NextRequestedUsage
} else if requestedUsage == ExtKeyUsageServerAuth &&
(usage == ExtKeyUsageNetscapeServerGatedCrypto ||
usage == ExtKeyUsageMicrosoftServerGatedCrypto) {
// In order to support COMODO
// certificate chains, we have to
// accept Netscape or Microsoft SGC
// usages as equal to ServerAuth.
continue NextRequestedUsage
}
}
usages[i] = invalidUsage
usagesRemaining--
if usagesRemaining == 0 {
return false
}
}
}
return true
}
// earlier returns the earlier of a and b
func earlier(a, b time.Time) time.Time {
if a.Before(b) {
return a
}
return b
}
// later returns the later of a and b
func later(a, b time.Time) time.Time {
if a.After(b) {
return a
}
return b
}
// check expirations divides chains into a set of disjoint chains, containing
// current chains valid now, expired chains that were valid at some point, and
// the set of chains that were never valid.
func FilterByDate(chains []CertificateChain, now time.Time) (current, expired, never []CertificateChain) {
for _, chain := range chains {
if len(chain) == 0 {
continue
}
leaf := chain[0]
lowerBound := leaf.NotBefore
upperBound := leaf.NotAfter
for _, c := range chain[1:] {
lowerBound = later(lowerBound, c.NotBefore)
upperBound = earlier(upperBound, c.NotAfter)
}
valid := lowerBound.Before(now) && upperBound.After(now)
wasValid := lowerBound.Before(upperBound)
if valid && !wasValid {
// Math/logic tells us this is impossible.
panic("valid && !wasValid should not be possible")
}
if valid {
current = append(current, chain)
} else if wasValid {
expired = append(expired, chain)
} else {
never = append(never, chain)
}
}
return
}

3042
vendor/github.com/zmap/zcrypto/x509/x509.go generated vendored Normal file

File diff suppressed because it is too large Load diff

30
vendor/github.com/zmap/zlint/v3/.goreleaser.yml generated vendored Normal file
View file

@ -0,0 +1,30 @@
project_name: zlint
before:
hooks:
- go mod tidy
builds:
-
main: ./cmd/zlint/main.go
binary: zlint
env:
- CGO_ENABLED=0
goos:
- linux
- freebsd
- windows
- darwin
goarch:
- amd64
archives:
-
wrap_in_directory: true
replacements:
darwin: Darwin
linux: Linux
windows: Windows
amd64: x86_64
snapshot:
name_template: "{{ .Tag }}-next"
release:
draft: true
prerelease: auto

202
vendor/github.com/zmap/zlint/v3/LICENSE generated vendored Normal file
View file

@ -0,0 +1,202 @@
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 2020 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.

96
vendor/github.com/zmap/zlint/v3/lint/base.go generated vendored Normal file
View file

@ -0,0 +1,96 @@
package lint
/*
* 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 (
"time"
"github.com/zmap/zcrypto/x509"
"github.com/zmap/zlint/v3/util"
)
// LintInterface is implemented by each Lint.
type LintInterface interface {
// Initialize runs once per-lint. It is called during RegisterLint().
Initialize() error
// 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
// Run().
CheckApplies(c *x509.Certificate) bool
// Execute() is the body of the lint. It is called for every certificate for
// which CheckApplies() returns true.
Execute(c *x509.Certificate) *LintResult
}
// A Lint struct represents a single lint, e.g.
// "e_basic_constraints_not_critical". It contains an implementation of LintInterface.
type Lint struct {
// Name is a lowercase underscore-separated string describing what a given
// Lint checks. If Name beings with "w", the lint MUST NOT return Error, only
// Warn. If Name beings with "e", the Lint MUST NOT return Warn, only Error.
Name string `json:"name,omitempty"`
// A human-readable description of what the Lint checks. Usually copied
// directly from the CA/B Baseline Requirements or RFC 5280.
Description string `json:"description,omitempty"`
// The source of the check, e.g. "BRs: 6.1.6" or "RFC 5280: 4.1.2.6".
Citation string `json:"citation,omitempty"`
// Programmatic source of the check, BRs, RFC5280, or ZLint
Source LintSource `json:"source"`
// Lints automatically returns NE for all certificates where CheckApplies() is
// true but with NotBefore < EffectiveDate. This check is bypassed if
// EffectiveDate is zero.
EffectiveDate time.Time `json:"-"`
// The implementation of the lint logic.
Lint LintInterface `json:"-"`
}
// CheckEffective returns true if c was issued on or after the EffectiveDate. If
// EffectiveDate is zero, 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
}
// Execute runs the lint against a certificate. For lints that are
// sourced from the CA/B Forum Baseline Requirements, we first determine
// if they are within the purview of the BRs. See LintInterface for details
// about the other methods called. The ordering is as follows:
//
// CheckApplies()
// CheckEffective()
// Execute()
func (l *Lint) Execute(cert *x509.Certificate) *LintResult {
if l.Source == CABFBaselineRequirements && !util.IsServerAuthCert(cert) {
return &LintResult{Status: NA}
}
if !l.Lint.CheckApplies(cert) {
return &LintResult{Status: NA}
} else if !l.CheckEffective(cert) {
return &LintResult{Status: NE}
}
res := l.Lint.Execute(cert)
return res
}

351
vendor/github.com/zmap/zlint/v3/lint/registration.go generated vendored Normal file
View file

@ -0,0 +1,351 @@
/*
* 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 (
"encoding/json"
"errors"
"fmt"
"io"
"regexp"
"sort"
"strings"
"sync"
)
// FilterOptions is a struct used by Registry.Filter to create a sub registry
// containing only lints that meet the filter options specified.
//
// Source based exclusion/inclusion is evaluated before Lint name based
// exclusion/inclusion. In both cases exclusion is processed before inclusion.
//
// Only one of NameFilter or IncludeNames/ExcludeNames can be provided at
// a time.
type FilterOptions struct {
// NameFilter is a regexp used to filter lints by their name. It is mutually
// exclusive with IncludeNames and ExcludeNames.
NameFilter *regexp.Regexp
// IncludeNames is a case sensitive list of lint names to include in the
// registry being filtered.
IncludeNames []string
// ExcludeNames is a case sensitive list of lint names to exclude from the
// registry being filtered.
ExcludeNames []string
// IncludeSource is a SourceList of LintSource's to be included in the
// registry being filtered.
IncludeSources SourceList
// ExcludeSources is a SourceList of LintSources's to be excluded in the
// registry being filtered.
ExcludeSources SourceList
}
// Empty returns true if the FilterOptions is empty and does not specify any
// elements to filter by.
func (opts FilterOptions) Empty() bool {
return opts.NameFilter == nil &&
len(opts.IncludeNames) == 0 &&
len(opts.ExcludeNames) == 0 &&
len(opts.IncludeSources) == 0 &&
len(opts.ExcludeSources) == 0
}
// Registry is an interface describing a collection of registered lints.
// A Registry instance can be given to zlint.LintCertificateEx() to control what
// lints are run for a given certificate.
//
// Typically users will interact with the global Registry returned by
// GlobalRegistry(), or a filtered Registry created by applying FilterOptions to
// the GlobalRegistry()'s Filter function.
type Registry interface {
// Names returns a list of all of the lint names that have been registered
// in string sorted order.
Names() []string
// 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
// 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
// BySource returns a list of registered lints that have the same LintSource as
// provided (or nil if there were no such lints in the registry).
BySource(s LintSource) []*Lint
// Filter returns a new Registry containing only lints that match the
// FilterOptions criteria.
Filter(opts FilterOptions) (Registry, error)
// WriteJSON writes a description of each registered lint as
// a JSON object, one object per line, to the provided writer.
WriteJSON(w io.Writer)
}
// registryImpl implements the Registry interface to provide a global collection
// of Lints that have been registered.
type registryImpl struct {
sync.RWMutex
// lintsByName is a map of all registered lints by name.
lintsByName map[string]*Lint
// lintNames is a sorted list of all of the registered lint names. It is
// equivalent to collecting the keys from lintsByName into a slice and sorting
// them lexicographically.
lintNames []string
// lintsBySource is a map of all registered lints by source category. Lints
// are added to the lintsBySource map by RegisterLint.
lintsBySource map[LintSource][]*Lint
}
var (
// errNilLint is returned from registry.Register if the provided lint was nil.
errNilLint = errors.New("can not register a nil lint")
// errNilLintPtr is returned from registry.Register if the provided lint had
// a nil Lint field.
errNilLintPtr = errors.New("can not register a lint with a nil Lint pointer")
// errEmptyName is returned from registry.Register if the provided lint had an
// empty Name field.
errEmptyName = errors.New("can not register a lint with an empty Name")
)
// errDuplicateName is returned from registry.Register if the provided lint had
// a Name field matching a lint that was previously registered.
type errDuplicateName struct {
lintName string
}
func (e errDuplicateName) Error() string {
return fmt.Sprintf(
"can not register lint with name %q - it has already been registered",
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 {
if l == nil {
return errNilLint
}
if l.Lint == nil {
return errNilLintPtr
}
if l.Name == "" {
return errEmptyName
}
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)
r.lintsByName[l.Name] = l
r.lintsBySource[l.Source] = append(r.lintsBySource[l.Source], l)
sort.Strings(r.lintNames)
return nil
}
// ByName returns the Lint previously registered under the given name with
// Register, or nil if no matching lint name has been registered.
func (r *registryImpl) ByName(name string) *Lint {
r.RLock()
defer r.RUnlock()
return r.lintsByName[name]
}
// Names returns a list of all of the lint names that have been registered
// in string sorted order.
func (r *registryImpl) Names() []string {
r.RLock()
defer r.RUnlock()
return r.lintNames
}
// BySource returns a list of registered lints that have the same LintSource as
// provided (or nil if there were no such lints).
func (r *registryImpl) BySource(s LintSource) []*Lint {
r.RLock()
defer r.RUnlock()
return r.lintsBySource[s]
}
// Sources returns a SourceList of registered LintSources. The list is not
// sorted but can be sorted by the caller with sort.Sort() if required.
func (r *registryImpl) Sources() SourceList {
r.RLock()
defer r.RUnlock()
var results SourceList
for k := range r.lintsBySource {
results = append(results, k)
}
return results
}
// lintNamesToMap converts a list of lit names into a bool hashmap useful for
// filtering. If any of the lint names are not known by the registry an error is
// returned.
func (r *registryImpl) lintNamesToMap(names []string) (map[string]bool, error) {
if len(names) == 0 {
return nil, nil
}
namesMap := make(map[string]bool, len(names))
for _, n := range names {
n = strings.TrimSpace(n)
if l := r.ByName(n); l == nil {
return nil, fmt.Errorf("unknown lint name %q", n)
}
namesMap[n] = true
}
return namesMap, nil
}
func sourceListToMap(sources SourceList) map[LintSource]bool {
if len(sources) == 0 {
return nil
}
sourceMap := make(map[LintSource]bool, len(sources))
for _, s := range sources {
sourceMap[s] = true
}
return sourceMap
}
// Filter creates a new Registry with only the lints that meet the FilterOptions
// criteria included.
//
// FilterOptions are applied in the following order of precedence:
// ExcludeSources > IncludeSources > NameFilter > ExcludeNames > IncludeNames
func (r *registryImpl) Filter(opts FilterOptions) (Registry, error) {
// If there's no filtering to be done, return the existing Registry.
if opts.Empty() {
return r, nil
}
filteredRegistry := NewRegistry()
sourceExcludes := sourceListToMap(opts.ExcludeSources)
sourceIncludes := sourceListToMap(opts.IncludeSources)
nameExcludes, err := r.lintNamesToMap(opts.ExcludeNames)
if err != nil {
return nil, err
}
nameIncludes, err := r.lintNamesToMap(opts.IncludeNames)
if err != nil {
return nil, err
}
if opts.NameFilter != nil && (len(nameExcludes) != 0 || len(nameIncludes) != 0) {
return nil, errors.New(
"FilterOptions.NameFilter cannot be used at the same time as " +
"FilterOptions.ExcludeNames or FilterOptions.IncludeNames")
}
for _, name := range r.Names() {
l := r.ByName(name)
if sourceExcludes != nil && sourceExcludes[l.Source] {
continue
}
if sourceIncludes != nil && !sourceIncludes[l.Source] {
continue
}
if opts.NameFilter != nil && !opts.NameFilter.MatchString(name) {
continue
}
if nameExcludes != nil && nameExcludes[name] {
continue
}
if nameIncludes != nil && !nameIncludes[name] {
continue
}
// 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 {
return nil, err
}
}
return filteredRegistry, nil
}
// WriteJSON writes a description of each registered lint as
// a JSON object, one object per line, to the provided writer.
func (r *registryImpl) WriteJSON(w io.Writer) {
enc := json.NewEncoder(w)
enc.SetEscapeHTML(false)
for _, name := range r.Names() {
_ = enc.Encode(r.ByName(name))
}
}
// NewRegistry constructs a Registry implementation that can be used to register
// lints.
func NewRegistry() *registryImpl {
return &registryImpl{
lintsByName: make(map[string]*Lint),
lintsBySource: make(map[LintSource][]*Lint),
}
}
// globalRegistry is the Registry used by all loaded lints that call
// RegisterLint().
var globalRegistry *registryImpl = 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.
//
// RegsterLint will call l.Lint's Initialize() function as part of the
// registration process.
//
// IMPORTANT: RegisterLint will panic if given a nil lint, or a lint with a nil
// Lint pointer, or if the lint's Initialize function errors, or if the lint
// name matches a previously registered lint's name. These conditions all
// indicate a bug that should be addressed by a developer.
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 {
panic(fmt.Sprintf("RegisterLint error: %v\n", err.Error()))
}
}
// GlobalRegistry is the Registry used by RegisterLint and contains all of the
// lints that are loaded.
//
// If you want to run only a subset of the globally registered lints use
// GloablRegistry().Filter with FilterOptions to create a filtered
// Registry.
func GlobalRegistry() Registry {
return globalRegistry
}

106
vendor/github.com/zmap/zlint/v3/lint/result.go generated vendored Normal file
View file

@ -0,0 +1,106 @@
package lint
/*
* 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 (
"encoding/json"
"fmt"
"strings"
)
// LintStatus is an enum returned by lints inside of a LintResult.
type LintStatus int
// Known LintStatus values
const (
// Unused / unset LintStatus
Reserved LintStatus = 0
// Not Applicable
NA LintStatus = 1
// Not Effective
NE LintStatus = 2
Pass LintStatus = 3
Notice LintStatus = 4
Warn LintStatus = 5
Error LintStatus = 6
Fatal LintStatus = 7
)
var (
// StatusLabelToLintStatus is used to work backwards from
// a LintStatus.String() to the LintStatus. This is used by
// LintStatus.Unmarshal.
StatusLabelToLintStatus = map[string]LintStatus{
Reserved.String(): Reserved,
NA.String(): NA,
NE.String(): NE,
Pass.String(): Pass,
Notice.String(): Notice,
Warn.String(): Warn,
Error.String(): Error,
Fatal.String(): Fatal,
}
)
// LintResult contains a LintStatus, and an optional human-readable description.
// The output of a lint is a LintResult.
type LintResult struct {
Status LintStatus `json:"result"`
Details string `json:"details,omitempty"`
}
// MarshalJSON implements the json.Marshaler interface.
func (e LintStatus) MarshalJSON() ([]byte, error) {
s := e.String()
return json.Marshal(s)
}
// UnmarshalJSON implements the json.Unmarshaler interface.
func (e *LintStatus) UnmarshalJSON(data []byte) error {
key := strings.ReplaceAll(string(data), `"`, "")
if status, ok := StatusLabelToLintStatus[key]; ok {
*e = status
} else {
return fmt.Errorf("bad LintStatus JSON value: %s", string(data))
}
return nil
}
// String returns the canonical representation of a LintStatus as a string.
func (e LintStatus) String() string {
switch e {
case Reserved:
return "reserved"
case NA:
return "NA"
case NE:
return "NE"
case Pass:
return "pass"
case Notice:
return "info"
case Warn:
return "warn"
case Error:
return "error"
case Fatal:
return "fatal"
default:
return ""
}
}

129
vendor/github.com/zmap/zlint/v3/lint/source.go generated vendored Normal file
View file

@ -0,0 +1,129 @@
package lint
import (
"encoding/json"
"fmt"
"strings"
)
/*
* 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.
*/
// LintSource is a type representing a known lint source that lints cite
// requirements from.
type LintSource string
const (
UnknownLintSource LintSource = "Unknown"
RFC5280 LintSource = "RFC5280"
RFC5480 LintSource = "RFC5480"
RFC5891 LintSource = "RFC5891"
CABFBaselineRequirements LintSource = "CABF_BR"
CABFEVGuidelines LintSource = "CABF_EV"
MozillaRootStorePolicy LintSource = "Mozilla"
AppleRootStorePolicy LintSource = "Apple"
Community LintSource = "Community"
EtsiEsi LintSource = "ETSI_ESI"
)
// UnmarshalJSON implements the json.Unmarshaler interface. It ensures that the
// unmarshaled value is a known LintSource.
func (s *LintSource) UnmarshalJSON(data []byte) error {
var throwAway string
if err := json.Unmarshal(data, &throwAway); err != nil {
return err
}
switch LintSource(throwAway) {
case RFC5280, RFC5480, RFC5891, CABFBaselineRequirements, CABFEVGuidelines, MozillaRootStorePolicy, AppleRootStorePolicy, Community, EtsiEsi:
*s = LintSource(throwAway)
return nil
default:
*s = UnknownLintSource
return fmt.Errorf("unknown LintSource value %q", throwAway)
}
}
// FromString sets the LintSource value based on the source string provided
// (case sensitive). If the src string does not match any of the known
// LintSource's then s is set to the UnknownLintSource.
func (s *LintSource) FromString(src string) {
// Start with the unknown lint source
*s = UnknownLintSource
// Trim space and try to match a known value
src = strings.TrimSpace(src)
switch LintSource(src) {
case RFC5280:
*s = RFC5280
case RFC5480:
*s = RFC5480
case RFC5891:
*s = RFC5891
case CABFBaselineRequirements:
*s = CABFBaselineRequirements
case CABFEVGuidelines:
*s = CABFEVGuidelines
case MozillaRootStorePolicy:
*s = MozillaRootStorePolicy
case AppleRootStorePolicy:
*s = AppleRootStorePolicy
case Community:
*s = Community
case EtsiEsi:
*s = EtsiEsi
}
}
// SourceList is a slice of LintSources that can be sorted.
type SourceList []LintSource
// Len returns the length of the list.
func (l SourceList) Len() int {
return len(l)
}
// Swap swaps the LintSource at index i and j in the list.
func (l SourceList) Swap(i, j int) {
l[i], l[j] = l[j], l[i]
}
// Less compares the LintSources at index i and j lexicographically.
func (l SourceList) Less(i, j int) bool {
return l[i] < l[j]
}
// FromString populates a SourceList (replacing any existing content) with the
// comma separated list of sources provided in raw. If any of the comma
// separated values are not known LintSource's an error is returned.
func (l *SourceList) FromString(raw string) error {
// Start with an empty list
*l = SourceList{}
values := strings.Split(raw, ",")
for _, val := range values {
val = strings.TrimSpace(val)
if val == "" {
continue
}
// Populate the LintSource with the trimmed value.
var src LintSource
src.FromString(val)
// If the LintSource is UnknownLintSource then return an error.
if src == UnknownLintSource {
return fmt.Errorf("unknown lint source in list: %q", val)
}
*l = append(*l, src)
}
return nil
}

View file

@ -0,0 +1,157 @@
/*
* 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 apple
import (
"fmt"
"time"
"github.com/zmap/zcrypto/x509"
"github.com/zmap/zcrypto/x509/ct"
"github.com/zmap/zlint/v3/lint"
"github.com/zmap/zlint/v3/util"
)
type sctPolicyCount struct{}
func init() {
lint.RegisterLint(&lint.Lint{
Name: "w_ct_sct_policy_count_unsatisfied",
Description: "Check if certificate has enough embedded SCTs to meet Apple CT Policy",
Citation: "https://support.apple.com/en-us/HT205280",
Source: lint.AppleRootStorePolicy,
EffectiveDate: util.AppleCTPolicyDate,
Lint: &sctPolicyCount{},
})
}
// Initialize for a sctPolicyCount instance does nothing.
func (l *sctPolicyCount) Initialize() error {
return nil
}
// 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.
func (l *sctPolicyCount) CheckApplies(c *x509.Certificate) bool {
return util.IsSubscriberCert(c) && !util.IsExtInCert(c, util.CtPoisonOID)
}
// Execute checks if the provided certificate has embedded SCTs from
// a sufficient number of unique CT logs to meet Apple's CT log policy[0],
// effective Oct 15th, 2018.
//
// The number of required SCTs from different logs is calculated based on the
// Certificate's lifetime. If the number of required SCTs are not embedded in
// the certificate a Notice level lint.LintResult is returned.
//
// | Certificate lifetime | # of SCTs from separate logs |
// -------------------------------------------------------
// | Less than 15 months | 2 |
// | 15 to 27 months | 3 |
// | 27 to 39 months | 4 |
// | More than 39 months | 5 |
// -------------------------------------------------------
//
// Important note 1: We can't know whether additional SCTs were presented
// alongside the certificate via OCSP stapling. This linter assumes only
// embedded SCTs are used and ignores the portion of the Apple policy related to
// SCTs delivered via OCSP. This is one limitation that restricts the linter's
// findings to Notice level. See more background discussion in Issue 226[1].
//
// Important note 2: The linter doesn't maintain a list of Apple's trusted
// logs. The SCTs embedded in the certificate may not be from log's Apple
// actually trusts. Similarly the embedded SCT signatures are not validated
// in any way.
//
// [0]: https://support.apple.com/en-us/HT205280
// [1]: https://github.com/zmap/zlint/issues/226
func (l *sctPolicyCount) Execute(c *x509.Certificate) *lint.LintResult {
// Determine the required number of SCTs from separate logs
expected := appleCTPolicyExpectedSCTs(c)
// If there are no SCTs then the job is easy. We can return a Notice
// lint.LintResult immediately.
if len(c.SignedCertificateTimestampList) == 0 && expected > 0 {
return &lint.LintResult{
Status: lint.Notice,
Details: fmt.Sprintf(
"Certificate had 0 embedded SCTs. Browser policy may require %d for this certificate.",
expected),
}
}
// Build a map from LogID to SCT so that we can count embedded SCTs by unique
// log.
sctsByLogID := make(map[ct.SHA256Hash]*ct.SignedCertificateTimestamp)
for _, sct := range c.SignedCertificateTimestampList {
sctsByLogID[sct.LogID] = sct
}
// If the number of embedded SCTs from separate logs meets expected return
// a lint.Pass result.
if len(sctsByLogID) >= expected {
return &lint.LintResult{Status: lint.Pass}
}
// Otherwise return a Notice result - there weren't enough SCTs embedded in
// the certificate. More must be provided by OCSP stapling if the certificate
// is to meet Apple's CT policy.
return &lint.LintResult{
Status: lint.Notice,
Details: fmt.Sprintf(
"Certificate had %d embedded SCTs from distinct log IDs. "+
"Browser policy may require %d for this certificate.",
len(sctsByLogID), expected),
}
}
// appleCTPolicyExpectedSCTs returns a count of the number of SCTs expected to
// be embedded in the given certificate based on its lifetime.
//
// For this function the relevant portion of Apple's policy is the table
// "Number of embedded SCTs based on certificate lifetime" (Also reproduced in
// the `Execute` godoc comment).
func appleCTPolicyExpectedSCTs(cert *x509.Certificate) int {
// Lifetime is relative to the certificate's NotBefore date.
start := cert.NotBefore
// Thresholds is an ordered array of lifetime periods and their expected # of
// SCTs. A lifetime period is defined by the cutoff date relative to the
// start of the certificate's lifetime.
thresholds := []struct {
CutoffDate time.Time
Expected int
}{
// Start date ... 15 months
{CutoffDate: start.AddDate(0, 15, 0), Expected: 2},
// Start date ... 27 months
{CutoffDate: start.AddDate(0, 27, 0), Expected: 3},
// Start date ... 39 months
{CutoffDate: start.AddDate(0, 39, 0), Expected: 4},
}
// If the certificate's lifetime falls into any of the cutoff date ranges then
// we expect that range's expected # of SCTs for this certificate. This loop
// assumes the `thresholds` list is sorted in ascending order.
for _, threshold := range thresholds {
if cert.NotAfter.Before(threshold.CutoffDate) {
return threshold.Expected
}
}
// The certificate had a validity > 39 months.
return 5
}

View file

@ -0,0 +1,61 @@
/*
* 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 apple
import (
"time"
"github.com/zmap/zcrypto/x509"
"github.com/zmap/zlint/v3/lint"
"github.com/zmap/zlint/v3/util"
)
type serverCertValidityTooLong struct{}
func init() {
lint.RegisterLint(&lint.Lint{
Name: "e_tls_server_cert_valid_time_longer_than_398_days",
Description: "TLS server certificates issued on or after September 1, 2020 " +
"00:00 GMT/UTC must not have a validity period greater than 398 days",
Citation: "https://support.apple.com/en-us/HT211025",
Source: lint.AppleRootStorePolicy,
EffectiveDate: util.AppleReducedLifetimeDate,
Lint: &serverCertValidityTooLong{},
})
}
func (l *serverCertValidityTooLong) Initialize() error {
return nil
}
func (l *serverCertValidityTooLong) CheckApplies(c *x509.Certificate) bool {
return util.IsServerAuthCert(c) && !c.IsCA
}
func (l *serverCertValidityTooLong) Execute(c *x509.Certificate) *lint.LintResult {
// "TLS server certificates issued on or after September 1, 2020 00:00 GMT/UTC
// must not have a validity period greater than 398 days."
maxValidity := 398 * appleDayLength
// RFC 5280, section 4.1.2.5: "The validity period for a certificate is the period
// of time from notBefore through notAfter, inclusive."
certValidity := c.NotAfter.Add(1 * time.Second).Sub(c.NotBefore)
if certValidity > maxValidity {
return &lint.LintResult{Status: lint.Error}
}
return &lint.LintResult{Status: lint.Pass}
}

View file

@ -0,0 +1,67 @@
/*
* 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 apple
import (
"time"
"github.com/zmap/zcrypto/x509"
"github.com/zmap/zlint/v3/lint"
"github.com/zmap/zlint/v3/util"
)
type serverCertValidityAlmostTooLong struct{}
func init() {
lint.RegisterLint(&lint.Lint{
Name: "w_tls_server_cert_valid_time_longer_than_397_days",
Description: "TLS server certificates issued on or after September 1, 2020 " +
"00:00 GMT/UTC should not have a validity period greater than 397 days",
Citation: "https://support.apple.com/en-us/HT211025",
Source: lint.AppleRootStorePolicy,
EffectiveDate: util.AppleReducedLifetimeDate,
Lint: &serverCertValidityAlmostTooLong{},
})
}
func (l *serverCertValidityAlmostTooLong) Initialize() error {
return nil
}
func (l *serverCertValidityAlmostTooLong) CheckApplies(c *x509.Certificate) bool {
return util.IsServerAuthCert(c) && !c.IsCA
}
func (l *serverCertValidityAlmostTooLong) Execute(c *x509.Certificate) *lint.LintResult {
// "We recommend that certificates be issued with a maximum validity of 397 days."
warnValidity := 397 * appleDayLength
// RFC 5280, section 4.1.2.5: "The validity period for a certificate is the period
// of time from notBefore through notAfter, inclusive."
certValidity := c.NotAfter.Add(1 * time.Second).Sub(c.NotBefore)
if certValidity > warnValidity {
return &lint.LintResult{
// RFC 2119 has SHOULD and RECOMMENDED as equal. Since Apple recommends
// 397 days we treat this as a lint.Warn result as a violation of
// a SHOULD.
Status: lint.Warn,
Details: "Apple recommends that certificates be issued with a maximum " +
"validity of 397 days.",
}
}
return &lint.LintResult{Status: lint.Pass}
}

13
vendor/github.com/zmap/zlint/v3/lints/apple/time.go generated vendored Normal file
View file

@ -0,0 +1,13 @@
package apple
import "time"
// In the context of a root policy update on trusted certificate lifetimes[0]
// Apple provided an unambiguous definition for the length of a day:
// "398 days is measured with a day being equal to 86,400 seconds. Any time
// greater than this indicates an additional day of validity."
//
// We provide that value as a constant here for lints to use.
//
// [0]: https://support.apple.com/en-us/HT211025
var appleDayLength = 86400 * time.Second

View file

@ -0,0 +1,50 @@
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 caCommonNameMissing struct{}
func init() {
lint.RegisterLint(&lint.Lint{
Name: "e_ca_common_name_missing",
Description: "CA Certificates common name MUST be included.",
Citation: "BRs: 7.1.4.3.1",
Source: lint.CABFBaselineRequirements,
EffectiveDate: util.CABV148Date,
Lint: &caCommonNameMissing{},
})
}
func (l *caCommonNameMissing) Initialize() error {
return nil
}
func (l *caCommonNameMissing) CheckApplies(c *x509.Certificate) bool {
return util.IsCACert(c)
}
func (l *caCommonNameMissing) Execute(c *x509.Certificate) *lint.LintResult {
if c.Subject.CommonName == "" {
return &lint.LintResult{Status: lint.Error}
} else {
return &lint.LintResult{Status: lint.Pass}
}
}

View file

@ -0,0 +1,63 @@
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 caCountryNameInvalid struct{}
/************************************************
BRs: 7.1.2.1e
The Certificate Subject MUST contain the following:
countryName (OID 2.5.4.6).
This field MUST contain the twoletter ISO 31661 country code for the country
in which the CAs place of business is located.
************************************************/
func init() {
lint.RegisterLint(&lint.Lint{
Name: "e_ca_country_name_invalid",
Description: "Root and Subordinate CA certificates MUST have a two-letter country code specified in ISO 3166-1",
Citation: "BRs: 7.1.2.1",
Source: lint.CABFBaselineRequirements,
EffectiveDate: util.CABEffectiveDate,
Lint: &caCountryNameInvalid{},
})
}
func (l *caCountryNameInvalid) Initialize() error {
return nil
}
func (l *caCountryNameInvalid) CheckApplies(c *x509.Certificate) bool {
return c.IsCA
}
func (l *caCountryNameInvalid) Execute(c *x509.Certificate) *lint.LintResult {
if c.Subject.Country != nil {
for _, j := range c.Subject.Country {
if !util.IsISOCountryCode(j) {
return &lint.LintResult{Status: lint.Error}
}
}
return &lint.LintResult{Status: lint.Pass}
} else {
return &lint.LintResult{Status: lint.NA}
}
}

View file

@ -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 caCountryNameMissing struct{}
/************************************************
BRs: 7.1.2.1e
The Certificate Subject MUST contain the following:
countryName (OID 2.5.4.6).
This field MUST contain the twoletter ISO 31661 country code for the country
in which the CAs place of business is located.
************************************************/
func init() {
lint.RegisterLint(&lint.Lint{
Name: "e_ca_country_name_missing",
Description: "Root and Subordinate CA certificates MUST have a countryName present in subject information",
Citation: "BRs: 7.1.2.1",
Source: lint.CABFBaselineRequirements,
EffectiveDate: util.CABEffectiveDate,
Lint: &caCountryNameMissing{},
})
}
func (l *caCountryNameMissing) Initialize() error {
return nil
}
func (l *caCountryNameMissing) CheckApplies(c *x509.Certificate) bool {
return c.IsCA
}
func (l *caCountryNameMissing) Execute(c *x509.Certificate) *lint.LintResult {
if c.Subject.Country != nil && c.Subject.Country[0] != "" {
return &lint.LintResult{Status: lint.Pass}
} else {
return &lint.LintResult{Status: lint.Error}
}
}

View file

@ -0,0 +1,57 @@
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 caCRLSignNotSet struct{}
/************************************************
BRs: 7.1.2.1b
This extension MUST be present and MUST be marked critical. Bit positions for
keyCertSign and cRLSign MUST be set. If the Root CA Private Key is used for
signing OCSP responses, then the digitalSignature bit MUST be set.
************************************************/
func init() {
lint.RegisterLint(&lint.Lint{
Name: "e_ca_crl_sign_not_set",
Description: "Root and Subordinate CA certificate keyUsage extension's crlSign bit MUST be set",
Citation: "BRs: 7.1.2.1",
Source: lint.CABFBaselineRequirements,
EffectiveDate: util.CABEffectiveDate,
Lint: &caCRLSignNotSet{},
})
}
func (l *caCRLSignNotSet) Initialize() error {
return nil
}
func (l *caCRLSignNotSet) CheckApplies(c *x509.Certificate) bool {
return c.IsCA && util.IsExtInCert(c, util.KeyUsageOID)
}
func (l *caCRLSignNotSet) Execute(c *x509.Certificate) *lint.LintResult {
if c.KeyUsage&x509.KeyUsageCRLSign != 0 {
return &lint.LintResult{Status: lint.Pass}
} else {
return &lint.LintResult{Status: lint.Error}
}
}

View file

@ -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 caDigSignNotSet struct{}
/************************************************
BRs: 7.1.2.1b: Root CA Certificate keyUsage
This extension MUST be present and MUST be marked critical. Bit positions for keyCertSign and cRLSign MUST be set.
If the Root CA Private Key is used for signing OCSP responses, then the digitalSignature bit MUST be set.
BRs: 7.1.2.2e: Subordinate CA Certificate keyUsage
This extension MUST be present and MUST be marked critical. Bit positions for keyCertSign and cRLSign MUST be set.
If the Root CA Private Key is used for signing OCSP responses, then the digitalSignature bit MUST be set.
************************************************/
func init() {
lint.RegisterLint(&lint.Lint{
Name: "n_ca_digital_signature_not_set",
Description: "Root and Subordinate CA Certificates that wish to use their private key for signing OCSP responses will not be able to without their digital signature set",
Citation: "BRs: 7.1.2.1",
Source: lint.CABFBaselineRequirements,
EffectiveDate: util.CABEffectiveDate,
Lint: &caDigSignNotSet{},
})
}
func (l *caDigSignNotSet) Initialize() error {
return nil
}
func (l *caDigSignNotSet) CheckApplies(c *x509.Certificate) bool {
return c.IsCA && util.IsExtInCert(c, util.KeyUsageOID)
}
func (l *caDigSignNotSet) Execute(c *x509.Certificate) *lint.LintResult {
if c.KeyUsage&x509.KeyUsageDigitalSignature != 0 {
return &lint.LintResult{Status: lint.Pass}
} else {
return &lint.LintResult{Status: lint.Notice}
}
}

Some files were not shown because too many files have changed in this diff Show more