diff --git a/addons.go b/addons.go new file mode 100644 index 0000000..e33f63b --- /dev/null +++ b/addons.go @@ -0,0 +1,26 @@ +package main + +// Kubernetes' compatible ConfigMap +type configMap struct { + APIVersion string `yaml:"apiVersion"` // v1 + Kind string + Metadata metadata + Data map[string]string +} + +type metadata struct { + Namespace string + Name string +} + +func newConfigMap(name string) *configMap { + return &configMap{ + APIVersion: "v1", + Kind: "ConfigMap", + Metadata: metadata{ + Namespace: "kube-system", + Name: name, + }, + Data: make(map[string]string), + } +} diff --git a/go.mod b/go.mod index be2ce69..bc93648 100644 --- a/go.mod +++ b/go.mod @@ -1,10 +1,25 @@ module novit.nc/direktil/local-server require ( + cloud.google.com/go v0.24.0 github.com/cavaliercoder/go-cpio v0.0.0-20180626203310-925f9528c45e - github.com/cloudflare/cfssl v0.0.0-20180530085446-275fb308ac70 + github.com/cloudflare/cfssl v0.0.0-20180705210102-ff56ab5eb62a + github.com/go-sql-driver/mysql v1.4.0 github.com/golang/protobuf v1.1.0 - github.com/google/certificate-transparency-go v1.0.19 + github.com/google/certificate-transparency-go v1.0.20 + github.com/googleapis/gax-go v1.0.0 + github.com/kr/pretty v0.1.0 + github.com/mattn/go-sqlite3 v1.9.0 + golang.org/x/build v0.0.0-20180706045728-5a0b491d3d31 + golang.org/x/crypto v0.0.0-20180621125126-a49355c7e3f8 + golang.org/x/net v0.0.0-20180706051357-32a936f46389 + golang.org/x/oauth2 v0.0.0-20180620175406-ef147856a6dd golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f - novit.nc/direktil/pkg v0.0.0-20180619202319-3b512e61055e + golang.org/x/tools v0.0.0-20180706162124-435878328fa3 + google.golang.org/api v0.0.0-20180706000841-61180b1196c9 + google.golang.org/appengine v1.1.0 + google.golang.org/grpc v1.13.0 + gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 + honnef.co/go/tools v0.0.0-20180628101929-85dde8b51d3a + novit.nc/direktil/pkg v0.0.0-20180707011528-e82b59c0324d ) diff --git a/http.go b/http.go index 4dced7a..c86f858 100644 --- a/http.go +++ b/http.go @@ -1,6 +1,7 @@ package main import ( + "bytes" "encoding/json" "flag" "log" @@ -10,6 +11,7 @@ import ( "regexp" "strings" + yaml "gopkg.in/yaml.v2" "novit.nc/direktil/pkg/clustersconfig" ) @@ -193,3 +195,81 @@ func renderJSON(w http.ResponseWriter, v interface{}) { w.Header().Add("Content-Type", "application/json") json.NewEncoder(w).Encode(v) } + +func serveClusters(w http.ResponseWriter, r *http.Request) { + cfg, err := readConfig() + if err != nil { + http.Error(w, "", http.StatusServiceUnavailable) + return + } + + clusterNames := make([]string, len(cfg.Clusters)) + for i, cluster := range cfg.Clusters { + clusterNames[i] = cluster.Name + } + + renderJSON(w, clusterNames) +} + +func serveCluster(w http.ResponseWriter, r *http.Request) { + // "/clusters//" split => "", "clusters", "", "" + p := strings.Split(r.URL.Path, "/") + + if len(p) != 4 { + http.NotFound(w, r) + return + } + + clusterName, what := p[2], p[3] + + cfg, err := readConfig() + if err != nil { + http.Error(w, "", http.StatusServiceUnavailable) + return + } + + cluster := cfg.Cluster(clusterName) + if cluster == nil { + http.NotFound(w, r) + return + } + + switch what { + case "addons": + if cluster.Addons == "" { + log.Printf("cluster %q has no addons defined", clusterName) + http.NotFound(w, r) + return + } + + addons := cfg.Addons[cluster.Addons] + if addons == nil { + log.Printf("cluster %q: no addons with name %q", clusterName, cluster.Addons) + http.NotFound(w, r) + return + } + + clusterAsMap := asMap(cluster) + + cm := newConfigMap("cluster-addons") + + for _, addon := range addons { + buf := &bytes.Buffer{} + err := addon.Execute(buf, clusterAsMap, nil) + + if err != nil { + log.Printf("cluster %q: addons %q: failed to render %q: %v", + clusterName, cluster.Addons, addon.Name, err) + http.Error(w, "", http.StatusServiceUnavailable) + return + } + + cm.Data[addon.Name] = buf.String() + } + + yaml.NewEncoder(w).Encode(cm) + + default: + http.NotFound(w, r) + } +} diff --git a/main.go b/main.go index c0065bb..782bbfd 100644 --- a/main.go +++ b/main.go @@ -42,6 +42,9 @@ func main() { http.HandleFunc("/hosts", serveHosts) http.HandleFunc("/hosts/", serveHost) + http.HandleFunc("/clusters", serveClusters) + http.HandleFunc("/clusters/", serveCluster) + if *address != "" { log.Print("HTTP listening on ", *address) go log.Fatal(http.ListenAndServe(*address, nil)) diff --git a/render-context.go b/render-context.go index 4cff7d9..2e16fed 100644 --- a/render-context.go +++ b/render-context.go @@ -30,15 +30,17 @@ type renderContext struct { clusterConfig *clustersconfig.Config } -func newRenderContext(host *clustersconfig.Host, cfg *clustersconfig.Config) (*renderContext, error) { +func newRenderContext(host *clustersconfig.Host, cfg *clustersconfig.Config) (ctx *renderContext, err error) { cluster := cfg.Cluster(host.Cluster) if cluster == nil { - return nil, fmt.Errorf("no cluster named %q", host.Cluster) + err = fmt.Errorf("no cluster named %q", host.Cluster) + return } group := cfg.Group(host.Group) if group == nil { - return nil, fmt.Errorf("no group named %q", host.Group) + err = fmt.Errorf("no group named %q", host.Group) + return } vars := make(map[string]interface{}) @@ -78,6 +80,20 @@ func (ctx *renderContext) Config() (ba []byte, cfg *config.Config, err error) { return } + templateFuncs := ctx.templateFuncs(secretData, ctxMap) + + render := func(what string, t *clustersconfig.Template) (s string, err error) { + buf := &bytes.Buffer{} + err = t.Execute(buf, ctxMap, templateFuncs) + if err != nil { + log.Printf("host %s: failed to render %s [%q]: %v", ctx.Host.Name, what, t.Name, err) + return + } + + s = buf.String() + return + } + extraFuncs := ctx.templateFuncs(secretData, ctxMap) extraFuncs["static_pods"] = func(name string) (string, error) { @@ -86,14 +102,7 @@ func (ctx *renderContext) Config() (ba []byte, cfg *config.Config, err error) { return "", fmt.Errorf("no static pods template named %q", name) } - buf := &bytes.Buffer{} - err := t.Execute(buf, ctxMap, ctx.templateFuncs(secretData, ctxMap)) - if err != nil { - log.Printf("host %s: failed to render static pods: %v", ctx.Host.Name, err) - return "", err - } - - return buf.String(), nil + return render("static pods", t) } buf := bytes.NewBuffer(make([]byte, 0, 4096)) diff --git a/vendor/github.com/google/certificate-transparency-go/.gitignore b/vendor/github.com/google/certificate-transparency-go/.gitignore index cb3c4c0..26073b0 100644 --- a/vendor/github.com/google/certificate-transparency-go/.gitignore +++ b/vendor/github.com/google/certificate-transparency-go/.gitignore @@ -17,6 +17,8 @@ /dumpscts /etcdiscover /findlog +/goshawk +/gosmin /gossip_server /preloader /scanlog diff --git a/vendor/github.com/google/certificate-transparency-go/.travis.yml b/vendor/github.com/google/certificate-transparency-go/.travis.yml index e806c4c..23f3851 100644 --- a/vendor/github.com/google/certificate-transparency-go/.travis.yml +++ b/vendor/github.com/google/certificate-transparency-go/.travis.yml @@ -1,7 +1,7 @@ sudo: true # required for CI push into Kubernetes. language: go os: linux -go: 1.9 +go: "1.10" go_import_path: github.com/google/certificate-transparency-go @@ -22,8 +22,8 @@ install: - | ( cd ../protoc - wget https://github.com/google/protobuf/releases/download/v3.2.0/protoc-3.2.0-${TRAVIS_OS_NAME}-x86_64.zip - unzip protoc-3.2.0-${TRAVIS_OS_NAME}-x86_64.zip + wget https://github.com/google/protobuf/releases/download/v3.5.1/protoc-3.5.1-${TRAVIS_OS_NAME}-x86_64.zip + unzip protoc-3.5.1-${TRAVIS_OS_NAME}-x86_64.zip ) - export PATH=$(pwd)/../protoc/bin:$PATH - go get -d -t ./... diff --git a/vendor/github.com/google/certificate-transparency-go/CHANGELOG.md b/vendor/github.com/google/certificate-transparency-go/CHANGELOG.md new file mode 100644 index 0000000..cb8b7e3 --- /dev/null +++ b/vendor/github.com/google/certificate-transparency-go/CHANGELOG.md @@ -0,0 +1,194 @@ +# CERTIFICATE-TRANSPARENCY-GO Changelog + +## v1.0.19 - CTFE User Quota + +Published 2018-06-01 13:51:52 +0000 UTC + +CTFE now supports Trillian Log's explicit quota API; quota can be requested based on the remote user's IP, as well as per-issuing certificate in submitted chains. + +Commit [8736a411b4ff214ea20687e46c2b67d66ebd83fc](https://api.github.com/repos/google/certificate-transparency-go/commits/8736a411b4ff214ea20687e46c2b67d66ebd83fc) Download [zip](https://api.github.com/repos/google/certificate-transparency-go/zipball/v1.0.19) + +## v1.0.18 - Adding Migration Tool / Client Additions / K8 Config + +Published 2018-06-01 14:28:20 +0000 UTC + +Work on a log migration tool (Migrillian) is in progress. This is not yet ready for production use but will provide features for mirroring and migrating logs. + +The `RequestLog` API allows for logging of SCTs when they are issued by CTFE. + +The CT Go client now supports `GetEntryAndProof`. Utilities have been switched over to use the `glog` package. + +Commit [77abf2dac5410a62c04ac1c662c6d0fa54afc2dc](https://api.github.com/repos/google/certificate-transparency-go/commits/77abf2dac5410a62c04ac1c662c6d0fa54afc2dc) Download [zip](https://api.github.com/repos/google/certificate-transparency-go/zipball/v1.0.18) + +## v1.0.17 - Merkle verification / Tracing / Demo script / CORS + +Published 2018-06-01 14:25:16 +0000 UTC + +Now uses Merkle Tree verification from Trillian. + +The CT server now supports CORS. + +Request tracing added using OpenCensus. For GCE / K8 it just requires the flag to be enabled to export traces to Stackdriver. Other environments may differ. + +A demo script was added that goes through setting up a simple deployment suitable for development / demo purposes. This may be useful for those new to the project. + +Commit [3c3d22ce946447d047a03228ebb4a41e3e4eb15b](https://api.github.com/repos/google/certificate-transparency-go/commits/3c3d22ce946447d047a03228ebb4a41e3e4eb15b) Download [zip](https://api.github.com/repos/google/certificate-transparency-go/zipball/v1.0.17) + +## v1.0.16 - Lifecycle test / Go 1.10.1 + +Published 2018-06-01 14:22:23 +0000 UTC + +An integration test was added that goes through a create / drain queue / freeze lifecycle for a log. + +Changes to `x509` were merged from Go 1.10.1. + +Commit [a72423d09b410b80673fd1135ba1022d04bac6cd](https://api.github.com/repos/google/certificate-transparency-go/commits/a72423d09b410b80673fd1135ba1022d04bac6cd) Download [zip](https://api.github.com/repos/google/certificate-transparency-go/zipball/v1.0.16) + +## v1.0.15 - More control of verification, grpclb, stackdriver metrics + +Published 2018-06-01 14:20:32 +0000 UTC + +Facilities were added to the `x509` package to control whether verification checks are applied. + +Log server requests are now balanced using `gRPClb`. + +For Kubernetes, metrics can be published to Stackdriver monitoring. + +Commit [684d6eee6092774e54d301ccad0ed61bc8d010c1](https://api.github.com/repos/google/certificate-transparency-go/commits/684d6eee6092774e54d301ccad0ed61bc8d010c1) Download [zip](https://api.github.com/repos/google/certificate-transparency-go/zipball/v1.0.15) + +## v1.0.14 - SQLite Removed, LeafHashForLeaf + +Published 2018-06-01 14:15:37 +0000 UTC + +Support for SQLlite was removed. This motivation was ongoing test flakiness caused by multi-user access. This database may work for an embedded scenario but is not suitable for use in a server environment. + +A `LeafHashForLeaf` client API was added and is now used by the CT client and integration tests. + +Commit [698cd6a661196db4b2e71437422178ffe8705006](https://api.github.com/repos/google/certificate-transparency-go/commits/698cd6a661196db4b2e71437422178ffe8705006) Download [zip](https://api.github.com/repos/google/certificate-transparency-go/zipball/v1.0.14) + +## v1.0.13 - Crypto changes, util updates, sync with trillian repo, loglist verification + +Published 2018-06-01 14:15:21 +0000 UTC + +Some of our custom crypto package that were wrapping calls to the standard package have been removed and the base features used directly. + +Updates were made to GCE ingress and health checks. + +The log list utility can verify signatures. + +Commit [480c3654a70c5383b9543ec784203030aedbd3a5](https://api.github.com/repos/google/certificate-transparency-go/commits/480c3654a70c5383b9543ec784203030aedbd3a5) Download [zip](https://api.github.com/repos/google/certificate-transparency-go/zipball/v1.0.13) + +## v1.0.12 - Client / util updates & CTFE fixes + +Published 2018-06-01 14:13:42 +0000 UTC + +The CT client can now use a JSON loglist to find logs. + +CTFE had a fix applied for preissued precerts. + +A DNS client was added and CT client was extended to support DNS retrieval. + +Commit [74c06c95e0b304a050a1c33764c8a01d653a16e3](https://api.github.com/repos/google/certificate-transparency-go/commits/74c06c95e0b304a050a1c33764c8a01d653a16e3) Download [zip](https://api.github.com/repos/google/certificate-transparency-go/zipball/v1.0.12) + +## v1.0.11 - Kubernetes CI / Integration fixes + +Published 2018-06-01 14:12:18 +0000 UTC + +Updates to Kubernetes configs, mostly related to running a CI instance. + +Commit [0856acca7e0ab7f082ae83a1fbb5d21160962efc](https://api.github.com/repos/google/certificate-transparency-go/commits/0856acca7e0ab7f082ae83a1fbb5d21160962efc) Download [zip](https://api.github.com/repos/google/certificate-transparency-go/zipball/v1.0.11) + +## v1.0.10 - More scanner, x509, utility and client fixes. CTFE updates + +Published 2018-06-01 14:09:47 +0000 UTC + +The CT client was using the wrong protobuffer library package. To guard against this in future a check has been added to our lint config. + +The `x509` and `asn1` packages have had upstream fixes applied from Go 1.10rc1. + +Commit [1bec4527572c443752ad4f2830bef88be0533236](https://api.github.com/repos/google/certificate-transparency-go/commits/1bec4527572c443752ad4f2830bef88be0533236) Download [zip](https://api.github.com/repos/google/certificate-transparency-go/zipball/v1.0.10) + +## v1.0.9 - Scanner, x509, utility and client fixes + +Published 2018-06-01 14:11:13 +0000 UTC + +The `scanner` utility now displays throughput stats. + +Build instructions and README files were updated. + +The `certcheck` utility can be told to ignore unknown critical X.509 extensions. + +Commit [c06833528d04a94eed0c775104d1107bab9ae17c](https://api.github.com/repos/google/certificate-transparency-go/commits/c06833528d04a94eed0c775104d1107bab9ae17c) Download [zip](https://api.github.com/repos/google/certificate-transparency-go/zipball/v1.0.9) + +## v1.0.8 - Client fixes, align with trillian repo + +Published 2018-06-01 14:06:44 +0000 UTC + + + +Commit [e8b02c60f294b503dbb67de0868143f5d4935e56](https://api.github.com/repos/google/certificate-transparency-go/commits/e8b02c60f294b503dbb67de0868143f5d4935e56) Download [zip](https://api.github.com/repos/google/certificate-transparency-go/zipball/v1.0.8) + +## v1.0.7 - CTFE fixes + +Published 2018-06-01 14:06:13 +0000 UTC + +An issue was fixed with CTFE signature caching. In an unlikely set of circumstances this could lead to log mis-operation. While the chances of this are small, we recommend that versions prior to this one are not deployed. + +Commit [52c0590bd3b4b80c5497005b0f47e10557425eeb](https://api.github.com/repos/google/certificate-transparency-go/commits/52c0590bd3b4b80c5497005b0f47e10557425eeb) Download [zip](https://api.github.com/repos/google/certificate-transparency-go/zipball/v1.0.7) + +## v1.0.6 - crlcheck improvements / other fixes + +Published 2018-06-01 14:04:22 +0000 UTC + +The `crlcheck` utility has had several fixes and enhancements. Additionally the `hammer` now supports temporal logs. + +Commit [3955e4a00c42e83ff17ce25003976159c5d0f0f9](https://api.github.com/repos/google/certificate-transparency-go/commits/3955e4a00c42e83ff17ce25003976159c5d0f0f9) Download [zip](https://api.github.com/repos/google/certificate-transparency-go/zipball/v1.0.6) + +## v1.0.5 - X509 and asn1 fixes + +Published 2018-06-01 14:02:58 +0000 UTC + +This release is mostly fixes to the `x509` and `asn1` packages. Some command line utilties were also updated. + +Commit [ae40d07cce12f1227c6e658e61c9dddb7646f97b](https://api.github.com/repos/google/certificate-transparency-go/commits/ae40d07cce12f1227c6e658e61c9dddb7646f97b) Download [zip](https://api.github.com/repos/google/certificate-transparency-go/zipball/v1.0.5) + +## v1.0.4 - Multi log backend configs + +Published 2018-06-01 14:02:07 +0000 UTC + +Support was added to allow CTFE to use multiple backends, each serving a distinct set of logs. It allows for e.g. regional backend deployment with common frontend servers. + +Commit [62023ed90b41fa40854957b5dec7d9d73594723f](https://api.github.com/repos/google/certificate-transparency-go/commits/62023ed90b41fa40854957b5dec7d9d73594723f) Download [zip](https://api.github.com/repos/google/certificate-transparency-go/zipball/v1.0.4) + +## v1.0.3 - Hammer updates, use standard context + +Published 2018-06-01 14:01:11 +0000 UTC + +After the Go 1.9 migration references to anything other than the standard `context` package have been removed. This is the only one that should be used from now on. + +Commit [b28beed8b9aceacc705e0ff4a11d435a310e3d97](https://api.github.com/repos/google/certificate-transparency-go/commits/b28beed8b9aceacc705e0ff4a11d435a310e3d97) Download [zip](https://api.github.com/repos/google/certificate-transparency-go/zipball/v1.0.3) + +## v1.0.2 - Go 1.9 + +Published 2018-06-01 14:00:00 +0000 UTC + +Go 1.9 is now required to build the code. + +Commit [3aed33d672ee43f04b1e8a00b25ca3e2e2e74309](https://api.github.com/repos/google/certificate-transparency-go/commits/3aed33d672ee43f04b1e8a00b25ca3e2e2e74309) Download [zip](https://api.github.com/repos/google/certificate-transparency-go/zipball/v1.0.2) + +## v1.0.1 - Hammer and client improvements + +Published 2018-06-01 13:59:29 +0000 UTC + + + +Commit [c28796cc21776667fb05d6300e32d9517be96515](https://api.github.com/repos/google/certificate-transparency-go/commits/c28796cc21776667fb05d6300e32d9517be96515) Download [zip](https://api.github.com/repos/google/certificate-transparency-go/zipball/v1.0.1) + +## v1.0 - First Trillian CT Release + +Published 2018-06-01 13:59:00 +0000 UTC + +This is the point that corresponds to the 1.0 release in the trillian repo. + +Commit [abb79e468b6f3bbd48d1ab0c9e68febf80d52c4d](https://api.github.com/repos/google/certificate-transparency-go/commits/abb79e468b6f3bbd48d1ab0c9e68febf80d52c4d) Download [zip](https://api.github.com/repos/google/certificate-transparency-go/zipball/v1.0) + diff --git a/vendor/github.com/google/certificate-transparency-go/client/configpb/multilog.pb.go b/vendor/github.com/google/certificate-transparency-go/client/configpb/multilog.pb.go index ee4bdba..2e55408 100644 --- a/vendor/github.com/google/certificate-transparency-go/client/configpb/multilog.pb.go +++ b/vendor/github.com/google/certificate-transparency-go/client/configpb/multilog.pb.go @@ -22,7 +22,7 @@ const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package // TemporalLogConfig is a set of LogShardConfig messages, whose // time limits should be contiguous. type TemporalLogConfig struct { - Shard []*LogShardConfig `protobuf:"bytes,1,rep,name=shard" json:"shard,omitempty"` + Shard []*LogShardConfig `protobuf:"bytes,1,rep,name=shard,proto3" json:"shard,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -62,17 +62,17 @@ func (m *TemporalLogConfig) GetShard() []*LogShardConfig { // LogShardConfig describes the acceptable date range for a single shard of a temporal // log. type LogShardConfig struct { - Uri string `protobuf:"bytes,1,opt,name=uri" json:"uri,omitempty"` + Uri string `protobuf:"bytes,1,opt,name=uri,proto3" json:"uri,omitempty"` // The log's public key in DER-encoded PKIX form. PublicKeyDer []byte `protobuf:"bytes,2,opt,name=public_key_der,json=publicKeyDer,proto3" json:"public_key_der,omitempty"` // not_after_start defines the start of the range of acceptable NotAfter // values, inclusive. // Leaving this unset implies no lower bound to the range. - NotAfterStart *timestamp.Timestamp `protobuf:"bytes,3,opt,name=not_after_start,json=notAfterStart" json:"not_after_start,omitempty"` + NotAfterStart *timestamp.Timestamp `protobuf:"bytes,3,opt,name=not_after_start,json=notAfterStart,proto3" json:"not_after_start,omitempty"` // not_after_limit defines the end of the range of acceptable NotAfter values, // exclusive. // Leaving this unset implies no upper bound to the range. - NotAfterLimit *timestamp.Timestamp `protobuf:"bytes,4,opt,name=not_after_limit,json=notAfterLimit" json:"not_after_limit,omitempty"` + NotAfterLimit *timestamp.Timestamp `protobuf:"bytes,4,opt,name=not_after_limit,json=notAfterLimit,proto3" json:"not_after_limit,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` diff --git a/vendor/github.com/google/certificate-transparency-go/cloudbuild_tag.yaml b/vendor/github.com/google/certificate-transparency-go/cloudbuild_tag.yaml new file mode 100644 index 0000000..8c8c5ab --- /dev/null +++ b/vendor/github.com/google/certificate-transparency-go/cloudbuild_tag.yaml @@ -0,0 +1,10 @@ +steps: +- id: build_ctfe + name: gcr.io/cloud-builders/docker + args: + - build + - --file=trillian/examples/deployment/docker/ctfe/Dockerfile + - --tag=gcr.io/${PROJECT_ID}/ctfe:${TAG_NAME} + - . +images: +- gcr.io/${PROJECT_ID}/ctfe:${TAG_NAME} diff --git a/vendor/github.com/google/certificate-transparency-go/gometalinter.json b/vendor/github.com/google/certificate-transparency-go/gometalinter.json index f85f825..4eba1b6 100644 --- a/vendor/github.com/google/certificate-transparency-go/gometalinter.json +++ b/vendor/github.com/google/certificate-transparency-go/gometalinter.json @@ -1,4 +1,5 @@ { + "Deadline": "60s", "Linters": { "license": "./scripts/check_license.sh:PATH:LINE:MESSAGE", "forked": "./scripts/check_forked.sh:PATH:LINE:MESSAGE", diff --git a/vendor/github.com/google/certificate-transparency-go/gossip/minimal/testdata/Makefile b/vendor/github.com/google/certificate-transparency-go/gossip/minimal/testdata/Makefile new file mode 100644 index 0000000..f6b5fc1 --- /dev/null +++ b/vendor/github.com/google/certificate-transparency-go/gossip/minimal/testdata/Makefile @@ -0,0 +1,37 @@ +all: ca + +# The following private keys are never regenerated. +SERVER_PRIVKEYS=gossiper.privkey.pem + +# Server public keys are derived from the corresponding private keys. +SERVER_PUBKEYS=$(subst .privkey,.pubkey,$(SERVER_PRIVKEYS)) + +# Build public keys from private keys +pubkeys: $(SERVER_PUBKEYS) +gossiper.pubkey.pem: gossiper.privkey.pem + openssl ec -in $< -pubout -out $@ -passin pass:$(GOSSIPER_PWD) + +ROOT_CA_PRIVKEY=gossiper.privkey.pem +ROOT_CA_PWD=hissing-sid + +ca: root-ca.cert + +# Fake Root CA +root-ca.cert: gossiper.privkey.pem root-ca.cfg + openssl req -new -x509 -config root-ca.cfg -set_serial 0x0406cafe -days 3650 -extensions v3_ca -inform pem -key gossiper.privkey.pem -passin pass:$(ROOT_CA_PWD) -out $@ +show-ca: root-ca.cert + openssl x509 -inform pem -in $< -text -noout + +# clean removes things that regenerate exactly the same. +clean: + rm -f $(SERVER_PUBKEYS) +# distclean removes things that regenerate with changes (e.g. timestamped, randomized). +distclean: clean + rm -f $(SERVER_PUBKEYS) root-ca.cert + +# The newkey target creates a fresh private key; should never be needed. +newkey: fresh.privkey.pem +fresh.privkey.pem: + openssl ecparam -genkey -name prime256v1 -noout -out $@.unencrypted + openssl ec -in $@.unencrypted -out $@ -des # Prompts for password + rm -f $@.unencrypted diff --git a/vendor/github.com/google/certificate-transparency-go/gossip/minimal/testdata/dup-source-name.cfg b/vendor/github.com/google/certificate-transparency-go/gossip/minimal/testdata/dup-source-name.cfg new file mode 100644 index 0000000..9b487cc --- /dev/null +++ b/vendor/github.com/google/certificate-transparency-go/gossip/minimal/testdata/dup-source-name.cfg @@ -0,0 +1,32 @@ +source_log: < + name: "theSourceOfAllSTHs" + url: "http://example.com/ct-source" + min_req_interval: < + seconds: 3600 + > + public_key: { + der: "\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x07\xf8\x51\xaf\xaa\x8c\x56\x83\x90\x31\xb7\x80\xe3\xd6\x1a\xf7\x2f\x36\x06\x71\xec\xdd\x3b\xbe\x7e\x36\x6f\x0d\x1c\x1c\x60\x0b\x7f\xf5\x9f\xff\xe5\x24\x49\x34\x56\xf2\x4b\x10\x5f\xbf\x08\x1f\xf9\x0e\xcf\x35\xb5\x8a\x8a\x8b\x30\x0a\x54\xb7\xbf\x1d\x4d\xb9" + } +> +source_log: < + name: "theSourceOfAllSTHs" + url: "http://example.com/ct-source-2" + min_req_interval: < + seconds: 3600 + > + public_key: { + der: "\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x07\xf8\x51\xaf\xaa\x8c\x56\x83\x90\x31\xb7\x80\xe3\xd6\x1a\xf7\x2f\x36\x06\x71\xec\xdd\x3b\xbe\x7e\x36\x6f\x0d\x1c\x1c\x60\x0b\x7f\xf5\x9f\xff\xe5\x24\x49\x34\x56\xf2\x4b\x10\x5f\xbf\x08\x1f\xf9\x0e\xcf\x35\xb5\x8a\x8a\x8b\x30\x0a\x54\xb7\xbf\x1d\x4d\xb9" + } +> +dest_log: < + name: "theDestinationOfAllSTHs" + url: "http://example.com/ct-dest" + min_req_interval: < + seconds: 60 + > +> +root_cert: "-----BEGIN CERTIFICATE-----\nMIICCzCCAbCgAwIBAgIEBAbK/jAKBggqhkjOPQQDAjBpMQswCQYDVQQGEwJHQjEP\nMA0GA1UECBMGTG9uZG9uMQ8wDQYDVQQHEwZMb25kb24xDzANBgNVBAoTBkdvb2ds\nZTEMMAoGA1UECxMDRW5nMRkwFwYDVQQDExBUZXN0R29zc2lwZXJSb290MB4XDTE4\nMDIyMzEzNDUyOVoXDTI4MDIyMTEzNDUyOVowaTELMAkGA1UEBhMCR0IxDzANBgNV\nBAgTBkxvbmRvbjEPMA0GA1UEBxMGTG9uZG9uMQ8wDQYDVQQKEwZHb29nbGUxDDAK\nBgNVBAsTA0VuZzEZMBcGA1UEAxMQVGVzdEdvc3NpcGVyUm9vdDBZMBMGByqGSM49\nAgEGCCqGSM49AwEHA0IABOqzZufPSU6hMJOIbljkjklDvQKBGYW9VenI6i7HSiyH\nccPUuh3F3fbbe2MrLtuRCjH7nqvcELPqBJsL3IVgQJijRjBEMA0GA1UdDgQGBAQR\nEhMUMA8GA1UdIwQIMAaABBESExQwEgYDVR0TAQH/BAgwBgEB/wIBAzAOBgNVHQ8B\nAf8EBAMCAgQwCgYIKoZIzj0EAwIDSQAwRgIhAICXxzQ+EulZALo8em3KujsOCpNY\n6lvLF5lqBMLS9fxwAiEAkh54N7Dq6P+3Sl/u15TA5DKhFPqgnvnB51wXGAsDhN0=\n-----END CERTIFICATE-----" +private_key: < + type_url: "type.googleapis.com/keyspb.PEMKeyFile" + value: "\n\035testdata/gossiper.privkey.pem\022\013hissing-sid" +> diff --git a/vendor/github.com/google/certificate-transparency-go/gossip/minimal/testdata/goshawk.cfg b/vendor/github.com/google/certificate-transparency-go/gossip/minimal/testdata/goshawk.cfg new file mode 100644 index 0000000..c7825fd --- /dev/null +++ b/vendor/github.com/google/certificate-transparency-go/gossip/minimal/testdata/goshawk.cfg @@ -0,0 +1,17 @@ +source_log: < + name: "theSourceOfAllSTHs" + url: "http://example.com/ct-source" + min_req_interval: < + seconds: 3600 + > + public_key: { + der: "\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x07\xf8\x51\xaf\xaa\x8c\x56\x83\x90\x31\xb7\x80\xe3\xd6\x1a\xf7\x2f\x36\x06\x71\xec\xdd\x3b\xbe\x7e\x36\x6f\x0d\x1c\x1c\x60\x0b\x7f\xf5\x9f\xff\xe5\x24\x49\x34\x56\xf2\x4b\x10\x5f\xbf\x08\x1f\xf9\x0e\xcf\x35\xb5\x8a\x8a\x8b\x30\x0a\x54\xb7\xbf\x1d\x4d\xb9" + } +> +dest_log: < + name: "theDestinationOfAllSTHs" + url: "http://example.com/ct-dest" + min_req_interval: < + seconds: 60 + > +> diff --git a/vendor/github.com/google/certificate-transparency-go/gossip/minimal/testdata/gossiper.privkey.pem b/vendor/github.com/google/certificate-transparency-go/gossip/minimal/testdata/gossiper.privkey.pem new file mode 100644 index 0000000..09336f4 --- /dev/null +++ b/vendor/github.com/google/certificate-transparency-go/gossip/minimal/testdata/gossiper.privkey.pem @@ -0,0 +1,8 @@ +-----BEGIN EC PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-CBC,559BE893ECD7A88C + +UOwSw+WlSv5LLiBZSCnR12FX13Hk1a3vavdpUde4W4qawQgJSMqLa3it8Lfadtnm +GfGVqN+gF5KFiNWxgMs2qRcbdQ03ZlMmoH8Z8jPQHXvKseJvME8tZQWPvJ15rbXh +G9Lcx7NYlm0miHPy3ras8ci58HSDqz9Z7yOdgHzPpiU= +-----END EC PRIVATE KEY----- diff --git a/vendor/github.com/google/certificate-transparency-go/gossip/minimal/testdata/hawk-dup-source-name.cfg b/vendor/github.com/google/certificate-transparency-go/gossip/minimal/testdata/hawk-dup-source-name.cfg new file mode 100644 index 0000000..9ea4484 --- /dev/null +++ b/vendor/github.com/google/certificate-transparency-go/gossip/minimal/testdata/hawk-dup-source-name.cfg @@ -0,0 +1,27 @@ +source_log: < + name: "theSourceOfAllSTHs" + url: "http://example.com/ct-source" + min_req_interval: < + seconds: 3600 + > + public_key: { + der: "\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x07\xf8\x51\xaf\xaa\x8c\x56\x83\x90\x31\xb7\x80\xe3\xd6\x1a\xf7\x2f\x36\x06\x71\xec\xdd\x3b\xbe\x7e\x36\x6f\x0d\x1c\x1c\x60\x0b\x7f\xf5\x9f\xff\xe5\x24\x49\x34\x56\xf2\x4b\x10\x5f\xbf\x08\x1f\xf9\x0e\xcf\x35\xb5\x8a\x8a\x8b\x30\x0a\x54\xb7\xbf\x1d\x4d\xb9" + } +> +source_log: < + name: "theSourceOfAllSTHs" + url: "http://example.com/ct-source-2" + min_req_interval: < + seconds: 3600 + > + public_key: { + der: "\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x07\xf8\x51\xaf\xaa\x8c\x56\x83\x90\x31\xb7\x80\xe3\xd6\x1a\xf7\x2f\x36\x06\x71\xec\xdd\x3b\xbe\x7e\x36\x6f\x0d\x1c\x1c\x60\x0b\x7f\xf5\x9f\xff\xe5\x24\x49\x34\x56\xf2\x4b\x10\x5f\xbf\x08\x1f\xf9\x0e\xcf\x35\xb5\x8a\x8a\x8b\x30\x0a\x54\xb7\xbf\x1d\x4d\xb9" + } +> +dest_log: < + name: "theDestinationOfAllSTHs" + url: "http://example.com/ct-dest" + min_req_interval: < + seconds: 60 + > +> \ No newline at end of file diff --git a/vendor/github.com/google/certificate-transparency-go/gossip/minimal/testdata/hawk-no-dest-name.cfg b/vendor/github.com/google/certificate-transparency-go/gossip/minimal/testdata/hawk-no-dest-name.cfg new file mode 100644 index 0000000..0fad377 --- /dev/null +++ b/vendor/github.com/google/certificate-transparency-go/gossip/minimal/testdata/hawk-no-dest-name.cfg @@ -0,0 +1,13 @@ +source_log: < + name: "theSourceOfAllSTHs" + url: "http://example.com/ct-source" + min_req_interval: < + seconds: 3600 + > +> +dest_log: < + url: "http://example.com/ct-dest" + min_req_interval: < + seconds: 60 + > +> diff --git a/vendor/github.com/google/certificate-transparency-go/gossip/minimal/testdata/hawk-no-source-log.cfg b/vendor/github.com/google/certificate-transparency-go/gossip/minimal/testdata/hawk-no-source-log.cfg new file mode 100644 index 0000000..070e111 --- /dev/null +++ b/vendor/github.com/google/certificate-transparency-go/gossip/minimal/testdata/hawk-no-source-log.cfg @@ -0,0 +1,7 @@ +dest_log: < + name: "theDestinationOfAllSTHs" + url: "http://example.com/ct-dest" + min_req_interval: < + seconds: 60 + > +> diff --git a/vendor/github.com/google/certificate-transparency-go/gossip/minimal/testdata/hawk-no-source-name.cfg b/vendor/github.com/google/certificate-transparency-go/gossip/minimal/testdata/hawk-no-source-name.cfg new file mode 100644 index 0000000..98d5deb --- /dev/null +++ b/vendor/github.com/google/certificate-transparency-go/gossip/minimal/testdata/hawk-no-source-name.cfg @@ -0,0 +1,13 @@ +source_log: < + url: "http://example.com/ct-source" + min_req_interval: < + seconds: 3600 + > +> +dest_log: < + name: "theDestinationOfAllSTHs" + url: "http://example.com/ct-dest" + min_req_interval: < + seconds: 60 + > +> \ No newline at end of file diff --git a/vendor/github.com/google/certificate-transparency-go/gossip/minimal/testdata/invalid-private-key.cfg b/vendor/github.com/google/certificate-transparency-go/gossip/minimal/testdata/invalid-private-key.cfg new file mode 100644 index 0000000..20febcc --- /dev/null +++ b/vendor/github.com/google/certificate-transparency-go/gossip/minimal/testdata/invalid-private-key.cfg @@ -0,0 +1,19 @@ +source_log: < + name: "theSourceOfAllSTHs" + url: "http://example.com/ct-source" + min_req_interval: < + seconds: 3600 + > +> +dest_log: < + name: "theDestinationOfAllSTHs" + url: "http://example.com/ct-dest" + min_req_interval: < + seconds: 60 + > +> +root_cert: "-----BEGIN CERTIFICATE-----\nMIICCzCCAbCgAwIBAgIEBAbK/jAKBggqhkjOPQQDAjBpMQswCQYDVQQGEwJHQjEP\nMA0GA1UECBMGTG9uZG9uMQ8wDQYDVQQHEwZMb25kb24xDzANBgNVBAoTBkdvb2ds\nZTEMMAoGA1UECxMDRW5nMRkwFwYDVQQDExBUZXN0R29zc2lwZXJSb290MB4XDTE4\nMDIyMzEzNDUyOVoXDTI4MDIyMTEzNDUyOVowaTELMAkGA1UEBhMCR0IxDzANBgNV\nBAgTBkxvbmRvbjEPMA0GA1UEBxMGTG9uZG9uMQ8wDQYDVQQKEwZHb29nbGUxDDAK\nBgNVBAsTA0VuZzEZMBcGA1UEAxMQVGVzdEdvc3NpcGVyUm9vdDBZMBMGByqGSM49\nAgEGCCqGSM49AwEHA0IABOqzZufPSU6hMJOIbljkjklDvQKBGYW9VenI6i7HSiyH\nccPUuh3F3fbbe2MrLtuRCjH7nqvcELPqBJsL3IVgQJijRjBEMA0GA1UdDgQGBAQR\nEhMUMA8GA1UdIwQIMAaABBESExQwEgYDVR0TAQH/BAgwBgEB/wIBAzAOBgNVHQ8B\nAf8EBAMCAgQwCgYIKoZIzj0EAwIDSQAwRgIhAICXxzQ+EulZALo8em3KujsOCpNY\n6lvLF5lqBMLS9fxwAiEAkh54N7Dq6P+3Sl/u15TA5DKhFPqgnvnB51wXGAsDhN0=\n-----END CERTIFICATE-----" +private_key: < + type_url: "type.googleapis.com/keyspb.PEMKeyFile" + value: "\n\035testdata/gone.privkey.pem\022\013hissing-sid" +> diff --git a/vendor/github.com/google/certificate-transparency-go/gossip/minimal/testdata/invalid-root-cert.cfg b/vendor/github.com/google/certificate-transparency-go/gossip/minimal/testdata/invalid-root-cert.cfg new file mode 100644 index 0000000..ee3a359 --- /dev/null +++ b/vendor/github.com/google/certificate-transparency-go/gossip/minimal/testdata/invalid-root-cert.cfg @@ -0,0 +1,19 @@ +source_log: < + name: "theSourceOfAllSTHs" + url: "http://example.com/ct-source" + min_req_interval: < + seconds: 3600 + > +> +dest_log: < + name: "theDestinationOfAllSTHs" + url: "http://example.com/ct-dest" + min_req_interval: < + seconds: 60 + > +> +root_cert: "-----BEGIN CARTIFICATE-----\nMIICCzCCAbCgAwIBAgIEBAbK/jAKBggqhkjOPQQDAjBpMQswCQYDVQQGEwJHQjEP\nMA0GA1UECBMGTG9uZG9uMQ8wDQYDVQQHEwZMb25kb24xDzANBgNVBAoTBkdvb2ds\nZTEMMAoGA1UECxMDRW5nMRkwFwYDVQQDExBUZXN0R29zc2lwZXJSb290MB4XDTE4\nMDIyMzEzNDUyOVoXDTI4MDIyMTEzNDUyOVowaTELMAkGA1UEBhMCR0IxDzANBgNV\nBAgTBkxvbmRvbjEPMA0GA1UEBxMGTG9uZG9uMQ8wDQYDVQQKEwZHb29nbGUxDDAK\nBgNVBAsTA0VuZzEZMBcGA1UEAxMQVGVzdEdvc3NpcGVyUm9vdDBZMBMGByqGSM49\nAgEGCCqGSM49AwEHA0IABOqzZufPSU6hMJOIbljkjklDvQKBGYW9VenI6i7HSiyH\nccPUuh3F3fbbe2MrLtuRCjH7nqvcELPqBJsL3IVgQJijRjBEMA0GA1UdDgQGBAQR\nEhMUMA8GA1UdIwQIMAaABBESExQwEgYDVR0TAQH/BAgwBgEB/wIBAzAOBgNVHQ8B\nAf8EBAMCAgQwCgYIKoZIzj0EAwIDSQAwRgIhAICXxzQ+EulZALo8em3KujsOCpNY\n6lvLF5lqBMLS9fxwAiEAkh54N7Dq6P+3Sl/u15TA5DKhFPqgnvnB51wXGAsDhN0=\n-----END CERTIFICATE-----" +private_key: < + type_url: "type.googleapis.com/keyspb.PEMKeyFile" + value: "\n\035testdata/gossiper.privkey.pem\022\013hissing-sid" +> diff --git a/vendor/github.com/google/certificate-transparency-go/gossip/minimal/testdata/invalid-source-duration.cfg b/vendor/github.com/google/certificate-transparency-go/gossip/minimal/testdata/invalid-source-duration.cfg new file mode 100644 index 0000000..1470b0c --- /dev/null +++ b/vendor/github.com/google/certificate-transparency-go/gossip/minimal/testdata/invalid-source-duration.cfg @@ -0,0 +1,20 @@ +source_log: < + name: "theSourceOfAllSTHs" + url: "http://example.com/ct-source" + min_req_interval: < + seconds: 10 + nanos: -20 + > +> +dest_log: < + name: "theDestinationOfAllSTHs" + url: "http://example.com/ct-dest" + min_req_interval: < + seconds: 60 + > +> +root_cert: "-----BEGIN CERTIFICATE-----\nMIICCzCCAbCgAwIBAgIEBAbK/jAKBggqhkjOPQQDAjBpMQswCQYDVQQGEwJHQjEP\nMA0GA1UECBMGTG9uZG9uMQ8wDQYDVQQHEwZMb25kb24xDzANBgNVBAoTBkdvb2ds\nZTEMMAoGA1UECxMDRW5nMRkwFwYDVQQDExBUZXN0R29zc2lwZXJSb290MB4XDTE4\nMDIyMzEzNDUyOVoXDTI4MDIyMTEzNDUyOVowaTELMAkGA1UEBhMCR0IxDzANBgNV\nBAgTBkxvbmRvbjEPMA0GA1UEBxMGTG9uZG9uMQ8wDQYDVQQKEwZHb29nbGUxDDAK\nBgNVBAsTA0VuZzEZMBcGA1UEAxMQVGVzdEdvc3NpcGVyUm9vdDBZMBMGByqGSM49\nAgEGCCqGSM49AwEHA0IABOqzZufPSU6hMJOIbljkjklDvQKBGYW9VenI6i7HSiyH\nccPUuh3F3fbbe2MrLtuRCjH7nqvcELPqBJsL3IVgQJijRjBEMA0GA1UdDgQGBAQR\nEhMUMA8GA1UdIwQIMAaABBESExQwEgYDVR0TAQH/BAgwBgEB/wIBAzAOBgNVHQ8B\nAf8EBAMCAgQwCgYIKoZIzj0EAwIDSQAwRgIhAICXxzQ+EulZALo8em3KujsOCpNY\n6lvLF5lqBMLS9fxwAiEAkh54N7Dq6P+3Sl/u15TA5DKhFPqgnvnB51wXGAsDhN0=\n-----END CERTIFICATE-----" +private_key: < + type_url: "type.googleapis.com/keyspb.PEMKeyFile" + value: "\n\035testdata/gossiper.privkey.pem\022\013hissing-sid" +> diff --git a/vendor/github.com/google/certificate-transparency-go/gossip/minimal/testdata/invalid-source-pubkey.cfg b/vendor/github.com/google/certificate-transparency-go/gossip/minimal/testdata/invalid-source-pubkey.cfg new file mode 100644 index 0000000..b86bc02 --- /dev/null +++ b/vendor/github.com/google/certificate-transparency-go/gossip/minimal/testdata/invalid-source-pubkey.cfg @@ -0,0 +1,22 @@ +source_log: < + name: "theSourceOfAllSTHs" + url: "http://example.com/ct-source" + min_req_interval: < + seconds: 3600 + > + public_key: { + der: "\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x07\xf8\x51\xaf\xaa\x8c\x56\x83\x90\x31\xb7\x80\xe3\xd6\x1a\xf7\x2f\x36\x06\x71\xec\xdd\x3b\xbe\x7e\x36\x6f\x0d\x1c\x1c\x60\x0b\x7f\xf5\x9f\xff\xe5\x24\x49\x34\x56\xf2\x4b\x10\x5f\xbf\x08\x1f\xf9\x0e\xcf\x35\xb5\x8a\x8a\x8b\x30\x0a\x54\xb7\xbf\x1d\x4d" + } +> +dest_log: < + name: "theDestinationOfAllSTHs" + url: "http://example.com/ct-dest" + min_req_interval: < + seconds: 60 + > +> +root_cert: "-----BEGIN CERTIFICATE-----\nMIICCzCCAbCgAwIBAgIEBAbK/jAKBggqhkjOPQQDAjBpMQswCQYDVQQGEwJHQjEP\nMA0GA1UECBMGTG9uZG9uMQ8wDQYDVQQHEwZMb25kb24xDzANBgNVBAoTBkdvb2ds\nZTEMMAoGA1UECxMDRW5nMRkwFwYDVQQDExBUZXN0R29zc2lwZXJSb290MB4XDTE4\nMDIyMzEzNDUyOVoXDTI4MDIyMTEzNDUyOVowaTELMAkGA1UEBhMCR0IxDzANBgNV\nBAgTBkxvbmRvbjEPMA0GA1UEBxMGTG9uZG9uMQ8wDQYDVQQKEwZHb29nbGUxDDAK\nBgNVBAsTA0VuZzEZMBcGA1UEAxMQVGVzdEdvc3NpcGVyUm9vdDBZMBMGByqGSM49\nAgEGCCqGSM49AwEHA0IABOqzZufPSU6hMJOIbljkjklDvQKBGYW9VenI6i7HSiyH\nccPUuh3F3fbbe2MrLtuRCjH7nqvcELPqBJsL3IVgQJijRjBEMA0GA1UdDgQGBAQR\nEhMUMA8GA1UdIwQIMAaABBESExQwEgYDVR0TAQH/BAgwBgEB/wIBAzAOBgNVHQ8B\nAf8EBAMCAgQwCgYIKoZIzj0EAwIDSQAwRgIhAICXxzQ+EulZALo8em3KujsOCpNY\n6lvLF5lqBMLS9fxwAiEAkh54N7Dq6P+3Sl/u15TA5DKhFPqgnvnB51wXGAsDhN0=\n-----END CERTIFICATE-----" +private_key: < + type_url: "type.googleapis.com/keyspb.PEMKeyFile" + value: "\n\035testdata/gossiper.privkey.pem\022\013hissing-sid" +> diff --git a/vendor/github.com/google/certificate-transparency-go/gossip/minimal/testdata/no-dest-log.cfg b/vendor/github.com/google/certificate-transparency-go/gossip/minimal/testdata/no-dest-log.cfg new file mode 100644 index 0000000..a254ded --- /dev/null +++ b/vendor/github.com/google/certificate-transparency-go/gossip/minimal/testdata/no-dest-log.cfg @@ -0,0 +1,15 @@ +source_log: < + name: "theSourceOfAllSTHs" + url: "http://example.com/ct-source" + min_req_interval: < + seconds: 3600 + > + public_key: { + der: "\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x07\xf8\x51\xaf\xaa\x8c\x56\x83\x90\x31\xb7\x80\xe3\xd6\x1a\xf7\x2f\x36\x06\x71\xec\xdd\x3b\xbe\x7e\x36\x6f\x0d\x1c\x1c\x60\x0b\x7f\xf5\x9f\xff\xe5\x24\x49\x34\x56\xf2\x4b\x10\x5f\xbf\x08\x1f\xf9\x0e\xcf\x35\xb5\x8a\x8a\x8b\x30\x0a\x54\xb7\xbf\x1d\x4d\xb9" + } +> +root_cert: "-----BEGIN CERTIFICATE-----\nMIICCzCCAbCgAwIBAgIEBAbK/jAKBggqhkjOPQQDAjBpMQswCQYDVQQGEwJHQjEP\nMA0GA1UECBMGTG9uZG9uMQ8wDQYDVQQHEwZMb25kb24xDzANBgNVBAoTBkdvb2ds\nZTEMMAoGA1UECxMDRW5nMRkwFwYDVQQDExBUZXN0R29zc2lwZXJSb290MB4XDTE4\nMDIyMzEzNDUyOVoXDTI4MDIyMTEzNDUyOVowaTELMAkGA1UEBhMCR0IxDzANBgNV\nBAgTBkxvbmRvbjEPMA0GA1UEBxMGTG9uZG9uMQ8wDQYDVQQKEwZHb29nbGUxDDAK\nBgNVBAsTA0VuZzEZMBcGA1UEAxMQVGVzdEdvc3NpcGVyUm9vdDBZMBMGByqGSM49\nAgEGCCqGSM49AwEHA0IABOqzZufPSU6hMJOIbljkjklDvQKBGYW9VenI6i7HSiyH\nccPUuh3F3fbbe2MrLtuRCjH7nqvcELPqBJsL3IVgQJijRjBEMA0GA1UdDgQGBAQR\nEhMUMA8GA1UdIwQIMAaABBESExQwEgYDVR0TAQH/BAgwBgEB/wIBAzAOBgNVHQ8B\nAf8EBAMCAgQwCgYIKoZIzj0EAwIDSQAwRgIhAICXxzQ+EulZALo8em3KujsOCpNY\n6lvLF5lqBMLS9fxwAiEAkh54N7Dq6P+3Sl/u15TA5DKhFPqgnvnB51wXGAsDhN0=\n-----END CERTIFICATE-----" +private_key: < + type_url: "type.googleapis.com/keyspb.PEMKeyFile" + value: "\n\035testdata/gossiper.privkey.pem\022\013hissing-sid" +> diff --git a/vendor/github.com/google/certificate-transparency-go/gossip/minimal/testdata/no-dest-name.cfg b/vendor/github.com/google/certificate-transparency-go/gossip/minimal/testdata/no-dest-name.cfg new file mode 100644 index 0000000..48d5338 --- /dev/null +++ b/vendor/github.com/google/certificate-transparency-go/gossip/minimal/testdata/no-dest-name.cfg @@ -0,0 +1,18 @@ +source_log: < + name: "theSourceOfAllSTHs" + url: "http://example.com/ct-source" + min_req_interval: < + seconds: 3600 + > +> +dest_log: < + url: "http://example.com/ct-dest" + min_req_interval: < + seconds: 60 + > +> +root_cert: "-----BEGIN CERTIFICATE-----\nMIICCzCCAbCgAwIBAgIEBAbK/jAKBggqhkjOPQQDAjBpMQswCQYDVQQGEwJHQjEP\nMA0GA1UECBMGTG9uZG9uMQ8wDQYDVQQHEwZMb25kb24xDzANBgNVBAoTBkdvb2ds\nZTEMMAoGA1UECxMDRW5nMRkwFwYDVQQDExBUZXN0R29zc2lwZXJSb290MB4XDTE4\nMDIyMzEzNDUyOVoXDTI4MDIyMTEzNDUyOVowaTELMAkGA1UEBhMCR0IxDzANBgNV\nBAgTBkxvbmRvbjEPMA0GA1UEBxMGTG9uZG9uMQ8wDQYDVQQKEwZHb29nbGUxDDAK\nBgNVBAsTA0VuZzEZMBcGA1UEAxMQVGVzdEdvc3NpcGVyUm9vdDBZMBMGByqGSM49\nAgEGCCqGSM49AwEHA0IABOqzZufPSU6hMJOIbljkjklDvQKBGYW9VenI6i7HSiyH\nccPUuh3F3fbbe2MrLtuRCjH7nqvcELPqBJsL3IVgQJijRjBEMA0GA1UdDgQGBAQR\nEhMUMA8GA1UdIwQIMAaABBESExQwEgYDVR0TAQH/BAgwBgEB/wIBAzAOBgNVHQ8B\nAf8EBAMCAgQwCgYIKoZIzj0EAwIDSQAwRgIhAICXxzQ+EulZALo8em3KujsOCpNY\n6lvLF5lqBMLS9fxwAiEAkh54N7Dq6P+3Sl/u15TA5DKhFPqgnvnB51wXGAsDhN0=\n-----END CERTIFICATE-----" +private_key: < + type_url: "type.googleapis.com/keyspb.PEMKeyFile" + value: "\n\035testdata/gossiper.privkey.pem\022\013hissing-sid" +> diff --git a/vendor/github.com/google/certificate-transparency-go/gossip/minimal/testdata/no-private-key.cfg b/vendor/github.com/google/certificate-transparency-go/gossip/minimal/testdata/no-private-key.cfg new file mode 100644 index 0000000..43ae3cd --- /dev/null +++ b/vendor/github.com/google/certificate-transparency-go/gossip/minimal/testdata/no-private-key.cfg @@ -0,0 +1,15 @@ +source_log: < + name: "theSourceOfAllSTHs" + url: "http://example.com/ct-source" + min_req_interval: < + seconds: 3600 + > +> +dest_log: < + name: "theDestinationOfAllSTHs" + url: "http://example.com/ct-dest" + min_req_interval: < + seconds: 60 + > +> +root_cert: "-----BEGIN CERTIFICATE-----\nMIICCzCCAbCgAwIBAgIEBAbK/jAKBggqhkjOPQQDAjBpMQswCQYDVQQGEwJHQjEP\nMA0GA1UECBMGTG9uZG9uMQ8wDQYDVQQHEwZMb25kb24xDzANBgNVBAoTBkdvb2ds\nZTEMMAoGA1UECxMDRW5nMRkwFwYDVQQDExBUZXN0R29zc2lwZXJSb290MB4XDTE4\nMDIyMzEzNDUyOVoXDTI4MDIyMTEzNDUyOVowaTELMAkGA1UEBhMCR0IxDzANBgNV\nBAgTBkxvbmRvbjEPMA0GA1UEBxMGTG9uZG9uMQ8wDQYDVQQKEwZHb29nbGUxDDAK\nBgNVBAsTA0VuZzEZMBcGA1UEAxMQVGVzdEdvc3NpcGVyUm9vdDBZMBMGByqGSM49\nAgEGCCqGSM49AwEHA0IABOqzZufPSU6hMJOIbljkjklDvQKBGYW9VenI6i7HSiyH\nccPUuh3F3fbbe2MrLtuRCjH7nqvcELPqBJsL3IVgQJijRjBEMA0GA1UdDgQGBAQR\nEhMUMA8GA1UdIwQIMAaABBESExQwEgYDVR0TAQH/BAgwBgEB/wIBAzAOBgNVHQ8B\nAf8EBAMCAgQwCgYIKoZIzj0EAwIDSQAwRgIhAICXxzQ+EulZALo8em3KujsOCpNY\n6lvLF5lqBMLS9fxwAiEAkh54N7Dq6P+3Sl/u15TA5DKhFPqgnvnB51wXGAsDhN0=\n-----END CERTIFICATE-----" diff --git a/vendor/github.com/google/certificate-transparency-go/gossip/minimal/testdata/no-root-cert.cfg b/vendor/github.com/google/certificate-transparency-go/gossip/minimal/testdata/no-root-cert.cfg new file mode 100644 index 0000000..2d9d74f --- /dev/null +++ b/vendor/github.com/google/certificate-transparency-go/gossip/minimal/testdata/no-root-cert.cfg @@ -0,0 +1,18 @@ +source_log: < + name: "theSourceOfAllSTHs" + url: "http://example.com/ct-source" + min_req_interval: < + seconds: 3600 + > +> +dest_log: < + name: "theDestinationOfAllSTHs" + url: "http://example.com/ct-dest" + min_req_interval: < + seconds: 60 + > +> +private_key: < + type_url: "type.googleapis.com/keyspb.PEMKeyFile" + value: "\n\035testdata/gossiper.privkey.pem\022\013hissing-sid" +> diff --git a/vendor/github.com/google/certificate-transparency-go/gossip/minimal/testdata/no-source-log.cfg b/vendor/github.com/google/certificate-transparency-go/gossip/minimal/testdata/no-source-log.cfg new file mode 100644 index 0000000..972e0f7 --- /dev/null +++ b/vendor/github.com/google/certificate-transparency-go/gossip/minimal/testdata/no-source-log.cfg @@ -0,0 +1,12 @@ +dest_log: < + name: "theDestinationOfAllSTHs" + url: "http://example.com/ct-dest" + min_req_interval: < + seconds: 60 + > +> +root_cert: "-----BEGIN CERTIFICATE-----\nMIICCzCCAbCgAwIBAgIEBAbK/jAKBggqhkjOPQQDAjBpMQswCQYDVQQGEwJHQjEP\nMA0GA1UECBMGTG9uZG9uMQ8wDQYDVQQHEwZMb25kb24xDzANBgNVBAoTBkdvb2ds\nZTEMMAoGA1UECxMDRW5nMRkwFwYDVQQDExBUZXN0R29zc2lwZXJSb290MB4XDTE4\nMDIyMzEzNDUyOVoXDTI4MDIyMTEzNDUyOVowaTELMAkGA1UEBhMCR0IxDzANBgNV\nBAgTBkxvbmRvbjEPMA0GA1UEBxMGTG9uZG9uMQ8wDQYDVQQKEwZHb29nbGUxDDAK\nBgNVBAsTA0VuZzEZMBcGA1UEAxMQVGVzdEdvc3NpcGVyUm9vdDBZMBMGByqGSM49\nAgEGCCqGSM49AwEHA0IABOqzZufPSU6hMJOIbljkjklDvQKBGYW9VenI6i7HSiyH\nccPUuh3F3fbbe2MrLtuRCjH7nqvcELPqBJsL3IVgQJijRjBEMA0GA1UdDgQGBAQR\nEhMUMA8GA1UdIwQIMAaABBESExQwEgYDVR0TAQH/BAgwBgEB/wIBAzAOBgNVHQ8B\nAf8EBAMCAgQwCgYIKoZIzj0EAwIDSQAwRgIhAICXxzQ+EulZALo8em3KujsOCpNY\n6lvLF5lqBMLS9fxwAiEAkh54N7Dq6P+3Sl/u15TA5DKhFPqgnvnB51wXGAsDhN0=\n-----END CERTIFICATE-----" +private_key: < + type_url: "type.googleapis.com/keyspb.PEMKeyFile" + value: "\n\035testdata/gossiper.privkey.pem\022\013hissing-sid" +> diff --git a/vendor/github.com/google/certificate-transparency-go/gossip/minimal/testdata/no-source-name.cfg b/vendor/github.com/google/certificate-transparency-go/gossip/minimal/testdata/no-source-name.cfg new file mode 100644 index 0000000..021caf3 --- /dev/null +++ b/vendor/github.com/google/certificate-transparency-go/gossip/minimal/testdata/no-source-name.cfg @@ -0,0 +1,18 @@ +source_log: < + url: "http://example.com/ct-source" + min_req_interval: < + seconds: 3600 + > +> +dest_log: < + name: "theDestinationOfAllSTHs" + url: "http://example.com/ct-dest" + min_req_interval: < + seconds: 60 + > +> +root_cert: "-----BEGIN CERTIFICATE-----\nMIICCzCCAbCgAwIBAgIEBAbK/jAKBggqhkjOPQQDAjBpMQswCQYDVQQGEwJHQjEP\nMA0GA1UECBMGTG9uZG9uMQ8wDQYDVQQHEwZMb25kb24xDzANBgNVBAoTBkdvb2ds\nZTEMMAoGA1UECxMDRW5nMRkwFwYDVQQDExBUZXN0R29zc2lwZXJSb290MB4XDTE4\nMDIyMzEzNDUyOVoXDTI4MDIyMTEzNDUyOVowaTELMAkGA1UEBhMCR0IxDzANBgNV\nBAgTBkxvbmRvbjEPMA0GA1UEBxMGTG9uZG9uMQ8wDQYDVQQKEwZHb29nbGUxDDAK\nBgNVBAsTA0VuZzEZMBcGA1UEAxMQVGVzdEdvc3NpcGVyUm9vdDBZMBMGByqGSM49\nAgEGCCqGSM49AwEHA0IABOqzZufPSU6hMJOIbljkjklDvQKBGYW9VenI6i7HSiyH\nccPUuh3F3fbbe2MrLtuRCjH7nqvcELPqBJsL3IVgQJijRjBEMA0GA1UdDgQGBAQR\nEhMUMA8GA1UdIwQIMAaABBESExQwEgYDVR0TAQH/BAgwBgEB/wIBAzAOBgNVHQ8B\nAf8EBAMCAgQwCgYIKoZIzj0EAwIDSQAwRgIhAICXxzQ+EulZALo8em3KujsOCpNY\n6lvLF5lqBMLS9fxwAiEAkh54N7Dq6P+3Sl/u15TA5DKhFPqgnvnB51wXGAsDhN0=\n-----END CERTIFICATE-----" +private_key: < + type_url: "type.googleapis.com/keyspb.PEMKeyFile" + value: "\n\035testdata/gossiper.privkey.pem\022\013hissing-sid" +> diff --git a/vendor/github.com/google/certificate-transparency-go/gossip/minimal/testdata/root-ca.cert b/vendor/github.com/google/certificate-transparency-go/gossip/minimal/testdata/root-ca.cert new file mode 100644 index 0000000..7a0c196 --- /dev/null +++ b/vendor/github.com/google/certificate-transparency-go/gossip/minimal/testdata/root-ca.cert @@ -0,0 +1,15 @@ +-----BEGIN CERTIFICATE----- +MIICQTCCAeegAwIBAgIEBAbK/jAKBggqhkjOPQQDAjBpMQswCQYDVQQGEwJHQjEP +MA0GA1UECBMGTG9uZG9uMQ8wDQYDVQQHEwZMb25kb24xDzANBgNVBAoTBkdvb2ds +ZTEMMAoGA1UECxMDRW5nMRkwFwYDVQQDExBUZXN0R29zc2lwZXJSb290MB4XDTE4 +MDIyNTA4MTA1M1oXDTI4MDIyMzA4MTA1M1owaTELMAkGA1UEBhMCR0IxDzANBgNV +BAgTBkxvbmRvbjEPMA0GA1UEBxMGTG9uZG9uMQ8wDQYDVQQKEwZHb29nbGUxDDAK +BgNVBAsTA0VuZzEZMBcGA1UEAxMQVGVzdEdvc3NpcGVyUm9vdDBZMBMGByqGSM49 +AgEGCCqGSM49AwEHA0IABOqzZufPSU6hMJOIbljkjklDvQKBGYW9VenI6i7HSiyH +ccPUuh3F3fbbe2MrLtuRCjH7nqvcELPqBJsL3IVgQJijfTB7MB0GA1UdDgQWBBRq +6hoXslGgHhrCVJMu4jrYlksyZjAfBgNVHSMEGDAWgBRq6hoXslGgHhrCVJMu4jrY +lksyZjASBgNVHRMBAf8ECDAGAQH/AgEDMA4GA1UdDwEB/wQEAwICBDAVBgNVHSUE +DjAMBgorBgEEAdZ5AgQGMAoGCCqGSM49BAMCA0gAMEUCIQCQCnWTIOlC6LqkcdH0 +fWZeNo5E3AaZBb9Tkv76ET2fJAIgOeGJvfiiOIlDV41/bIOg5eTHb/fxg80TCQBe +6ia6ZS8= +-----END CERTIFICATE----- diff --git a/vendor/github.com/google/certificate-transparency-go/gossip/minimal/testdata/root-ca.cfg b/vendor/github.com/google/certificate-transparency-go/gossip/minimal/testdata/root-ca.cfg new file mode 100644 index 0000000..894052b --- /dev/null +++ b/vendor/github.com/google/certificate-transparency-go/gossip/minimal/testdata/root-ca.cfg @@ -0,0 +1,28 @@ +# OpenSSL configuration file. + +[ req ] +# Options for the `req` tool (`man req`). +default_bits = 2048 +distinguished_name = req_distinguished_name +prompt = no +# SHA-1 is deprecated, so use SHA-2 instead. +default_md = sha256 +# Extension to add when the -x509 option is used. +x509_extensions = v3_ca +# Try to force use of PrintableString throughout +string_mask = pkix + +[ req_distinguished_name ] +C=GB +ST=London +L=London +O=Google +OU=Eng +CN=TestGossiperRoot + +[ v3_ca ] +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always,issuer +basicConstraints = critical, CA:true, pathlen:3 +keyUsage = critical, keyCertSign +extendedKeyUsage = 1.3.6.1.4.1.11129.2.4.6 diff --git a/vendor/github.com/google/certificate-transparency-go/gossip/minimal/testdata/test.cfg b/vendor/github.com/google/certificate-transparency-go/gossip/minimal/testdata/test.cfg new file mode 100644 index 0000000..158d732 --- /dev/null +++ b/vendor/github.com/google/certificate-transparency-go/gossip/minimal/testdata/test.cfg @@ -0,0 +1,22 @@ +source_log: < + name: "theSourceOfAllSTHs" + url: "http://example.com/ct-source" + min_req_interval: < + seconds: 3600 + > + public_key: { + der: "\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x07\xf8\x51\xaf\xaa\x8c\x56\x83\x90\x31\xb7\x80\xe3\xd6\x1a\xf7\x2f\x36\x06\x71\xec\xdd\x3b\xbe\x7e\x36\x6f\x0d\x1c\x1c\x60\x0b\x7f\xf5\x9f\xff\xe5\x24\x49\x34\x56\xf2\x4b\x10\x5f\xbf\x08\x1f\xf9\x0e\xcf\x35\xb5\x8a\x8a\x8b\x30\x0a\x54\xb7\xbf\x1d\x4d\xb9" + } +> +dest_log: < + name: "theDestinationOfAllSTHs" + url: "http://example.com/ct-dest" + min_req_interval: < + seconds: 60 + > +> +root_cert: "-----BEGIN CERTIFICATE-----\nMIICCzCCAbCgAwIBAgIEBAbK/jAKBggqhkjOPQQDAjBpMQswCQYDVQQGEwJHQjEP\nMA0GA1UECBMGTG9uZG9uMQ8wDQYDVQQHEwZMb25kb24xDzANBgNVBAoTBkdvb2ds\nZTEMMAoGA1UECxMDRW5nMRkwFwYDVQQDExBUZXN0R29zc2lwZXJSb290MB4XDTE4\nMDIyMzEzNDUyOVoXDTI4MDIyMTEzNDUyOVowaTELMAkGA1UEBhMCR0IxDzANBgNV\nBAgTBkxvbmRvbjEPMA0GA1UEBxMGTG9uZG9uMQ8wDQYDVQQKEwZHb29nbGUxDDAK\nBgNVBAsTA0VuZzEZMBcGA1UEAxMQVGVzdEdvc3NpcGVyUm9vdDBZMBMGByqGSM49\nAgEGCCqGSM49AwEHA0IABOqzZufPSU6hMJOIbljkjklDvQKBGYW9VenI6i7HSiyH\nccPUuh3F3fbbe2MrLtuRCjH7nqvcELPqBJsL3IVgQJijRjBEMA0GA1UdDgQGBAQR\nEhMUMA8GA1UdIwQIMAaABBESExQwEgYDVR0TAQH/BAgwBgEB/wIBAzAOBgNVHQ8B\nAf8EBAMCAgQwCgYIKoZIzj0EAwIDSQAwRgIhAICXxzQ+EulZALo8em3KujsOCpNY\n6lvLF5lqBMLS9fxwAiEAkh54N7Dq6P+3Sl/u15TA5DKhFPqgnvnB51wXGAsDhN0=\n-----END CERTIFICATE-----" +private_key: < + type_url: "type.googleapis.com/keyspb.PEMKeyFile" + value: "\n\035testdata/gossiper.privkey.pem\022\013hissing-sid" +> diff --git a/vendor/github.com/google/certificate-transparency-go/gossip/minimal/testdata/wrong-password-private-key.cfg b/vendor/github.com/google/certificate-transparency-go/gossip/minimal/testdata/wrong-password-private-key.cfg new file mode 100644 index 0000000..39c7bfb --- /dev/null +++ b/vendor/github.com/google/certificate-transparency-go/gossip/minimal/testdata/wrong-password-private-key.cfg @@ -0,0 +1,19 @@ +source_log: < + name: "theSourceOfAllSTHs" + url: "http://example.com/ct-source" + min_req_interval: < + seconds: 3600 + > +> +dest_log: < + name: "theDestinationOfAllSTHs" + url: "http://example.com/ct-dest" + min_req_interval: < + seconds: 60 + > +> +root_cert: "-----BEGIN CERTIFICATE-----\nMIICCzCCAbCgAwIBAgIEBAbK/jAKBggqhkjOPQQDAjBpMQswCQYDVQQGEwJHQjEP\nMA0GA1UECBMGTG9uZG9uMQ8wDQYDVQQHEwZMb25kb24xDzANBgNVBAoTBkdvb2ds\nZTEMMAoGA1UECxMDRW5nMRkwFwYDVQQDExBUZXN0R29zc2lwZXJSb290MB4XDTE4\nMDIyMzEzNDUyOVoXDTI4MDIyMTEzNDUyOVowaTELMAkGA1UEBhMCR0IxDzANBgNV\nBAgTBkxvbmRvbjEPMA0GA1UEBxMGTG9uZG9uMQ8wDQYDVQQKEwZHb29nbGUxDDAK\nBgNVBAsTA0VuZzEZMBcGA1UEAxMQVGVzdEdvc3NpcGVyUm9vdDBZMBMGByqGSM49\nAgEGCCqGSM49AwEHA0IABOqzZufPSU6hMJOIbljkjklDvQKBGYW9VenI6i7HSiyH\nccPUuh3F3fbbe2MrLtuRCjH7nqvcELPqBJsL3IVgQJijRjBEMA0GA1UdDgQGBAQR\nEhMUMA8GA1UdIwQIMAaABBESExQwEgYDVR0TAQH/BAgwBgEB/wIBAzAOBgNVHQ8B\nAf8EBAMCAgQwCgYIKoZIzj0EAwIDSQAwRgIhAICXxzQ+EulZALo8em3KujsOCpNY\n6lvLF5lqBMLS9fxwAiEAkh54N7Dq6P+3Sl/u15TA5DKhFPqgnvnB51wXGAsDhN0=\n-----END CERTIFICATE-----" +private_key: < + type_url: "type.googleapis.com/keyspb.PEMKeyFile" + value: "\n\035testdata/gossiper.privkey.pem\022\013passing-sid" +> diff --git a/vendor/github.com/google/certificate-transparency-go/gossip/minimal/x509ext/x509ext.go b/vendor/github.com/google/certificate-transparency-go/gossip/minimal/x509ext/x509ext.go new file mode 100644 index 0000000..8f673b9 --- /dev/null +++ b/vendor/github.com/google/certificate-transparency-go/gossip/minimal/x509ext/x509ext.go @@ -0,0 +1,91 @@ +// Copyright 2018 Google Inc. All Rights Reserved. +// +// 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 x509ext holds extensions types and values for minimal gossip. +package x509ext + +import ( + "errors" + "fmt" + + "github.com/google/certificate-transparency-go" + "github.com/google/certificate-transparency-go/asn1" + "github.com/google/certificate-transparency-go/tls" + "github.com/google/certificate-transparency-go/x509" +) + +// OIDExtensionCTSTH is the OID value for an X.509 extension that holds +// a log STH value. +// TODO(drysdale): get an official OID value +var OIDExtensionCTSTH = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 11129, 2, 4, 5} + +// OIDExtKeyUsageCTMinimalGossip is the OID value for an extended key usage +// (EKU) that indicates a leaf certificate is used for the validation of STH +// values from public CT logs. +// TODO(drysdale): get an official OID value +var OIDExtKeyUsageCTMinimalGossip = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 11129, 2, 4, 6} + +// LogSTHInfo is the structure that gets TLS-encoded into the X.509 extension +// identified by OIDExtensionCTSTH. +type LogSTHInfo struct { + LogURL []byte `tls:"maxlen:255"` + Version tls.Enum `tls:"maxval:255"` + TreeSize uint64 + Timestamp uint64 + SHA256RootHash ct.SHA256Hash + TreeHeadSignature ct.DigitallySigned +} + +// LogSTHInfoFromCert retrieves the STH information embedded in a certificate. +func LogSTHInfoFromCert(cert *x509.Certificate) (*LogSTHInfo, error) { + for _, ext := range cert.Extensions { + if ext.Id.Equal(OIDExtensionCTSTH) { + var sthInfo LogSTHInfo + rest, err := tls.Unmarshal(ext.Value, &sthInfo) + if err != nil { + return nil, fmt.Errorf("failed to unmarshal STH: %v", err) + } else if len(rest) > 0 { + return nil, fmt.Errorf("trailing data (%d bytes) after STH", len(rest)) + } + return &sthInfo, nil + } + } + return nil, errors.New("no STH extension found") +} + +// HasSTHInfo indicates whether a certificate has embedded STH information. +func HasSTHInfo(cert *x509.Certificate) bool { + for _, ext := range cert.Extensions { + if ext.Id.Equal(OIDExtensionCTSTH) { + return true + } + } + return false +} + +// STHFromCert retrieves the STH embedded in a certificate; note the returned STH +// does not have the LogID field filled in. +func STHFromCert(cert *x509.Certificate) (*ct.SignedTreeHead, error) { + sthInfo, err := LogSTHInfoFromCert(cert) + if err != nil { + return nil, err + } + return &ct.SignedTreeHead{ + Version: ct.Version(sthInfo.Version), + TreeSize: sthInfo.TreeSize, + Timestamp: sthInfo.Timestamp, + SHA256RootHash: sthInfo.SHA256RootHash, + TreeHeadSignature: sthInfo.TreeHeadSignature, + }, nil +} diff --git a/vendor/github.com/google/certificate-transparency-go/gossip/minimal/x509ext/x509ext_test.go b/vendor/github.com/google/certificate-transparency-go/gossip/minimal/x509ext/x509ext_test.go new file mode 100644 index 0000000..5c482f1 --- /dev/null +++ b/vendor/github.com/google/certificate-transparency-go/gossip/minimal/x509ext/x509ext_test.go @@ -0,0 +1,150 @@ +// Copyright 2018 Google Inc. All Rights Reserved. +// +// 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 x509ext_test + +import ( + "encoding/hex" + "encoding/pem" + "fmt" + "strings" + "testing" + "time" + + "github.com/google/certificate-transparency-go" + "github.com/google/certificate-transparency-go/gossip/minimal/x509ext" + "github.com/google/certificate-transparency-go/tls" + "github.com/google/certificate-transparency-go/x509" + "github.com/google/certificate-transparency-go/x509/pkix" +) + +var ( + // pilotPubKeyPEM is the public key for Google's Pilot log. + pilotPubKeyPEM = []byte(`-----BEGIN PUBLIC KEY----- +MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEfahLEimAoz2t01p3uMziiLOl/fHT +DM0YDOhBRuiBARsV4UvxG2LdNgoIGLrtCzWE0J5APC2em4JlvR8EEEFMoA== +-----END PUBLIC KEY-----`) +) + +func TestSTHFromCert(t *testing.T) { + rawPubKey, _ := pem.Decode(pilotPubKeyPEM) + pubKey, _, _, err := ct.PublicKeyFromPEM(pilotPubKeyPEM) + if err != nil { + t.Fatalf("failed to decode test pubkey data: %v", err) + } + validSTH := x509ext.LogSTHInfo{ + LogURL: []byte("http://ct.example.com/log"), + Version: 0, + TreeSize: 7834120, + Timestamp: 1519395540364, + SHA256RootHash: [...]byte{ + 0xfe, 0xc0, 0xed, 0xe1, 0xbe, 0xf1, 0xa2, 0x25, 0xc3, 0x72, 0xa6, 0x44, 0x1b, 0xa2, 0xd5, 0xdd, 0x3b, 0xbb, 0x9b, 0x7b, 0xa9, 0x79, 0xd1, 0xa7, 0x03, 0xe7, 0xfe, 0x81, 0x49, 0x75, 0x85, 0xfb, + }, + TreeHeadSignature: ct.DigitallySigned{ + Algorithm: tls.SignatureAndHashAlgorithm{Hash: tls.SHA256, Signature: tls.ECDSA}, + Signature: dehex("220164e031604aa2a0b68887ba668cefb3e0046e455d6323c3df38b8d50108895d70220146199ee1d759a029d8b37ce8701d2ca47a387bad8ac8ef1cb84b77bc0820ed"), + }, + } + sthData, err := tls.Marshal(validSTH) + if err != nil { + t.Fatalf("failed to marshal STH: %v", err) + } + + var tests = []struct { + name string + cert x509.Certificate + wantErr string + }{ + { + name: "ValidSTH", + cert: x509.Certificate{ + NotBefore: time.Now(), + NotAfter: time.Now().Add(24 * time.Hour), + PublicKey: pubKey, + RawSubjectPublicKeyInfo: rawPubKey.Bytes, + Subject: pkix.Name{ + CommonName: "Test STH holder", + }, + Extensions: []pkix.Extension{ + {Id: x509ext.OIDExtensionCTSTH, Critical: false, Value: sthData}, + }, + }, + }, + { + name: "MissingSTH", + cert: x509.Certificate{ + NotBefore: time.Now(), + NotAfter: time.Now().Add(24 * time.Hour), + Subject: pkix.Name{ + CommonName: "Test STH holder", + }, + }, + wantErr: "no STH extension found", + }, + { + name: "TrailingData", + cert: x509.Certificate{ + NotBefore: time.Now(), + NotAfter: time.Now().Add(24 * time.Hour), + Subject: pkix.Name{ + CommonName: "Test STH holder", + }, + Extensions: []pkix.Extension{ + {Id: x509ext.OIDExtensionCTSTH, Critical: false, Value: append(sthData, 0xff)}, + }, + }, + wantErr: "trailing data", + }, + { + name: "InvalidSTH", + cert: x509.Certificate{ + NotBefore: time.Now(), + NotAfter: time.Now().Add(24 * time.Hour), + Subject: pkix.Name{ + CommonName: "Test STH holder", + }, + Extensions: []pkix.Extension{ + {Id: x509ext.OIDExtensionCTSTH, Critical: false, Value: []byte{0xff}}, + }, + }, + wantErr: "failed to unmarshal", + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + got, err := x509ext.STHFromCert(&test.cert) + if err != nil { + if test.wantErr == "" { + t.Errorf("STHFromCert(%+v)=nil,%v; want _,nil", test.cert, err) + } else if !strings.Contains(err.Error(), test.wantErr) { + t.Errorf("STHFromCert(%+v)=nil,%v; want nil,err containing %q", test.cert, err, test.wantErr) + } + return + } + if test.wantErr != "" { + t.Errorf("STHFromCert(%+v)=_,nil; want nil,err containing %q", test.cert, test.wantErr) + } + t.Logf("retrieved STH %+v", got) + }) + } +} + +func dehex(h string) []byte { + d, err := hex.DecodeString(h) + if err != nil { + panic(fmt.Sprintf("hard-coded data %q failed to decode! %v", h, err)) + } + return d +} diff --git a/vendor/github.com/google/certificate-transparency-go/signatures.go b/vendor/github.com/google/certificate-transparency-go/signatures.go index 7171092..b1000ba 100644 --- a/vendor/github.com/google/certificate-transparency-go/signatures.go +++ b/vendor/github.com/google/certificate-transparency-go/signatures.go @@ -22,7 +22,6 @@ import ( "crypto/sha256" "encoding/base64" "encoding/pem" - "flag" "fmt" "log" @@ -30,8 +29,10 @@ import ( "github.com/google/certificate-transparency-go/x509" ) -var allowVerificationWithNonCompliantKeys = flag.Bool("allow_verification_with_non_compliant_keys", false, - "Allow a SignatureVerifier to use keys which are technically non-compliant with RFC6962.") +// AllowVerificationWithNonCompliantKeys may be set to true in order to allow +// SignatureVerifier to use keys which are technically non-compliant with +// RFC6962. +var AllowVerificationWithNonCompliantKeys = false // PublicKeyFromPEM parses a PEM formatted block and returns the public key contained within and any remaining unread bytes, or an error. func PublicKeyFromPEM(b []byte) (crypto.PublicKey, SHA256Hash, []byte, error) { @@ -63,7 +64,7 @@ func NewSignatureVerifier(pk crypto.PublicKey) (*SignatureVerifier, error) { case *rsa.PublicKey: if pkType.N.BitLen() < 2048 { e := fmt.Errorf("public key is RSA with < 2048 bits (size:%d)", pkType.N.BitLen()) - if !(*allowVerificationWithNonCompliantKeys) { + if !AllowVerificationWithNonCompliantKeys { return nil, e } log.Printf("WARNING: %v", e) @@ -72,7 +73,7 @@ func NewSignatureVerifier(pk crypto.PublicKey) (*SignatureVerifier, error) { params := *(pkType.Params()) if params != *elliptic.P256().Params() { e := fmt.Errorf("public is ECDSA, but not on the P256 curve") - if !(*allowVerificationWithNonCompliantKeys) { + if !AllowVerificationWithNonCompliantKeys { return nil, e } log.Printf("WARNING: %v", e) diff --git a/vendor/github.com/google/certificate-transparency-go/signatures_test.go b/vendor/github.com/google/certificate-transparency-go/signatures_test.go index 7083460..8a05a60 100644 --- a/vendor/github.com/google/certificate-transparency-go/signatures_test.go +++ b/vendor/github.com/google/certificate-transparency-go/signatures_test.go @@ -471,7 +471,7 @@ func TestNewSignatureVerifierFailsWithBadKeyParametersForRSA(t *testing.T) { } func TestWillAllowNonCompliantECKeyWithOverride(t *testing.T) { - *allowVerificationWithNonCompliantKeys = true + AllowVerificationWithNonCompliantKeys = true k, err := ecdsa.GenerateKey(elliptic.P224(), rand.Reader) if err != nil { t.Fatalf("Failed to generate EC key on P224: %v", err) @@ -482,7 +482,7 @@ func TestWillAllowNonCompliantECKeyWithOverride(t *testing.T) { } func TestWillAllowNonCompliantRSAKeyWithOverride(t *testing.T) { - *allowVerificationWithNonCompliantKeys = true + AllowVerificationWithNonCompliantKeys = true k, err := rsa.GenerateKey(rand.Reader, 1024) if err != nil { t.Fatalf("Failed to generate 1024 bit RSA key: %v", err) diff --git a/vendor/github.com/google/certificate-transparency-go/testdata/gossip-root.cert b/vendor/github.com/google/certificate-transparency-go/testdata/gossip-root.cert new file mode 100644 index 0000000..7a0c196 --- /dev/null +++ b/vendor/github.com/google/certificate-transparency-go/testdata/gossip-root.cert @@ -0,0 +1,15 @@ +-----BEGIN CERTIFICATE----- +MIICQTCCAeegAwIBAgIEBAbK/jAKBggqhkjOPQQDAjBpMQswCQYDVQQGEwJHQjEP +MA0GA1UECBMGTG9uZG9uMQ8wDQYDVQQHEwZMb25kb24xDzANBgNVBAoTBkdvb2ds +ZTEMMAoGA1UECxMDRW5nMRkwFwYDVQQDExBUZXN0R29zc2lwZXJSb290MB4XDTE4 +MDIyNTA4MTA1M1oXDTI4MDIyMzA4MTA1M1owaTELMAkGA1UEBhMCR0IxDzANBgNV +BAgTBkxvbmRvbjEPMA0GA1UEBxMGTG9uZG9uMQ8wDQYDVQQKEwZHb29nbGUxDDAK +BgNVBAsTA0VuZzEZMBcGA1UEAxMQVGVzdEdvc3NpcGVyUm9vdDBZMBMGByqGSM49 +AgEGCCqGSM49AwEHA0IABOqzZufPSU6hMJOIbljkjklDvQKBGYW9VenI6i7HSiyH +ccPUuh3F3fbbe2MrLtuRCjH7nqvcELPqBJsL3IVgQJijfTB7MB0GA1UdDgQWBBRq +6hoXslGgHhrCVJMu4jrYlksyZjAfBgNVHSMEGDAWgBRq6hoXslGgHhrCVJMu4jrY +lksyZjASBgNVHRMBAf8ECDAGAQH/AgEDMA4GA1UdDwEB/wQEAwICBDAVBgNVHSUE +DjAMBgorBgEEAdZ5AgQGMAoGCCqGSM49BAMCA0gAMEUCIQCQCnWTIOlC6LqkcdH0 +fWZeNo5E3AaZBb9Tkv76ET2fJAIgOeGJvfiiOIlDV41/bIOg5eTHb/fxg80TCQBe +6ia6ZS8= +-----END CERTIFICATE----- diff --git a/vendor/github.com/google/certificate-transparency-go/testdata/gossiper.privkey.pem b/vendor/github.com/google/certificate-transparency-go/testdata/gossiper.privkey.pem new file mode 100644 index 0000000..09336f4 --- /dev/null +++ b/vendor/github.com/google/certificate-transparency-go/testdata/gossiper.privkey.pem @@ -0,0 +1,8 @@ +-----BEGIN EC PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-CBC,559BE893ECD7A88C + +UOwSw+WlSv5LLiBZSCnR12FX13Hk1a3vavdpUde4W4qawQgJSMqLa3it8Lfadtnm +GfGVqN+gF5KFiNWxgMs2qRcbdQ03ZlMmoH8Z8jPQHXvKseJvME8tZQWPvJ15rbXh +G9Lcx7NYlm0miHPy3ras8ci58HSDqz9Z7yOdgHzPpiU= +-----END EC PRIVATE KEY----- diff --git a/vendor/github.com/google/certificate-transparency-go/types.go b/vendor/github.com/google/certificate-transparency-go/types.go index 90c4215..bcdd7e9 100644 --- a/vendor/github.com/google/certificate-transparency-go/types.go +++ b/vendor/github.com/google/certificate-transparency-go/types.go @@ -374,7 +374,27 @@ func (m *MerkleTreeLeaf) Precertificate() (*x509.Certificate, error) { return x509.ParseTBSCertificate(m.TimestampedEntry.PrecertEntry.TBSCertificate) } +// APIEndpoint is a string that represents one of the Certificate Transparency +// Log API endpoints. +type APIEndpoint string + +// Certificate Transparency Log API endpoints; see section 4. +// WARNING: Should match the URI paths without the "/ct/v1/" prefix. If +// changing these constants, may need to change those too. +const ( + AddChainStr APIEndpoint = "add-chain" + AddPreChainStr APIEndpoint = "add-pre-chain" + GetSTHStr APIEndpoint = "get-sth" + GetEntriesStr APIEndpoint = "get-entries" + GetProofByHashStr APIEndpoint = "get-proof-by-hash" + GetSTHConsistencyStr APIEndpoint = "get-sth-consistency" + GetRootsStr APIEndpoint = "get-roots" + GetEntryAndProofStr APIEndpoint = "get-entry-and-proof" +) + // URI paths for Log requests; see section 4. +// WARNING: Should match the API endpoints, with the "/ct/v1/" prefix. If +// changing these constants, may need to change those too. const ( AddChainPath = "/ct/v1/add-chain" AddPreChainPath = "/ct/v1/add-pre-chain" diff --git a/vendor/github.com/google/certificate-transparency-go/x509/ptr_sysptr_windows.go b/vendor/github.com/google/certificate-transparency-go/x509/ptr_sysptr_windows.go new file mode 100644 index 0000000..3543e30 --- /dev/null +++ b/vendor/github.com/google/certificate-transparency-go/x509/ptr_sysptr_windows.go @@ -0,0 +1,20 @@ +// 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. + +// +build go1.11 + +package x509 + +import ( + "syscall" + "unsafe" +) + +// For Go versions >= 1.11, the ExtraPolicyPara field in +// syscall.CertChainPolicyPara is of type syscall.Pointer. See: +// https://github.com/golang/go/commit/4869ec00e87ef + +func convertToPolicyParaType(p unsafe.Pointer) syscall.Pointer { + return (syscall.Pointer)(p) +} diff --git a/vendor/github.com/google/certificate-transparency-go/x509/ptr_uint_windows.go b/vendor/github.com/google/certificate-transparency-go/x509/ptr_uint_windows.go new file mode 100644 index 0000000..3908833 --- /dev/null +++ b/vendor/github.com/google/certificate-transparency-go/x509/ptr_uint_windows.go @@ -0,0 +1,17 @@ +// 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. + +// +build !go1.11 + +package x509 + +import "unsafe" + +// For Go versions before 1.11, the ExtraPolicyPara field in +// syscall.CertChainPolicyPara was of type uintptr. See: +// https://github.com/golang/go/commit/4869ec00e87ef + +func convertToPolicyParaType(p unsafe.Pointer) uintptr { + return uintptr(p) +} diff --git a/vendor/github.com/google/certificate-transparency-go/x509/root_windows.go b/vendor/github.com/google/certificate-transparency-go/x509/root_windows.go index 92cc716..304ad3a 100644 --- a/vendor/github.com/google/certificate-transparency-go/x509/root_windows.go +++ b/vendor/github.com/google/certificate-transparency-go/x509/root_windows.go @@ -109,7 +109,7 @@ func checkChainSSLServerPolicy(c *Certificate, chainCtx *syscall.CertChainContex sslPara.Size = uint32(unsafe.Sizeof(*sslPara)) para := &syscall.CertChainPolicyPara{ - ExtraPolicyPara: uintptr(unsafe.Pointer(sslPara)), + ExtraPolicyPara: convertToPolicyParaType(unsafe.Pointer(sslPara)), } para.Size = uint32(unsafe.Sizeof(*para)) diff --git a/vendor/github.com/google/certificate-transparency-go/x509/x509.go b/vendor/github.com/google/certificate-transparency-go/x509/x509.go index 7130f65..23f2a6a 100644 --- a/vendor/github.com/google/certificate-transparency-go/x509/x509.go +++ b/vendor/github.com/google/certificate-transparency-go/x509/x509.go @@ -1446,7 +1446,7 @@ func isValidIPMask(mask []byte) bool { return true } -func parseNameConstraintsExtension(out *Certificate, e pkix.Extension) (unhandled bool, err error) { +func parseNameConstraintsExtension(out *Certificate, e pkix.Extension, nfe *NonFatalErrors) (unhandled bool, err error) { // RFC 5280, 4.2.1.10 // NameConstraints ::= SEQUENCE { @@ -1513,7 +1513,7 @@ func parseNameConstraintsExtension(out *Certificate, e pkix.Extension) (unhandle trimmedDomain = trimmedDomain[1:] } if _, ok := domainToReverseLabels(trimmedDomain); !ok { - return nil, nil, nil, nil, fmt.Errorf("x509: failed to parse dnsName constraint %q", domain) + nfe.AddError(fmt.Errorf("x509: failed to parse dnsName constraint %q", domain)) } dnsNames = append(dnsNames, domain) @@ -1550,7 +1550,7 @@ func parseNameConstraintsExtension(out *Certificate, e pkix.Extension) (unhandle // it specifies an exact mailbox name. if strings.Contains(constraint, "@") { if _, ok := parseRFC2821Mailbox(constraint); !ok { - return nil, nil, nil, nil, fmt.Errorf("x509: failed to parse rfc822Name constraint %q", constraint) + nfe.AddError(fmt.Errorf("x509: failed to parse rfc822Name constraint %q", constraint)) } } else { // Otherwise it's a domain name. @@ -1559,7 +1559,7 @@ func parseNameConstraintsExtension(out *Certificate, e pkix.Extension) (unhandle domain = domain[1:] } if _, ok := domainToReverseLabels(domain); !ok { - return nil, nil, nil, nil, fmt.Errorf("x509: failed to parse rfc822Name constraint %q", constraint) + nfe.AddError(fmt.Errorf("x509: failed to parse rfc822Name constraint %q", constraint)) } } emails = append(emails, constraint) @@ -1583,7 +1583,7 @@ func parseNameConstraintsExtension(out *Certificate, e pkix.Extension) (unhandle trimmedDomain = trimmedDomain[1:] } if _, ok := domainToReverseLabels(trimmedDomain); !ok { - return nil, nil, nil, nil, fmt.Errorf("x509: failed to parse URI constraint %q", domain) + nfe.AddError(fmt.Errorf("x509: failed to parse URI constraint %q", domain)) } uriDomains = append(uriDomains, domain) @@ -1698,7 +1698,7 @@ func parseCertificate(in *certificate) (*Certificate, error) { } case OIDExtensionNameConstraints[3]: - unhandled, err = parseNameConstraintsExtension(out, e) + unhandled, err = parseNameConstraintsExtension(out, e, &nfe) if err != nil { return nil, err } @@ -1834,6 +1834,8 @@ func ParseTBSCertificate(asn1Data []byte) (*Certificate, error) { } // ParseCertificate parses a single certificate from the given ASN.1 DER data. +// This function can return both a Certificate and an error (in which case the +// error will be of type NonFatalErrors). func ParseCertificate(asn1Data []byte) (*Certificate, error) { var cert certificate rest, err := asn1.Unmarshal(asn1Data, &cert) @@ -1849,6 +1851,8 @@ func ParseCertificate(asn1Data []byte) (*Certificate, error) { // ParseCertificates parses one or more certificates from the given ASN.1 DER // data. The certificates must be concatenated with no intermediate padding. +// This function can return both a slice of Certificate and an error (in which +// case the error will be of type NonFatalErrors). func ParseCertificates(asn1Data []byte) ([]*Certificate, error) { var v []*certificate @@ -1862,15 +1866,23 @@ func ParseCertificates(asn1Data []byte) ([]*Certificate, error) { v = append(v, cert) } + var nfe NonFatalErrors ret := make([]*Certificate, len(v)) for i, ci := range v { cert, err := parseCertificate(ci) if err != nil { - return nil, err + if errs, ok := err.(NonFatalErrors); !ok { + return nil, err + } else { + nfe.Errors = append(nfe.Errors, errs.Errors...) + } } ret[i] = cert } + if nfe.HasError() { + return ret, nfe + } return ret, nil } diff --git a/vendor/github.com/google/certificate-transparency-go/x509util/x509util.go b/vendor/github.com/google/certificate-transparency-go/x509util/x509util.go index 902378d..270d1ce 100644 --- a/vendor/github.com/google/certificate-transparency-go/x509util/x509util.go +++ b/vendor/github.com/google/certificate-transparency-go/x509util/x509util.go @@ -31,6 +31,7 @@ import ( ct "github.com/google/certificate-transparency-go" "github.com/google/certificate-transparency-go/asn1" + "github.com/google/certificate-transparency-go/gossip/minimal/x509ext" "github.com/google/certificate-transparency-go/tls" "github.com/google/certificate-transparency-go/x509" "github.com/google/certificate-transparency-go/x509/pkix" @@ -426,6 +427,7 @@ func CertificateToString(cert *x509.Certificate) string { showAuthInfoAccess(&result, cert) showCTPoison(&result, cert) showCTSCT(&result, cert) + showCTLogSTHInfo(&result, cert) showUnhandledExtensions(&result, cert) showSignature(&result, cert) @@ -621,6 +623,30 @@ func showCTSCT(result *bytes.Buffer, cert *x509.Certificate) { } } +func showCTLogSTHInfo(result *bytes.Buffer, cert *x509.Certificate) { + count, critical := OIDInExtensions(x509ext.OIDExtensionCTSTH, cert.Extensions) + if count > 0 { + result.WriteString(fmt.Sprintf(" Certificate Transparency STH:")) + showCritical(result, critical) + sthInfo, err := x509ext.LogSTHInfoFromCert(cert) + if err != nil { + result.WriteString(fmt.Sprintf(" Failed to decode STH:\n")) + return + } + result.WriteString(fmt.Sprintf(" LogURL: %s\n", string(sthInfo.LogURL))) + result.WriteString(fmt.Sprintf(" Version: %d\n", sthInfo.Version)) + result.WriteString(fmt.Sprintf(" TreeSize: %d\n", sthInfo.TreeSize)) + result.WriteString(fmt.Sprintf(" Timestamp: %d\n", sthInfo.Timestamp)) + result.WriteString(fmt.Sprintf(" RootHash:\n")) + appendHexData(result, sthInfo.SHA256RootHash[:], 16, " ") + result.WriteString("\n") + result.WriteString(fmt.Sprintf(" TreeHeadSignature: %s\n", sthInfo.TreeHeadSignature.Algorithm)) + result.WriteString(fmt.Sprintf(" TreeHeadSignature:\n")) + appendHexData(result, sthInfo.TreeHeadSignature.Signature, 16, " ") + result.WriteString("\n") + } +} + func showUnhandledExtensions(result *bytes.Buffer, cert *x509.Certificate) { for _, ext := range cert.Extensions { // Skip extensions that are already cracked out @@ -653,7 +679,8 @@ func oidAlreadyPrinted(oid asn1.ObjectIdentifier) bool { oid.Equal(x509.OIDExtensionCRLDistributionPoints) || oid.Equal(x509.OIDExtensionAuthorityInfoAccess) || oid.Equal(x509.OIDExtensionCTPoison) || - oid.Equal(x509.OIDExtensionCTSCT) { + oid.Equal(x509.OIDExtensionCTSCT) || + oid.Equal(x509ext.OIDExtensionCTSTH) { return true } return false @@ -717,8 +744,10 @@ func ExtractSCT(sctData *x509.SerializedSCT) (*ct.SignedCertificateTimestamp, er return nil, errors.New("SCT is nil") } var sct ct.SignedCertificateTimestamp - if _, err := tls.Unmarshal(sctData.Val, &sct); err != nil { + if rest, err := tls.Unmarshal(sctData.Val, &sct); err != nil { return nil, fmt.Errorf("error parsing SCT: %s", err) + } else if len(rest) > 0 { + return nil, fmt.Errorf("extra data (%d bytes) after serialized SCT", len(rest)) } return &sct, nil } diff --git a/vendor/github.com/kr/pretty/.gitignore b/vendor/github.com/kr/pretty/.gitignore new file mode 100644 index 0000000..1f0a99f --- /dev/null +++ b/vendor/github.com/kr/pretty/.gitignore @@ -0,0 +1,4 @@ +[568].out +_go* +_test* +_obj diff --git a/vendor/github.com/kr/pretty/License b/vendor/github.com/kr/pretty/License new file mode 100644 index 0000000..05c783c --- /dev/null +++ b/vendor/github.com/kr/pretty/License @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright 2012 Keith Rarick + +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. diff --git a/vendor/github.com/kr/pretty/Readme b/vendor/github.com/kr/pretty/Readme new file mode 100644 index 0000000..c589fc6 --- /dev/null +++ b/vendor/github.com/kr/pretty/Readme @@ -0,0 +1,9 @@ +package pretty + + import "github.com/kr/pretty" + + Package pretty provides pretty-printing for Go values. + +Documentation + + http://godoc.org/github.com/kr/pretty diff --git a/vendor/github.com/kr/pretty/diff.go b/vendor/github.com/kr/pretty/diff.go new file mode 100644 index 0000000..6aa7f74 --- /dev/null +++ b/vendor/github.com/kr/pretty/diff.go @@ -0,0 +1,265 @@ +package pretty + +import ( + "fmt" + "io" + "reflect" +) + +type sbuf []string + +func (p *sbuf) Printf(format string, a ...interface{}) { + s := fmt.Sprintf(format, a...) + *p = append(*p, s) +} + +// Diff returns a slice where each element describes +// a difference between a and b. +func Diff(a, b interface{}) (desc []string) { + Pdiff((*sbuf)(&desc), a, b) + return desc +} + +// wprintfer calls Fprintf on w for each Printf call +// with a trailing newline. +type wprintfer struct{ w io.Writer } + +func (p *wprintfer) Printf(format string, a ...interface{}) { + fmt.Fprintf(p.w, format+"\n", a...) +} + +// Fdiff writes to w a description of the differences between a and b. +func Fdiff(w io.Writer, a, b interface{}) { + Pdiff(&wprintfer{w}, a, b) +} + +type Printfer interface { + Printf(format string, a ...interface{}) +} + +// Pdiff prints to p a description of the differences between a and b. +// It calls Printf once for each difference, with no trailing newline. +// The standard library log.Logger is a Printfer. +func Pdiff(p Printfer, a, b interface{}) { + diffPrinter{w: p}.diff(reflect.ValueOf(a), reflect.ValueOf(b)) +} + +type Logfer interface { + Logf(format string, a ...interface{}) +} + +// logprintfer calls Fprintf on w for each Printf call +// with a trailing newline. +type logprintfer struct{ l Logfer } + +func (p *logprintfer) Printf(format string, a ...interface{}) { + p.l.Logf(format, a...) +} + +// Ldiff prints to l a description of the differences between a and b. +// It calls Logf once for each difference, with no trailing newline. +// The standard library testing.T and testing.B are Logfers. +func Ldiff(l Logfer, a, b interface{}) { + Pdiff(&logprintfer{l}, a, b) +} + +type diffPrinter struct { + w Printfer + l string // label +} + +func (w diffPrinter) printf(f string, a ...interface{}) { + var l string + if w.l != "" { + l = w.l + ": " + } + w.w.Printf(l+f, a...) +} + +func (w diffPrinter) diff(av, bv reflect.Value) { + if !av.IsValid() && bv.IsValid() { + w.printf("nil != %# v", formatter{v: bv, quote: true}) + return + } + if av.IsValid() && !bv.IsValid() { + w.printf("%# v != nil", formatter{v: av, quote: true}) + return + } + if !av.IsValid() && !bv.IsValid() { + return + } + + at := av.Type() + bt := bv.Type() + if at != bt { + w.printf("%v != %v", at, bt) + return + } + + switch kind := at.Kind(); kind { + case reflect.Bool: + if a, b := av.Bool(), bv.Bool(); a != b { + w.printf("%v != %v", a, b) + } + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + if a, b := av.Int(), bv.Int(); a != b { + w.printf("%d != %d", a, b) + } + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + if a, b := av.Uint(), bv.Uint(); a != b { + w.printf("%d != %d", a, b) + } + case reflect.Float32, reflect.Float64: + if a, b := av.Float(), bv.Float(); a != b { + w.printf("%v != %v", a, b) + } + case reflect.Complex64, reflect.Complex128: + if a, b := av.Complex(), bv.Complex(); a != b { + w.printf("%v != %v", a, b) + } + case reflect.Array: + n := av.Len() + for i := 0; i < n; i++ { + w.relabel(fmt.Sprintf("[%d]", i)).diff(av.Index(i), bv.Index(i)) + } + case reflect.Chan, reflect.Func, reflect.UnsafePointer: + if a, b := av.Pointer(), bv.Pointer(); a != b { + w.printf("%#x != %#x", a, b) + } + case reflect.Interface: + w.diff(av.Elem(), bv.Elem()) + case reflect.Map: + ak, both, bk := keyDiff(av.MapKeys(), bv.MapKeys()) + for _, k := range ak { + w := w.relabel(fmt.Sprintf("[%#v]", k)) + w.printf("%q != (missing)", av.MapIndex(k)) + } + for _, k := range both { + w := w.relabel(fmt.Sprintf("[%#v]", k)) + w.diff(av.MapIndex(k), bv.MapIndex(k)) + } + for _, k := range bk { + w := w.relabel(fmt.Sprintf("[%#v]", k)) + w.printf("(missing) != %q", bv.MapIndex(k)) + } + case reflect.Ptr: + switch { + case av.IsNil() && !bv.IsNil(): + w.printf("nil != %# v", formatter{v: bv, quote: true}) + case !av.IsNil() && bv.IsNil(): + w.printf("%# v != nil", formatter{v: av, quote: true}) + case !av.IsNil() && !bv.IsNil(): + w.diff(av.Elem(), bv.Elem()) + } + case reflect.Slice: + lenA := av.Len() + lenB := bv.Len() + if lenA != lenB { + w.printf("%s[%d] != %s[%d]", av.Type(), lenA, bv.Type(), lenB) + break + } + for i := 0; i < lenA; i++ { + w.relabel(fmt.Sprintf("[%d]", i)).diff(av.Index(i), bv.Index(i)) + } + case reflect.String: + if a, b := av.String(), bv.String(); a != b { + w.printf("%q != %q", a, b) + } + case reflect.Struct: + for i := 0; i < av.NumField(); i++ { + w.relabel(at.Field(i).Name).diff(av.Field(i), bv.Field(i)) + } + default: + panic("unknown reflect Kind: " + kind.String()) + } +} + +func (d diffPrinter) relabel(name string) (d1 diffPrinter) { + d1 = d + if d.l != "" && name[0] != '[' { + d1.l += "." + } + d1.l += name + return d1 +} + +// keyEqual compares a and b for equality. +// Both a and b must be valid map keys. +func keyEqual(av, bv reflect.Value) bool { + if !av.IsValid() && !bv.IsValid() { + return true + } + if !av.IsValid() || !bv.IsValid() || av.Type() != bv.Type() { + return false + } + switch kind := av.Kind(); kind { + case reflect.Bool: + a, b := av.Bool(), bv.Bool() + return a == b + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + a, b := av.Int(), bv.Int() + return a == b + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + a, b := av.Uint(), bv.Uint() + return a == b + case reflect.Float32, reflect.Float64: + a, b := av.Float(), bv.Float() + return a == b + case reflect.Complex64, reflect.Complex128: + a, b := av.Complex(), bv.Complex() + return a == b + case reflect.Array: + for i := 0; i < av.Len(); i++ { + if !keyEqual(av.Index(i), bv.Index(i)) { + return false + } + } + return true + case reflect.Chan, reflect.UnsafePointer, reflect.Ptr: + a, b := av.Pointer(), bv.Pointer() + return a == b + case reflect.Interface: + return keyEqual(av.Elem(), bv.Elem()) + case reflect.String: + a, b := av.String(), bv.String() + return a == b + case reflect.Struct: + for i := 0; i < av.NumField(); i++ { + if !keyEqual(av.Field(i), bv.Field(i)) { + return false + } + } + return true + default: + panic("invalid map key type " + av.Type().String()) + } +} + +func keyDiff(a, b []reflect.Value) (ak, both, bk []reflect.Value) { + for _, av := range a { + inBoth := false + for _, bv := range b { + if keyEqual(av, bv) { + inBoth = true + both = append(both, av) + break + } + } + if !inBoth { + ak = append(ak, av) + } + } + for _, bv := range b { + inBoth := false + for _, av := range a { + if keyEqual(av, bv) { + inBoth = true + break + } + } + if !inBoth { + bk = append(bk, bv) + } + } + return +} diff --git a/vendor/github.com/kr/pretty/diff_test.go b/vendor/github.com/kr/pretty/diff_test.go new file mode 100644 index 0000000..a951e4b --- /dev/null +++ b/vendor/github.com/kr/pretty/diff_test.go @@ -0,0 +1,213 @@ +package pretty + +import ( + "bytes" + "fmt" + "log" + "reflect" + "testing" + "unsafe" +) + +var ( + _ Logfer = (*testing.T)(nil) + _ Logfer = (*testing.B)(nil) + _ Printfer = (*log.Logger)(nil) +) + +type difftest struct { + a interface{} + b interface{} + exp []string +} + +type S struct { + A int + S *S + I interface{} + C []int +} + +type ( + N struct{ N int } + E interface{} +) + +var ( + c0 = make(chan int) + c1 = make(chan int) + f0 = func() {} + f1 = func() {} + i0 = 0 + i1 = 1 +) + +var diffs = []difftest{ + {a: nil, b: nil}, + {a: S{A: 1}, b: S{A: 1}}, + + {0, "", []string{`int != string`}}, + {0, 1, []string{`0 != 1`}}, + {S{}, new(S), []string{`pretty.S != *pretty.S`}}, + {"a", "b", []string{`"a" != "b"`}}, + {S{}, S{A: 1}, []string{`A: 0 != 1`}}, + {new(S), &S{A: 1}, []string{`A: 0 != 1`}}, + {S{S: new(S)}, S{S: &S{A: 1}}, []string{`S.A: 0 != 1`}}, + {S{}, S{I: 0}, []string{`I: nil != int(0)`}}, + {S{I: 1}, S{I: "x"}, []string{`I: int != string`}}, + {S{}, S{C: []int{1}}, []string{`C: []int[0] != []int[1]`}}, + {S{C: []int{}}, S{C: []int{1}}, []string{`C: []int[0] != []int[1]`}}, + {S{C: []int{1, 2, 3}}, S{C: []int{1, 2, 4}}, []string{`C[2]: 3 != 4`}}, + {S{}, S{A: 1, S: new(S)}, []string{`A: 0 != 1`, `S: nil != &pretty.S{}`}}, + + // unexported fields of every reflect.Kind (both equal and unequal) + {struct{ x bool }{false}, struct{ x bool }{false}, nil}, + {struct{ x bool }{false}, struct{ x bool }{true}, []string{`x: false != true`}}, + {struct{ x int }{0}, struct{ x int }{0}, nil}, + {struct{ x int }{0}, struct{ x int }{1}, []string{`x: 0 != 1`}}, + {struct{ x int8 }{0}, struct{ x int8 }{0}, nil}, + {struct{ x int8 }{0}, struct{ x int8 }{1}, []string{`x: 0 != 1`}}, + {struct{ x int16 }{0}, struct{ x int16 }{0}, nil}, + {struct{ x int16 }{0}, struct{ x int16 }{1}, []string{`x: 0 != 1`}}, + {struct{ x int32 }{0}, struct{ x int32 }{0}, nil}, + {struct{ x int32 }{0}, struct{ x int32 }{1}, []string{`x: 0 != 1`}}, + {struct{ x int64 }{0}, struct{ x int64 }{0}, nil}, + {struct{ x int64 }{0}, struct{ x int64 }{1}, []string{`x: 0 != 1`}}, + {struct{ x uint }{0}, struct{ x uint }{0}, nil}, + {struct{ x uint }{0}, struct{ x uint }{1}, []string{`x: 0 != 1`}}, + {struct{ x uint8 }{0}, struct{ x uint8 }{0}, nil}, + {struct{ x uint8 }{0}, struct{ x uint8 }{1}, []string{`x: 0 != 1`}}, + {struct{ x uint16 }{0}, struct{ x uint16 }{0}, nil}, + {struct{ x uint16 }{0}, struct{ x uint16 }{1}, []string{`x: 0 != 1`}}, + {struct{ x uint32 }{0}, struct{ x uint32 }{0}, nil}, + {struct{ x uint32 }{0}, struct{ x uint32 }{1}, []string{`x: 0 != 1`}}, + {struct{ x uint64 }{0}, struct{ x uint64 }{0}, nil}, + {struct{ x uint64 }{0}, struct{ x uint64 }{1}, []string{`x: 0 != 1`}}, + {struct{ x uintptr }{0}, struct{ x uintptr }{0}, nil}, + {struct{ x uintptr }{0}, struct{ x uintptr }{1}, []string{`x: 0 != 1`}}, + {struct{ x float32 }{0}, struct{ x float32 }{0}, nil}, + {struct{ x float32 }{0}, struct{ x float32 }{1}, []string{`x: 0 != 1`}}, + {struct{ x float64 }{0}, struct{ x float64 }{0}, nil}, + {struct{ x float64 }{0}, struct{ x float64 }{1}, []string{`x: 0 != 1`}}, + {struct{ x complex64 }{0}, struct{ x complex64 }{0}, nil}, + {struct{ x complex64 }{0}, struct{ x complex64 }{1}, []string{`x: (0+0i) != (1+0i)`}}, + {struct{ x complex128 }{0}, struct{ x complex128 }{0}, nil}, + {struct{ x complex128 }{0}, struct{ x complex128 }{1}, []string{`x: (0+0i) != (1+0i)`}}, + {struct{ x [1]int }{[1]int{0}}, struct{ x [1]int }{[1]int{0}}, nil}, + {struct{ x [1]int }{[1]int{0}}, struct{ x [1]int }{[1]int{1}}, []string{`x[0]: 0 != 1`}}, + {struct{ x chan int }{c0}, struct{ x chan int }{c0}, nil}, + {struct{ x chan int }{c0}, struct{ x chan int }{c1}, []string{fmt.Sprintf("x: %p != %p", c0, c1)}}, + {struct{ x func() }{f0}, struct{ x func() }{f0}, nil}, + {struct{ x func() }{f0}, struct{ x func() }{f1}, []string{fmt.Sprintf("x: %p != %p", f0, f1)}}, + {struct{ x interface{} }{0}, struct{ x interface{} }{0}, nil}, + {struct{ x interface{} }{0}, struct{ x interface{} }{1}, []string{`x: 0 != 1`}}, + {struct{ x interface{} }{0}, struct{ x interface{} }{""}, []string{`x: int != string`}}, + {struct{ x interface{} }{0}, struct{ x interface{} }{nil}, []string{`x: int(0) != nil`}}, + {struct{ x interface{} }{nil}, struct{ x interface{} }{0}, []string{`x: nil != int(0)`}}, + {struct{ x map[int]int }{map[int]int{0: 0}}, struct{ x map[int]int }{map[int]int{0: 0}}, nil}, + {struct{ x map[int]int }{map[int]int{0: 0}}, struct{ x map[int]int }{map[int]int{0: 1}}, []string{`x[0]: 0 != 1`}}, + {struct{ x *int }{new(int)}, struct{ x *int }{new(int)}, nil}, + {struct{ x *int }{&i0}, struct{ x *int }{&i1}, []string{`x: 0 != 1`}}, + {struct{ x *int }{nil}, struct{ x *int }{&i0}, []string{`x: nil != &int(0)`}}, + {struct{ x *int }{&i0}, struct{ x *int }{nil}, []string{`x: &int(0) != nil`}}, + {struct{ x []int }{[]int{0}}, struct{ x []int }{[]int{0}}, nil}, + {struct{ x []int }{[]int{0}}, struct{ x []int }{[]int{1}}, []string{`x[0]: 0 != 1`}}, + {struct{ x string }{"a"}, struct{ x string }{"a"}, nil}, + {struct{ x string }{"a"}, struct{ x string }{"b"}, []string{`x: "a" != "b"`}}, + {struct{ x N }{N{0}}, struct{ x N }{N{0}}, nil}, + {struct{ x N }{N{0}}, struct{ x N }{N{1}}, []string{`x.N: 0 != 1`}}, + { + struct{ x unsafe.Pointer }{unsafe.Pointer(uintptr(0))}, + struct{ x unsafe.Pointer }{unsafe.Pointer(uintptr(0))}, + nil, + }, + { + struct{ x unsafe.Pointer }{unsafe.Pointer(uintptr(0))}, + struct{ x unsafe.Pointer }{unsafe.Pointer(uintptr(1))}, + []string{`x: 0x0 != 0x1`}, + }, +} + +func TestDiff(t *testing.T) { + for _, tt := range diffs { + got := Diff(tt.a, tt.b) + eq := len(got) == len(tt.exp) + if eq { + for i := range got { + eq = eq && got[i] == tt.exp[i] + } + } + if !eq { + t.Errorf("diffing % #v", tt.a) + t.Errorf("with % #v", tt.b) + diffdiff(t, got, tt.exp) + continue + } + } +} + +func TestKeyEqual(t *testing.T) { + var emptyInterfaceZero interface{} = 0 + + cases := []interface{}{ + new(bool), + new(int), + new(int8), + new(int16), + new(int32), + new(int64), + new(uint), + new(uint8), + new(uint16), + new(uint32), + new(uint64), + new(uintptr), + new(float32), + new(float64), + new(complex64), + new(complex128), + new([1]int), + new(chan int), + new(unsafe.Pointer), + new(interface{}), + &emptyInterfaceZero, + new(*int), + new(string), + new(struct{ int }), + } + + for _, test := range cases { + rv := reflect.ValueOf(test).Elem() + if !keyEqual(rv, rv) { + t.Errorf("keyEqual(%s, %s) = false want true", rv.Type(), rv.Type()) + } + } +} + +func TestFdiff(t *testing.T) { + var buf bytes.Buffer + Fdiff(&buf, 0, 1) + want := "0 != 1\n" + if got := buf.String(); got != want { + t.Errorf("Fdiff(0, 1) = %q want %q", got, want) + } +} + +func diffdiff(t *testing.T, got, exp []string) { + minus(t, "unexpected:", got, exp) + minus(t, "missing:", exp, got) +} + +func minus(t *testing.T, s string, a, b []string) { + var i, j int + for i = 0; i < len(a); i++ { + for j = 0; j < len(b); j++ { + if a[i] == b[j] { + break + } + } + if j == len(b) { + t.Error(s, a[i]) + } + } +} diff --git a/vendor/github.com/kr/pretty/example_test.go b/vendor/github.com/kr/pretty/example_test.go new file mode 100644 index 0000000..ecf40f3 --- /dev/null +++ b/vendor/github.com/kr/pretty/example_test.go @@ -0,0 +1,20 @@ +package pretty_test + +import ( + "fmt" + "github.com/kr/pretty" +) + +func Example() { + type myType struct { + a, b int + } + var x = []myType{{1, 2}, {3, 4}, {5, 6}} + fmt.Printf("%# v", pretty.Formatter(x)) + // output: + // []pretty_test.myType{ + // {a:1, b:2}, + // {a:3, b:4}, + // {a:5, b:6}, + // } +} diff --git a/vendor/github.com/kr/pretty/formatter.go b/vendor/github.com/kr/pretty/formatter.go new file mode 100644 index 0000000..a317d7b --- /dev/null +++ b/vendor/github.com/kr/pretty/formatter.go @@ -0,0 +1,328 @@ +package pretty + +import ( + "fmt" + "io" + "reflect" + "strconv" + "text/tabwriter" + + "github.com/kr/text" +) + +type formatter struct { + v reflect.Value + force bool + quote bool +} + +// Formatter makes a wrapper, f, that will format x as go source with line +// breaks and tabs. Object f responds to the "%v" formatting verb when both the +// "#" and " " (space) flags are set, for example: +// +// fmt.Sprintf("%# v", Formatter(x)) +// +// If one of these two flags is not set, or any other verb is used, f will +// format x according to the usual rules of package fmt. +// In particular, if x satisfies fmt.Formatter, then x.Format will be called. +func Formatter(x interface{}) (f fmt.Formatter) { + return formatter{v: reflect.ValueOf(x), quote: true} +} + +func (fo formatter) String() string { + return fmt.Sprint(fo.v.Interface()) // unwrap it +} + +func (fo formatter) passThrough(f fmt.State, c rune) { + s := "%" + for i := 0; i < 128; i++ { + if f.Flag(i) { + s += string(i) + } + } + if w, ok := f.Width(); ok { + s += fmt.Sprintf("%d", w) + } + if p, ok := f.Precision(); ok { + s += fmt.Sprintf(".%d", p) + } + s += string(c) + fmt.Fprintf(f, s, fo.v.Interface()) +} + +func (fo formatter) Format(f fmt.State, c rune) { + if fo.force || c == 'v' && f.Flag('#') && f.Flag(' ') { + w := tabwriter.NewWriter(f, 4, 4, 1, ' ', 0) + p := &printer{tw: w, Writer: w, visited: make(map[visit]int)} + p.printValue(fo.v, true, fo.quote) + w.Flush() + return + } + fo.passThrough(f, c) +} + +type printer struct { + io.Writer + tw *tabwriter.Writer + visited map[visit]int + depth int +} + +func (p *printer) indent() *printer { + q := *p + q.tw = tabwriter.NewWriter(p.Writer, 4, 4, 1, ' ', 0) + q.Writer = text.NewIndentWriter(q.tw, []byte{'\t'}) + return &q +} + +func (p *printer) printInline(v reflect.Value, x interface{}, showType bool) { + if showType { + io.WriteString(p, v.Type().String()) + fmt.Fprintf(p, "(%#v)", x) + } else { + fmt.Fprintf(p, "%#v", x) + } +} + +// printValue must keep track of already-printed pointer values to avoid +// infinite recursion. +type visit struct { + v uintptr + typ reflect.Type +} + +func (p *printer) printValue(v reflect.Value, showType, quote bool) { + if p.depth > 10 { + io.WriteString(p, "!%v(DEPTH EXCEEDED)") + return + } + + switch v.Kind() { + case reflect.Bool: + p.printInline(v, v.Bool(), showType) + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + p.printInline(v, v.Int(), showType) + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + p.printInline(v, v.Uint(), showType) + case reflect.Float32, reflect.Float64: + p.printInline(v, v.Float(), showType) + case reflect.Complex64, reflect.Complex128: + fmt.Fprintf(p, "%#v", v.Complex()) + case reflect.String: + p.fmtString(v.String(), quote) + case reflect.Map: + t := v.Type() + if showType { + io.WriteString(p, t.String()) + } + writeByte(p, '{') + if nonzero(v) { + expand := !canInline(v.Type()) + pp := p + if expand { + writeByte(p, '\n') + pp = p.indent() + } + keys := v.MapKeys() + for i := 0; i < v.Len(); i++ { + showTypeInStruct := true + k := keys[i] + mv := v.MapIndex(k) + pp.printValue(k, false, true) + writeByte(pp, ':') + if expand { + writeByte(pp, '\t') + } + showTypeInStruct = t.Elem().Kind() == reflect.Interface + pp.printValue(mv, showTypeInStruct, true) + if expand { + io.WriteString(pp, ",\n") + } else if i < v.Len()-1 { + io.WriteString(pp, ", ") + } + } + if expand { + pp.tw.Flush() + } + } + writeByte(p, '}') + case reflect.Struct: + t := v.Type() + if v.CanAddr() { + addr := v.UnsafeAddr() + vis := visit{addr, t} + if vd, ok := p.visited[vis]; ok && vd < p.depth { + p.fmtString(t.String()+"{(CYCLIC REFERENCE)}", false) + break // don't print v again + } + p.visited[vis] = p.depth + } + + if showType { + io.WriteString(p, t.String()) + } + writeByte(p, '{') + if nonzero(v) { + expand := !canInline(v.Type()) + pp := p + if expand { + writeByte(p, '\n') + pp = p.indent() + } + for i := 0; i < v.NumField(); i++ { + showTypeInStruct := true + if f := t.Field(i); f.Name != "" { + io.WriteString(pp, f.Name) + writeByte(pp, ':') + if expand { + writeByte(pp, '\t') + } + showTypeInStruct = labelType(f.Type) + } + pp.printValue(getField(v, i), showTypeInStruct, true) + if expand { + io.WriteString(pp, ",\n") + } else if i < v.NumField()-1 { + io.WriteString(pp, ", ") + } + } + if expand { + pp.tw.Flush() + } + } + writeByte(p, '}') + case reflect.Interface: + switch e := v.Elem(); { + case e.Kind() == reflect.Invalid: + io.WriteString(p, "nil") + case e.IsValid(): + pp := *p + pp.depth++ + pp.printValue(e, showType, true) + default: + io.WriteString(p, v.Type().String()) + io.WriteString(p, "(nil)") + } + case reflect.Array, reflect.Slice: + t := v.Type() + if showType { + io.WriteString(p, t.String()) + } + if v.Kind() == reflect.Slice && v.IsNil() && showType { + io.WriteString(p, "(nil)") + break + } + if v.Kind() == reflect.Slice && v.IsNil() { + io.WriteString(p, "nil") + break + } + writeByte(p, '{') + expand := !canInline(v.Type()) + pp := p + if expand { + writeByte(p, '\n') + pp = p.indent() + } + for i := 0; i < v.Len(); i++ { + showTypeInSlice := t.Elem().Kind() == reflect.Interface + pp.printValue(v.Index(i), showTypeInSlice, true) + if expand { + io.WriteString(pp, ",\n") + } else if i < v.Len()-1 { + io.WriteString(pp, ", ") + } + } + if expand { + pp.tw.Flush() + } + writeByte(p, '}') + case reflect.Ptr: + e := v.Elem() + if !e.IsValid() { + writeByte(p, '(') + io.WriteString(p, v.Type().String()) + io.WriteString(p, ")(nil)") + } else { + pp := *p + pp.depth++ + writeByte(pp, '&') + pp.printValue(e, true, true) + } + case reflect.Chan: + x := v.Pointer() + if showType { + writeByte(p, '(') + io.WriteString(p, v.Type().String()) + fmt.Fprintf(p, ")(%#v)", x) + } else { + fmt.Fprintf(p, "%#v", x) + } + case reflect.Func: + io.WriteString(p, v.Type().String()) + io.WriteString(p, " {...}") + case reflect.UnsafePointer: + p.printInline(v, v.Pointer(), showType) + case reflect.Invalid: + io.WriteString(p, "nil") + } +} + +func canInline(t reflect.Type) bool { + switch t.Kind() { + case reflect.Map: + return !canExpand(t.Elem()) + case reflect.Struct: + for i := 0; i < t.NumField(); i++ { + if canExpand(t.Field(i).Type) { + return false + } + } + return true + case reflect.Interface: + return false + case reflect.Array, reflect.Slice: + return !canExpand(t.Elem()) + case reflect.Ptr: + return false + case reflect.Chan, reflect.Func, reflect.UnsafePointer: + return false + } + return true +} + +func canExpand(t reflect.Type) bool { + switch t.Kind() { + case reflect.Map, reflect.Struct, + reflect.Interface, reflect.Array, reflect.Slice, + reflect.Ptr: + return true + } + return false +} + +func labelType(t reflect.Type) bool { + switch t.Kind() { + case reflect.Interface, reflect.Struct: + return true + } + return false +} + +func (p *printer) fmtString(s string, quote bool) { + if quote { + s = strconv.Quote(s) + } + io.WriteString(p, s) +} + +func writeByte(w io.Writer, b byte) { + w.Write([]byte{b}) +} + +func getField(v reflect.Value, i int) reflect.Value { + val := v.Field(i) + if val.Kind() == reflect.Interface && !val.IsNil() { + val = val.Elem() + } + return val +} diff --git a/vendor/github.com/kr/pretty/formatter_test.go b/vendor/github.com/kr/pretty/formatter_test.go new file mode 100644 index 0000000..c8c0b51 --- /dev/null +++ b/vendor/github.com/kr/pretty/formatter_test.go @@ -0,0 +1,288 @@ +package pretty + +import ( + "fmt" + "io" + "strings" + "testing" + "unsafe" +) + +type test struct { + v interface{} + s string +} + +type passtest struct { + v interface{} + f, s string +} + +type LongStructTypeName struct { + longFieldName interface{} + otherLongFieldName interface{} +} + +type SA struct { + t *T + v T +} + +type T struct { + x, y int +} + +type F int + +func (f F) Format(s fmt.State, c rune) { + fmt.Fprintf(s, "F(%d)", int(f)) +} + +type Stringer struct { i int } + +func (s *Stringer) String() string { return "foo" } + +var long = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" + +var passthrough = []passtest{ + {1, "%d", "1"}, + {"a", "%s", "a"}, + {&Stringer{}, "%s", "foo"}, +} + +func TestPassthrough(t *testing.T) { + for _, tt := range passthrough { + s := fmt.Sprintf(tt.f, Formatter(tt.v)) + if tt.s != s { + t.Errorf("expected %q", tt.s) + t.Errorf("got %q", s) + t.Errorf("expraw\n%s", tt.s) + t.Errorf("gotraw\n%s", s) + } + } +} + +var gosyntax = []test{ + {nil, `nil`}, + {"", `""`}, + {"a", `"a"`}, + {1, "int(1)"}, + {1.0, "float64(1)"}, + {[]int(nil), "[]int(nil)"}, + {[0]int{}, "[0]int{}"}, + {complex(1, 0), "(1+0i)"}, + //{make(chan int), "(chan int)(0x1234)"}, + {unsafe.Pointer(uintptr(unsafe.Pointer(&long))), fmt.Sprintf("unsafe.Pointer(0x%02x)", uintptr(unsafe.Pointer(&long)))}, + {func(int) {}, "func(int) {...}"}, + {map[int]int{1: 1}, "map[int]int{1:1}"}, + {int32(1), "int32(1)"}, + {io.EOF, `&errors.errorString{s:"EOF"}`}, + {[]string{"a"}, `[]string{"a"}`}, + { + []string{long}, + `[]string{"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"}`, + }, + {F(5), "pretty.F(5)"}, + { + SA{&T{1, 2}, T{3, 4}}, + `pretty.SA{ + t: &pretty.T{x:1, y:2}, + v: pretty.T{x:3, y:4}, +}`, + }, + { + map[int][]byte{1: {}}, + `map[int][]uint8{ + 1: {}, +}`, + }, + { + map[int]T{1: {}}, + `map[int]pretty.T{ + 1: {}, +}`, + }, + { + long, + `"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"`, + }, + { + LongStructTypeName{ + longFieldName: LongStructTypeName{}, + otherLongFieldName: long, + }, + `pretty.LongStructTypeName{ + longFieldName: pretty.LongStructTypeName{}, + otherLongFieldName: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", +}`, + }, + { + &LongStructTypeName{ + longFieldName: &LongStructTypeName{}, + otherLongFieldName: (*LongStructTypeName)(nil), + }, + `&pretty.LongStructTypeName{ + longFieldName: &pretty.LongStructTypeName{}, + otherLongFieldName: (*pretty.LongStructTypeName)(nil), +}`, + }, + { + []LongStructTypeName{ + {nil, nil}, + {3, 3}, + {long, nil}, + }, + `[]pretty.LongStructTypeName{ + {}, + { + longFieldName: int(3), + otherLongFieldName: int(3), + }, + { + longFieldName: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", + otherLongFieldName: nil, + }, +}`, + }, + { + []interface{}{ + LongStructTypeName{nil, nil}, + []byte{1, 2, 3}, + T{3, 4}, + LongStructTypeName{long, nil}, + }, + `[]interface {}{ + pretty.LongStructTypeName{}, + []uint8{0x1, 0x2, 0x3}, + pretty.T{x:3, y:4}, + pretty.LongStructTypeName{ + longFieldName: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", + otherLongFieldName: nil, + }, +}`, + }, +} + +func TestGoSyntax(t *testing.T) { + for _, tt := range gosyntax { + s := fmt.Sprintf("%# v", Formatter(tt.v)) + if tt.s != s { + t.Errorf("expected %q", tt.s) + t.Errorf("got %q", s) + t.Errorf("expraw\n%s", tt.s) + t.Errorf("gotraw\n%s", s) + } + } +} + +type I struct { + i int + R interface{} +} + +func (i *I) I() *I { return i.R.(*I) } + +func TestCycle(t *testing.T) { + type A struct{ *A } + v := &A{} + v.A = v + + // panics from stack overflow without cycle detection + t.Logf("Example cycle:\n%# v", Formatter(v)) + + p := &A{} + s := fmt.Sprintf("%# v", Formatter([]*A{p, p})) + if strings.Contains(s, "CYCLIC") { + t.Errorf("Repeated address detected as cyclic reference:\n%s", s) + } + + type R struct { + i int + *R + } + r := &R{ + i: 1, + R: &R{ + i: 2, + R: &R{ + i: 3, + }, + }, + } + r.R.R.R = r + t.Logf("Example longer cycle:\n%# v", Formatter(r)) + + r = &R{ + i: 1, + R: &R{ + i: 2, + R: &R{ + i: 3, + R: &R{ + i: 4, + R: &R{ + i: 5, + R: &R{ + i: 6, + R: &R{ + i: 7, + R: &R{ + i: 8, + R: &R{ + i: 9, + R: &R{ + i: 10, + R: &R{ + i: 11, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + } + // here be pirates + r.R.R.R.R.R.R.R.R.R.R.R = r + t.Logf("Example very long cycle:\n%# v", Formatter(r)) + + i := &I{ + i: 1, + R: &I{ + i: 2, + R: &I{ + i: 3, + R: &I{ + i: 4, + R: &I{ + i: 5, + R: &I{ + i: 6, + R: &I{ + i: 7, + R: &I{ + i: 8, + R: &I{ + i: 9, + R: &I{ + i: 10, + R: &I{ + i: 11, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + } + iv := i.I().I().I().I().I().I().I().I().I().I() + *iv = *i + t.Logf("Example long interface cycle:\n%# v", Formatter(i)) +} diff --git a/vendor/github.com/kr/pretty/go.mod b/vendor/github.com/kr/pretty/go.mod new file mode 100644 index 0000000..1e29533 --- /dev/null +++ b/vendor/github.com/kr/pretty/go.mod @@ -0,0 +1,3 @@ +module "github.com/kr/pretty" + +require "github.com/kr/text" v0.1.0 diff --git a/vendor/github.com/kr/pretty/pretty.go b/vendor/github.com/kr/pretty/pretty.go new file mode 100644 index 0000000..49423ec --- /dev/null +++ b/vendor/github.com/kr/pretty/pretty.go @@ -0,0 +1,108 @@ +// Package pretty provides pretty-printing for Go values. This is +// useful during debugging, to avoid wrapping long output lines in +// the terminal. +// +// It provides a function, Formatter, that can be used with any +// function that accepts a format string. It also provides +// convenience wrappers for functions in packages fmt and log. +package pretty + +import ( + "fmt" + "io" + "log" + "reflect" +) + +// Errorf is a convenience wrapper for fmt.Errorf. +// +// Calling Errorf(f, x, y) is equivalent to +// fmt.Errorf(f, Formatter(x), Formatter(y)). +func Errorf(format string, a ...interface{}) error { + return fmt.Errorf(format, wrap(a, false)...) +} + +// Fprintf is a convenience wrapper for fmt.Fprintf. +// +// Calling Fprintf(w, f, x, y) is equivalent to +// fmt.Fprintf(w, f, Formatter(x), Formatter(y)). +func Fprintf(w io.Writer, format string, a ...interface{}) (n int, error error) { + return fmt.Fprintf(w, format, wrap(a, false)...) +} + +// Log is a convenience wrapper for log.Printf. +// +// Calling Log(x, y) is equivalent to +// log.Print(Formatter(x), Formatter(y)), but each operand is +// formatted with "%# v". +func Log(a ...interface{}) { + log.Print(wrap(a, true)...) +} + +// Logf is a convenience wrapper for log.Printf. +// +// Calling Logf(f, x, y) is equivalent to +// log.Printf(f, Formatter(x), Formatter(y)). +func Logf(format string, a ...interface{}) { + log.Printf(format, wrap(a, false)...) +} + +// Logln is a convenience wrapper for log.Printf. +// +// Calling Logln(x, y) is equivalent to +// log.Println(Formatter(x), Formatter(y)), but each operand is +// formatted with "%# v". +func Logln(a ...interface{}) { + log.Println(wrap(a, true)...) +} + +// Print pretty-prints its operands and writes to standard output. +// +// Calling Print(x, y) is equivalent to +// fmt.Print(Formatter(x), Formatter(y)), but each operand is +// formatted with "%# v". +func Print(a ...interface{}) (n int, errno error) { + return fmt.Print(wrap(a, true)...) +} + +// Printf is a convenience wrapper for fmt.Printf. +// +// Calling Printf(f, x, y) is equivalent to +// fmt.Printf(f, Formatter(x), Formatter(y)). +func Printf(format string, a ...interface{}) (n int, errno error) { + return fmt.Printf(format, wrap(a, false)...) +} + +// Println pretty-prints its operands and writes to standard output. +// +// Calling Print(x, y) is equivalent to +// fmt.Println(Formatter(x), Formatter(y)), but each operand is +// formatted with "%# v". +func Println(a ...interface{}) (n int, errno error) { + return fmt.Println(wrap(a, true)...) +} + +// Sprint is a convenience wrapper for fmt.Sprintf. +// +// Calling Sprint(x, y) is equivalent to +// fmt.Sprint(Formatter(x), Formatter(y)), but each operand is +// formatted with "%# v". +func Sprint(a ...interface{}) string { + return fmt.Sprint(wrap(a, true)...) +} + +// Sprintf is a convenience wrapper for fmt.Sprintf. +// +// Calling Sprintf(f, x, y) is equivalent to +// fmt.Sprintf(f, Formatter(x), Formatter(y)). +func Sprintf(format string, a ...interface{}) string { + return fmt.Sprintf(format, wrap(a, false)...) +} + +func wrap(a []interface{}, force bool) []interface{} { + w := make([]interface{}, len(a)) + for i, x := range a { + w[i] = formatter{v: reflect.ValueOf(x), force: force} + } + return w +} diff --git a/vendor/github.com/kr/pretty/zero.go b/vendor/github.com/kr/pretty/zero.go new file mode 100644 index 0000000..abb5b6f --- /dev/null +++ b/vendor/github.com/kr/pretty/zero.go @@ -0,0 +1,41 @@ +package pretty + +import ( + "reflect" +) + +func nonzero(v reflect.Value) bool { + switch v.Kind() { + case reflect.Bool: + return v.Bool() + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return v.Int() != 0 + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + return v.Uint() != 0 + case reflect.Float32, reflect.Float64: + return v.Float() != 0 + case reflect.Complex64, reflect.Complex128: + return v.Complex() != complex(0, 0) + case reflect.String: + return v.String() != "" + case reflect.Struct: + for i := 0; i < v.NumField(); i++ { + if nonzero(getField(v, i)) { + return true + } + } + return false + case reflect.Array: + for i := 0; i < v.Len(); i++ { + if nonzero(v.Index(i)) { + return true + } + } + return false + case reflect.Map, reflect.Interface, reflect.Slice, reflect.Ptr, reflect.Chan, reflect.Func: + return !v.IsNil() + case reflect.UnsafePointer: + return v.Pointer() != 0 + } + return true +} diff --git a/vendor/github.com/kr/text/License b/vendor/github.com/kr/text/License new file mode 100644 index 0000000..480a328 --- /dev/null +++ b/vendor/github.com/kr/text/License @@ -0,0 +1,19 @@ +Copyright 2012 Keith Rarick + +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. diff --git a/vendor/github.com/kr/text/Readme b/vendor/github.com/kr/text/Readme new file mode 100644 index 0000000..7e6e7c0 --- /dev/null +++ b/vendor/github.com/kr/text/Readme @@ -0,0 +1,3 @@ +This is a Go package for manipulating paragraphs of text. + +See http://go.pkgdoc.org/github.com/kr/text for full documentation. diff --git a/vendor/github.com/kr/text/doc.go b/vendor/github.com/kr/text/doc.go new file mode 100644 index 0000000..cf4c198 --- /dev/null +++ b/vendor/github.com/kr/text/doc.go @@ -0,0 +1,3 @@ +// Package text provides rudimentary functions for manipulating text in +// paragraphs. +package text diff --git a/vendor/github.com/kr/text/go.mod b/vendor/github.com/kr/text/go.mod new file mode 100644 index 0000000..fa0528b --- /dev/null +++ b/vendor/github.com/kr/text/go.mod @@ -0,0 +1,3 @@ +module "github.com/kr/text" + +require "github.com/kr/pty" v1.1.1 diff --git a/vendor/github.com/kr/text/indent.go b/vendor/github.com/kr/text/indent.go new file mode 100644 index 0000000..4ebac45 --- /dev/null +++ b/vendor/github.com/kr/text/indent.go @@ -0,0 +1,74 @@ +package text + +import ( + "io" +) + +// Indent inserts prefix at the beginning of each non-empty line of s. The +// end-of-line marker is NL. +func Indent(s, prefix string) string { + return string(IndentBytes([]byte(s), []byte(prefix))) +} + +// IndentBytes inserts prefix at the beginning of each non-empty line of b. +// The end-of-line marker is NL. +func IndentBytes(b, prefix []byte) []byte { + var res []byte + bol := true + for _, c := range b { + if bol && c != '\n' { + res = append(res, prefix...) + } + res = append(res, c) + bol = c == '\n' + } + return res +} + +// Writer indents each line of its input. +type indentWriter struct { + w io.Writer + bol bool + pre [][]byte + sel int + off int +} + +// NewIndentWriter makes a new write filter that indents the input +// lines. Each line is prefixed in order with the corresponding +// element of pre. If there are more lines than elements, the last +// element of pre is repeated for each subsequent line. +func NewIndentWriter(w io.Writer, pre ...[]byte) io.Writer { + return &indentWriter{ + w: w, + pre: pre, + bol: true, + } +} + +// The only errors returned are from the underlying indentWriter. +func (w *indentWriter) Write(p []byte) (n int, err error) { + for _, c := range p { + if w.bol { + var i int + i, err = w.w.Write(w.pre[w.sel][w.off:]) + w.off += i + if err != nil { + return n, err + } + } + _, err = w.w.Write([]byte{c}) + if err != nil { + return n, err + } + n++ + w.bol = c == '\n' + if w.bol { + w.off = 0 + if w.sel < len(w.pre)-1 { + w.sel++ + } + } + } + return n, nil +} diff --git a/vendor/github.com/kr/text/indent_test.go b/vendor/github.com/kr/text/indent_test.go new file mode 100644 index 0000000..5c723ee --- /dev/null +++ b/vendor/github.com/kr/text/indent_test.go @@ -0,0 +1,119 @@ +package text + +import ( + "bytes" + "testing" +) + +type T struct { + inp, exp, pre string +} + +var tests = []T{ + { + "The quick brown fox\njumps over the lazy\ndog.\nBut not quickly.\n", + "xxxThe quick brown fox\nxxxjumps over the lazy\nxxxdog.\nxxxBut not quickly.\n", + "xxx", + }, + { + "The quick brown fox\njumps over the lazy\ndog.\n\nBut not quickly.", + "xxxThe quick brown fox\nxxxjumps over the lazy\nxxxdog.\n\nxxxBut not quickly.", + "xxx", + }, +} + +func TestIndent(t *testing.T) { + for _, test := range tests { + got := Indent(test.inp, test.pre) + if got != test.exp { + t.Errorf("mismatch %q != %q", got, test.exp) + } + } +} + +type IndentWriterTest struct { + inp, exp string + pre []string +} + +var ts = []IndentWriterTest{ + { + ` +The quick brown fox +jumps over the lazy +dog. +But not quickly. +`[1:], + ` +xxxThe quick brown fox +xxxjumps over the lazy +xxxdog. +xxxBut not quickly. +`[1:], + []string{"xxx"}, + }, + { + ` +The quick brown fox +jumps over the lazy +dog. +But not quickly. +`[1:], + ` +xxaThe quick brown fox +xxxjumps over the lazy +xxxdog. +xxxBut not quickly. +`[1:], + []string{"xxa", "xxx"}, + }, + { + ` +The quick brown fox +jumps over the lazy +dog. +But not quickly. +`[1:], + ` +xxaThe quick brown fox +xxbjumps over the lazy +xxcdog. +xxxBut not quickly. +`[1:], + []string{"xxa", "xxb", "xxc", "xxx"}, + }, + { + ` +The quick brown fox +jumps over the lazy +dog. + +But not quickly.`[1:], + ` +xxaThe quick brown fox +xxxjumps over the lazy +xxxdog. +xxx +xxxBut not quickly.`[1:], + []string{"xxa", "xxx"}, + }, +} + +func TestIndentWriter(t *testing.T) { + for _, test := range ts { + b := new(bytes.Buffer) + pre := make([][]byte, len(test.pre)) + for i := range test.pre { + pre[i] = []byte(test.pre[i]) + } + w := NewIndentWriter(b, pre...) + if _, err := w.Write([]byte(test.inp)); err != nil { + t.Error(err) + } + if got := b.String(); got != test.exp { + t.Errorf("mismatch %q != %q", got, test.exp) + t.Log(got) + t.Log(test.exp) + } + } +} diff --git a/vendor/github.com/kr/text/wrap.go b/vendor/github.com/kr/text/wrap.go new file mode 100644 index 0000000..b09bb03 --- /dev/null +++ b/vendor/github.com/kr/text/wrap.go @@ -0,0 +1,86 @@ +package text + +import ( + "bytes" + "math" +) + +var ( + nl = []byte{'\n'} + sp = []byte{' '} +) + +const defaultPenalty = 1e5 + +// Wrap wraps s into a paragraph of lines of length lim, with minimal +// raggedness. +func Wrap(s string, lim int) string { + return string(WrapBytes([]byte(s), lim)) +} + +// WrapBytes wraps b into a paragraph of lines of length lim, with minimal +// raggedness. +func WrapBytes(b []byte, lim int) []byte { + words := bytes.Split(bytes.Replace(bytes.TrimSpace(b), nl, sp, -1), sp) + var lines [][]byte + for _, line := range WrapWords(words, 1, lim, defaultPenalty) { + lines = append(lines, bytes.Join(line, sp)) + } + return bytes.Join(lines, nl) +} + +// WrapWords is the low-level line-breaking algorithm, useful if you need more +// control over the details of the text wrapping process. For most uses, either +// Wrap or WrapBytes will be sufficient and more convenient. +// +// WrapWords splits a list of words into lines with minimal "raggedness", +// treating each byte as one unit, accounting for spc units between adjacent +// words on each line, and attempting to limit lines to lim units. Raggedness +// is the total error over all lines, where error is the square of the +// difference of the length of the line and lim. Too-long lines (which only +// happen when a single word is longer than lim units) have pen penalty units +// added to the error. +func WrapWords(words [][]byte, spc, lim, pen int) [][][]byte { + n := len(words) + + length := make([][]int, n) + for i := 0; i < n; i++ { + length[i] = make([]int, n) + length[i][i] = len(words[i]) + for j := i + 1; j < n; j++ { + length[i][j] = length[i][j-1] + spc + len(words[j]) + } + } + + nbrk := make([]int, n) + cost := make([]int, n) + for i := range cost { + cost[i] = math.MaxInt32 + } + for i := n - 1; i >= 0; i-- { + if length[i][n-1] <= lim || i == n-1 { + cost[i] = 0 + nbrk[i] = n + } else { + for j := i + 1; j < n; j++ { + d := lim - length[i][j-1] + c := d*d + cost[j] + if length[i][j-1] > lim { + c += pen // too-long lines get a worse penalty + } + if c < cost[i] { + cost[i] = c + nbrk[i] = j + } + } + } + } + + var lines [][][]byte + i := 0 + for i < n { + lines = append(lines, words[i:nbrk[i]]) + i = nbrk[i] + } + return lines +} diff --git a/vendor/github.com/kr/text/wrap_test.go b/vendor/github.com/kr/text/wrap_test.go new file mode 100644 index 0000000..634b6e8 --- /dev/null +++ b/vendor/github.com/kr/text/wrap_test.go @@ -0,0 +1,62 @@ +package text + +import ( + "bytes" + "testing" +) + +var text = "The quick brown fox jumps over the lazy dog." + +func TestWrap(t *testing.T) { + exp := [][]string{ + {"The", "quick", "brown", "fox"}, + {"jumps", "over", "the", "lazy", "dog."}, + } + words := bytes.Split([]byte(text), sp) + got := WrapWords(words, 1, 24, defaultPenalty) + if len(exp) != len(got) { + t.Fail() + } + for i := range exp { + if len(exp[i]) != len(got[i]) { + t.Fail() + } + for j := range exp[i] { + if exp[i][j] != string(got[i][j]) { + t.Fatal(i, exp[i][j], got[i][j]) + } + } + } +} + +func TestWrapNarrow(t *testing.T) { + exp := "The\nquick\nbrown\nfox\njumps\nover\nthe\nlazy\ndog." + if Wrap(text, 5) != exp { + t.Fail() + } +} + +func TestWrapOneLine(t *testing.T) { + exp := "The quick brown fox jumps over the lazy dog." + if Wrap(text, 500) != exp { + t.Fail() + } +} + +func TestWrapBug1(t *testing.T) { + cases := []struct { + limit int + text string + want string + }{ + {4, "aaaaa", "aaaaa"}, + {4, "a aaaaa", "a\naaaaa"}, + } + + for _, test := range cases { + got := Wrap(test.text, test.limit) + if got != test.want { + t.Errorf("Wrap(%q, %d) = %q want %q", test.text, test.limit, got, test.want) + } + } +} diff --git a/vendor/golang.org/x/crypto/cryptobyte/asn1.go b/vendor/golang.org/x/crypto/cryptobyte/asn1.go index 88ec8b4..528b9bf 100644 --- a/vendor/golang.org/x/crypto/cryptobyte/asn1.go +++ b/vendor/golang.org/x/crypto/cryptobyte/asn1.go @@ -23,6 +23,12 @@ func (b *Builder) AddASN1Int64(v int64) { b.addASN1Signed(asn1.INTEGER, v) } +// AddASN1Int64WithTag appends a DER-encoded ASN.1 INTEGER with the +// given tag. +func (b *Builder) AddASN1Int64WithTag(v int64, tag asn1.Tag) { + b.addASN1Signed(tag, v) +} + // AddASN1Enum appends a DER-encoded ASN.1 ENUMERATION. func (b *Builder) AddASN1Enum(v int64) { b.addASN1Signed(asn1.ENUM, v) @@ -224,6 +230,9 @@ func (b *Builder) AddASN1(tag asn1.Tag, f BuilderContinuation) { // String +// ReadASN1Boolean decodes an ASN.1 INTEGER and converts it to a boolean +// representation into out and advances. It reports whether the read +// was successful. func (s *String) ReadASN1Boolean(out *bool) bool { var bytes String if !s.ReadASN1(&bytes, asn1.INTEGER) || len(bytes) != 1 { @@ -245,8 +254,8 @@ func (s *String) ReadASN1Boolean(out *bool) bool { var bigIntType = reflect.TypeOf((*big.Int)(nil)).Elem() // ReadASN1Integer decodes an ASN.1 INTEGER into out and advances. If out does -// not point to an integer or to a big.Int, it panics. It returns true on -// success and false on error. +// not point to an integer or to a big.Int, it panics. It reports whether the +// read was successful. func (s *String) ReadASN1Integer(out interface{}) bool { if reflect.TypeOf(out).Kind() != reflect.Ptr { panic("out is not a pointer") @@ -359,8 +368,16 @@ func asn1Unsigned(out *uint64, n []byte) bool { return true } -// ReadASN1Enum decodes an ASN.1 ENUMERATION into out and advances. It returns -// true on success and false on error. +// ReadASN1Int64WithTag decodes an ASN.1 INTEGER with the given tag into out +// and advances. It reports whether the read was successful and resulted in a +// value that can be represented in an int64. +func (s *String) ReadASN1Int64WithTag(out *int64, tag asn1.Tag) bool { + var bytes String + return s.ReadASN1(&bytes, tag) && checkASN1Integer(bytes) && asn1Signed(out, bytes) +} + +// ReadASN1Enum decodes an ASN.1 ENUMERATION into out and advances. It reports +// whether the read was successful. func (s *String) ReadASN1Enum(out *int) bool { var bytes String var i int64 @@ -392,7 +409,7 @@ func (s *String) readBase128Int(out *int) bool { } // ReadASN1ObjectIdentifier decodes an ASN.1 OBJECT IDENTIFIER into out and -// advances. It returns true on success and false on error. +// advances. It reports whether the read was successful. func (s *String) ReadASN1ObjectIdentifier(out *encoding_asn1.ObjectIdentifier) bool { var bytes String if !s.ReadASN1(&bytes, asn1.OBJECT_IDENTIFIER) || len(bytes) == 0 { @@ -431,7 +448,7 @@ func (s *String) ReadASN1ObjectIdentifier(out *encoding_asn1.ObjectIdentifier) b } // ReadASN1GeneralizedTime decodes an ASN.1 GENERALIZEDTIME into out and -// advances. It returns true on success and false on error. +// advances. It reports whether the read was successful. func (s *String) ReadASN1GeneralizedTime(out *time.Time) bool { var bytes String if !s.ReadASN1(&bytes, asn1.GeneralizedTime) { @@ -449,8 +466,8 @@ func (s *String) ReadASN1GeneralizedTime(out *time.Time) bool { return true } -// ReadASN1BitString decodes an ASN.1 BIT STRING into out and advances. It -// returns true on success and false on error. +// ReadASN1BitString decodes an ASN.1 BIT STRING into out and advances. +// It reports whether the read was successful. func (s *String) ReadASN1BitString(out *encoding_asn1.BitString) bool { var bytes String if !s.ReadASN1(&bytes, asn1.BIT_STRING) || len(bytes) == 0 { @@ -471,8 +488,8 @@ func (s *String) ReadASN1BitString(out *encoding_asn1.BitString) bool { } // ReadASN1BitString decodes an ASN.1 BIT STRING into out and advances. It is -// an error if the BIT STRING is not a whole number of bytes. This function -// returns true on success and false on error. +// an error if the BIT STRING is not a whole number of bytes. It reports +// whether the read was successful. func (s *String) ReadASN1BitStringAsBytes(out *[]byte) bool { var bytes String if !s.ReadASN1(&bytes, asn1.BIT_STRING) || len(bytes) == 0 { @@ -489,14 +506,14 @@ func (s *String) ReadASN1BitStringAsBytes(out *[]byte) bool { // ReadASN1Bytes reads the contents of a DER-encoded ASN.1 element (not including // tag and length bytes) into out, and advances. The element must match the -// given tag. It returns true on success and false on error. +// given tag. It reports whether the read was successful. func (s *String) ReadASN1Bytes(out *[]byte, tag asn1.Tag) bool { return s.ReadASN1((*String)(out), tag) } // ReadASN1 reads the contents of a DER-encoded ASN.1 element (not including // tag and length bytes) into out, and advances. The element must match the -// given tag. It returns true on success and false on error. +// given tag. It reports whether the read was successful. // // Tags greater than 30 are not supported (i.e. low-tag-number format only). func (s *String) ReadASN1(out *String, tag asn1.Tag) bool { @@ -509,7 +526,7 @@ func (s *String) ReadASN1(out *String, tag asn1.Tag) bool { // ReadASN1Element reads the contents of a DER-encoded ASN.1 element (including // tag and length bytes) into out, and advances. The element must match the -// given tag. It returns true on success and false on error. +// given tag. It reports whether the read was successful. // // Tags greater than 30 are not supported (i.e. low-tag-number format only). func (s *String) ReadASN1Element(out *String, tag asn1.Tag) bool { @@ -521,8 +538,8 @@ func (s *String) ReadASN1Element(out *String, tag asn1.Tag) bool { } // ReadAnyASN1 reads the contents of a DER-encoded ASN.1 element (not including -// tag and length bytes) into out, sets outTag to its tag, and advances. It -// returns true on success and false on error. +// tag and length bytes) into out, sets outTag to its tag, and advances. +// It reports whether the read was successful. // // Tags greater than 30 are not supported (i.e. low-tag-number format only). func (s *String) ReadAnyASN1(out *String, outTag *asn1.Tag) bool { @@ -531,14 +548,14 @@ func (s *String) ReadAnyASN1(out *String, outTag *asn1.Tag) bool { // ReadAnyASN1Element reads the contents of a DER-encoded ASN.1 element // (including tag and length bytes) into out, sets outTag to is tag, and -// advances. It returns true on success and false on error. +// advances. It reports whether the read was successful. // // Tags greater than 30 are not supported (i.e. low-tag-number format only). func (s *String) ReadAnyASN1Element(out *String, outTag *asn1.Tag) bool { return s.readASN1(out, outTag, false /* include header */) } -// PeekASN1Tag returns true if the next ASN.1 value on the string starts with +// PeekASN1Tag reports whether the next ASN.1 value on the string starts with // the given tag. func (s String) PeekASN1Tag(tag asn1.Tag) bool { if len(s) == 0 { @@ -547,7 +564,8 @@ func (s String) PeekASN1Tag(tag asn1.Tag) bool { return asn1.Tag(s[0]) == tag } -// SkipASN1 reads and discards an ASN.1 element with the given tag. +// SkipASN1 reads and discards an ASN.1 element with the given tag. It +// reports whether the operation was successful. func (s *String) SkipASN1(tag asn1.Tag) bool { var unused String return s.ReadASN1(&unused, tag) @@ -556,7 +574,7 @@ func (s *String) SkipASN1(tag asn1.Tag) bool { // ReadOptionalASN1 attempts to read the contents of a DER-encoded ASN.1 // element (not including tag and length bytes) tagged with the given tag into // out. It stores whether an element with the tag was found in outPresent, -// unless outPresent is nil. It returns true on success and false on error. +// unless outPresent is nil. It reports whether the read was successful. func (s *String) ReadOptionalASN1(out *String, outPresent *bool, tag asn1.Tag) bool { present := s.PeekASN1Tag(tag) if outPresent != nil { @@ -569,7 +587,7 @@ func (s *String) ReadOptionalASN1(out *String, outPresent *bool, tag asn1.Tag) b } // SkipOptionalASN1 advances s over an ASN.1 element with the given tag, or -// else leaves s unchanged. +// else leaves s unchanged. It reports whether the operation was successful. func (s *String) SkipOptionalASN1(tag asn1.Tag) bool { if !s.PeekASN1Tag(tag) { return true @@ -581,8 +599,8 @@ func (s *String) SkipOptionalASN1(tag asn1.Tag) bool { // ReadOptionalASN1Integer attempts to read an optional ASN.1 INTEGER // explicitly tagged with tag into out and advances. If no element with a // matching tag is present, it writes defaultValue into out instead. If out -// does not point to an integer or to a big.Int, it panics. It returns true on -// success and false on error. +// does not point to an integer or to a big.Int, it panics. It reports +// whether the read was successful. func (s *String) ReadOptionalASN1Integer(out interface{}, tag asn1.Tag, defaultValue interface{}) bool { if reflect.TypeOf(out).Kind() != reflect.Ptr { panic("out is not a pointer") @@ -619,8 +637,8 @@ func (s *String) ReadOptionalASN1Integer(out interface{}, tag asn1.Tag, defaultV // ReadOptionalASN1OctetString attempts to read an optional ASN.1 OCTET STRING // explicitly tagged with tag into out and advances. If no element with a -// matching tag is present, it writes defaultValue into out instead. It returns -// true on success and false on error. +// matching tag is present, it sets "out" to nil instead. It reports +// whether the read was successful. func (s *String) ReadOptionalASN1OctetString(out *[]byte, outPresent *bool, tag asn1.Tag) bool { var present bool var child String @@ -644,6 +662,7 @@ func (s *String) ReadOptionalASN1OctetString(out *[]byte, outPresent *bool, tag // ReadOptionalASN1Boolean sets *out to the value of the next ASN.1 BOOLEAN or, // if the next bytes are not an ASN.1 BOOLEAN, to the value of defaultValue. +// It reports whether the operation was successful. func (s *String) ReadOptionalASN1Boolean(out *bool, defaultValue bool) bool { var present bool var child String diff --git a/vendor/golang.org/x/crypto/cryptobyte/asn1_test.go b/vendor/golang.org/x/crypto/cryptobyte/asn1_test.go index ee6674a..9f6c952 100644 --- a/vendor/golang.org/x/crypto/cryptobyte/asn1_test.go +++ b/vendor/golang.org/x/crypto/cryptobyte/asn1_test.go @@ -149,6 +149,39 @@ func TestReadASN1IntegerSigned(t *testing.T) { } } }) + + // Repeat with the implicit-tagging functions + t.Run("WithTag", func(t *testing.T) { + for i, test := range testData64 { + tag := asn1.Tag((i * 3) % 32).ContextSpecific() + + testData := make([]byte, len(test.in)) + copy(testData, test.in) + + // Alter the tag of the test case. + testData[0] = uint8(tag) + + in := String(testData) + var out int64 + ok := in.ReadASN1Int64WithTag(&out, tag) + if !ok || out != test.out { + t.Errorf("#%d: in.ReadASN1Int64WithTag() = %v, want true; out = %d, want %d", i, ok, out, test.out) + } + + var b Builder + b.AddASN1Int64WithTag(test.out, tag) + result, err := b.Bytes() + + if err != nil { + t.Errorf("#%d: AddASN1Int64WithTag failed: %s", i, err) + continue + } + + if !bytes.Equal(result, testData) { + t.Errorf("#%d: AddASN1Int64WithTag: got %x, want %x", i, result, testData) + } + } + }) } func TestReadASN1IntegerUnsigned(t *testing.T) { diff --git a/vendor/golang.org/x/crypto/cryptobyte/string.go b/vendor/golang.org/x/crypto/cryptobyte/string.go index 7636fb9..39bf98a 100644 --- a/vendor/golang.org/x/crypto/cryptobyte/string.go +++ b/vendor/golang.org/x/crypto/cryptobyte/string.go @@ -37,8 +37,8 @@ func (s *String) Skip(n int) bool { return s.read(n) != nil } -// ReadUint8 decodes an 8-bit value into out and advances over it. It -// returns true on success and false on error. +// ReadUint8 decodes an 8-bit value into out and advances over it. +// It reports whether the read was successful. func (s *String) ReadUint8(out *uint8) bool { v := s.read(1) if v == nil { @@ -49,7 +49,7 @@ func (s *String) ReadUint8(out *uint8) bool { } // ReadUint16 decodes a big-endian, 16-bit value into out and advances over it. -// It returns true on success and false on error. +// It reports whether the read was successful. func (s *String) ReadUint16(out *uint16) bool { v := s.read(2) if v == nil { @@ -60,7 +60,7 @@ func (s *String) ReadUint16(out *uint16) bool { } // ReadUint24 decodes a big-endian, 24-bit value into out and advances over it. -// It returns true on success and false on error. +// It reports whether the read was successful. func (s *String) ReadUint24(out *uint32) bool { v := s.read(3) if v == nil { @@ -71,7 +71,7 @@ func (s *String) ReadUint24(out *uint32) bool { } // ReadUint32 decodes a big-endian, 32-bit value into out and advances over it. -// It returns true on success and false on error. +// It reports whether the read was successful. func (s *String) ReadUint32(out *uint32) bool { v := s.read(4) if v == nil { @@ -119,28 +119,27 @@ func (s *String) readLengthPrefixed(lenLen int, outChild *String) bool { } // ReadUint8LengthPrefixed reads the content of an 8-bit length-prefixed value -// into out and advances over it. It returns true on success and false on -// error. +// into out and advances over it. It reports whether the read was successful. func (s *String) ReadUint8LengthPrefixed(out *String) bool { return s.readLengthPrefixed(1, out) } // ReadUint16LengthPrefixed reads the content of a big-endian, 16-bit -// length-prefixed value into out and advances over it. It returns true on -// success and false on error. +// length-prefixed value into out and advances over it. It reports whether the +// read was successful. func (s *String) ReadUint16LengthPrefixed(out *String) bool { return s.readLengthPrefixed(2, out) } // ReadUint24LengthPrefixed reads the content of a big-endian, 24-bit -// length-prefixed value into out and advances over it. It returns true on -// success and false on error. +// length-prefixed value into out and advances over it. It reports whether +// the read was successful. func (s *String) ReadUint24LengthPrefixed(out *String) bool { return s.readLengthPrefixed(3, out) } -// ReadBytes reads n bytes into out and advances over them. It returns true on -// success and false and error. +// ReadBytes reads n bytes into out and advances over them. It reports +// whether the read was successful. func (s *String) ReadBytes(out *[]byte, n int) bool { v := s.read(n) if v == nil { @@ -150,8 +149,8 @@ func (s *String) ReadBytes(out *[]byte, n int) bool { return true } -// CopyBytes copies len(out) bytes into out and advances over them. It returns -// true on success and false on error. +// CopyBytes copies len(out) bytes into out and advances over them. It reports +// whether the copy operation was successful func (s *String) CopyBytes(out []byte) bool { n := len(out) v := s.read(n) diff --git a/vendor/golang.org/x/crypto/ocsp/ocsp.go b/vendor/golang.org/x/crypto/ocsp/ocsp.go index 589dfd3..5edc9c9 100644 --- a/vendor/golang.org/x/crypto/ocsp/ocsp.go +++ b/vendor/golang.org/x/crypto/ocsp/ocsp.go @@ -488,10 +488,6 @@ func ParseResponseForCert(bytes []byte, cert, issuer *x509.Certificate) (*Respon return nil, err } - if len(basicResp.Certificates) > 1 { - return nil, ParseError("OCSP response contains bad number of certificates") - } - if n := len(basicResp.TBSResponseData.Responses); n == 0 || cert == nil && n > 1 { return nil, ParseError("OCSP response contains bad number of responses") } @@ -544,6 +540,13 @@ func ParseResponseForCert(bytes []byte, cert, issuer *x509.Certificate) (*Respon } if len(basicResp.Certificates) > 0 { + // Responders should only send a single certificate (if they + // send any) that connects the responder's certificate to the + // original issuer. We accept responses with multiple + // certificates due to a number responders sending them[1], but + // ignore all but the first. + // + // [1] https://github.com/golang/go/issues/21527 ret.Certificate, err = x509.ParseCertificate(basicResp.Certificates[0].FullBytes) if err != nil { return nil, err diff --git a/vendor/gopkg.in/check.v1/check.go b/vendor/gopkg.in/check.v1/check.go index 137a274..de714c2 100644 --- a/vendor/gopkg.in/check.v1/check.go +++ b/vendor/gopkg.in/check.v1/check.go @@ -239,7 +239,7 @@ func (c *C) logValue(label string, value interface{}) { } } -func (c *C) logMultiLine(s string) { +func formatMultiLine(s string, quote bool) []byte { b := make([]byte, 0, len(s)*2) i := 0 n := len(s) @@ -249,14 +249,23 @@ func (c *C) logMultiLine(s string) { j++ } b = append(b, "... "...) - b = strconv.AppendQuote(b, s[i:j]) - if j < n { + if quote { + b = strconv.AppendQuote(b, s[i:j]) + } else { + b = append(b, s[i:j]...) + b = bytes.TrimSpace(b) + } + if quote && j < n { b = append(b, " +"...) } b = append(b, '\n') i = j } - c.writeLog(b) + return b +} + +func (c *C) logMultiLine(s string) { + c.writeLog(formatMultiLine(s, true)) } func isMultiLine(s string) bool { diff --git a/vendor/gopkg.in/check.v1/check_test.go b/vendor/gopkg.in/check.v1/check_test.go index 871b325..e8b0f52 100644 --- a/vendor/gopkg.in/check.v1/check_test.go +++ b/vendor/gopkg.in/check.v1/check_test.go @@ -187,8 +187,8 @@ func checkState(c *check.C, result interface{}, expected *expectedState) { log := c.GetTestLog() matched, matchError := regexp.MatchString("^"+expected.log+"$", log) if matchError != nil { - c.Errorf("Error in matching expression used in testing %s", - expected.name) + c.Errorf("Error in matching expression used in testing %s: %v", + expected.name, matchError) } else if !matched { c.Errorf("%s logged:\n----------\n%s----------\n\nExpected:\n----------\n%s\n----------", expected.name, log, expected.log) diff --git a/vendor/gopkg.in/check.v1/checkers.go b/vendor/gopkg.in/check.v1/checkers.go index 3749545..cdd7f9a 100644 --- a/vendor/gopkg.in/check.v1/checkers.go +++ b/vendor/gopkg.in/check.v1/checkers.go @@ -4,6 +4,9 @@ import ( "fmt" "reflect" "regexp" + "strings" + + "github.com/kr/pretty" ) // ----------------------------------------------------------------------- @@ -90,6 +93,10 @@ func (checker *notChecker) Info() *CheckerInfo { func (checker *notChecker) Check(params []interface{}, names []string) (result bool, error string) { result, error = checker.sub.Check(params, names) result = !result + if result { + // clear error message if the new result is true + error = "" + } return } @@ -153,6 +160,56 @@ func (checker *notNilChecker) Check(params []interface{}, names []string) (resul // ----------------------------------------------------------------------- // Equals checker. +func diffworthy(a interface{}) bool { + t := reflect.TypeOf(a) + switch t.Kind() { + case reflect.Array, reflect.Map, reflect.Slice, reflect.Struct, reflect.String, reflect.Ptr: + return true + } + return false +} + +// formatUnequal will dump the actual and expected values into a textual +// representation and return an error message containing a diff. +func formatUnequal(obtained interface{}, expected interface{}) string { + // We do not do diffs for basic types because go-check already + // shows them very cleanly. + if !diffworthy(obtained) || !diffworthy(expected) { + return "" + } + + // Handle strings, short strings are ignored (go-check formats + // them very nicely already). We do multi-line strings by + // generating two string slices and using kr.Diff to compare + // those (kr.Diff does not do string diffs by itself). + aStr, aOK := obtained.(string) + bStr, bOK := expected.(string) + if aOK && bOK { + l1 := strings.Split(aStr, "\n") + l2 := strings.Split(bStr, "\n") + // the "2" here is a bit arbitrary + if len(l1) > 2 && len(l2) > 2 { + diff := pretty.Diff(l1, l2) + return fmt.Sprintf(`String difference: +%s`, formatMultiLine(strings.Join(diff, "\n"), false)) + } + // string too short + return "" + } + + // generic diff + diff := pretty.Diff(obtained, expected) + if len(diff) == 0 { + // No diff, this happens when e.g. just struct + // pointers are different but the structs have + // identical values. + return "" + } + + return fmt.Sprintf(`Difference: +%s`, formatMultiLine(strings.Join(diff, "\n"), false)) +} + type equalsChecker struct { *CheckerInfo } @@ -175,7 +232,12 @@ func (checker *equalsChecker) Check(params []interface{}, names []string) (resul error = fmt.Sprint(v) } }() - return params[0] == params[1], "" + + result = params[0] == params[1] + if !result { + error = formatUnequal(params[0], params[1]) + } + return } // ----------------------------------------------------------------------- @@ -200,7 +262,11 @@ var DeepEquals Checker = &deepEqualsChecker{ } func (checker *deepEqualsChecker) Check(params []interface{}, names []string) (result bool, error string) { - return reflect.DeepEqual(params[0], params[1]), "" + result = reflect.DeepEqual(params[0], params[1]) + if !result { + error = formatUnequal(params[0], params[1]) + } + return } // ----------------------------------------------------------------------- diff --git a/vendor/gopkg.in/check.v1/checkers_test.go b/vendor/gopkg.in/check.v1/checkers_test.go index 5c69747..a2e87b6 100644 --- a/vendor/gopkg.in/check.v1/checkers_test.go +++ b/vendor/gopkg.in/check.v1/checkers_test.go @@ -2,9 +2,10 @@ package check_test import ( "errors" - "gopkg.in/check.v1" "reflect" "runtime" + + "gopkg.in/check.v1" ) type CheckersS struct{} @@ -77,6 +78,7 @@ func (s *CheckersS) TestNot(c *check.C) { testCheck(c, check.Not(check.IsNil), false, "", nil) testCheck(c, check.Not(check.IsNil), true, "", "a") + testCheck(c, check.Not(check.Equals), true, "", 42, 43) } type simpleStruct struct { @@ -101,11 +103,16 @@ func (s *CheckersS) TestEquals(c *check.C) { // Struct values testCheck(c, check.Equals, true, "", simpleStruct{1}, simpleStruct{1}) - testCheck(c, check.Equals, false, "", simpleStruct{1}, simpleStruct{2}) + testCheck(c, check.Equals, false, `Difference: +... i: 1 != 2 +`, simpleStruct{1}, simpleStruct{2}) - // Struct pointers + // Struct pointers, no difference in values, just pointer testCheck(c, check.Equals, false, "", &simpleStruct{1}, &simpleStruct{1}) - testCheck(c, check.Equals, false, "", &simpleStruct{1}, &simpleStruct{2}) + // Struct pointers, different pointers and different values + testCheck(c, check.Equals, false, `Difference: +... i: 1 != 2 +`, &simpleStruct{1}, &simpleStruct{2}) } func (s *CheckersS) TestDeepEquals(c *check.C) { @@ -123,15 +130,23 @@ func (s *CheckersS) TestDeepEquals(c *check.C) { // Slices testCheck(c, check.DeepEquals, true, "", []byte{1, 2}, []byte{1, 2}) - testCheck(c, check.DeepEquals, false, "", []byte{1, 2}, []byte{1, 3}) + testCheck(c, check.DeepEquals, false, `Difference: +... [1]: 2 != 3 +`, []byte{1, 2}, []byte{1, 3}) // Struct values testCheck(c, check.DeepEquals, true, "", simpleStruct{1}, simpleStruct{1}) - testCheck(c, check.DeepEquals, false, "", simpleStruct{1}, simpleStruct{2}) + testCheck(c, check.DeepEquals, false, `Difference: +... i: 1 != 2 +`, simpleStruct{1}, simpleStruct{2}) // Struct pointers testCheck(c, check.DeepEquals, true, "", &simpleStruct{1}, &simpleStruct{1}) - testCheck(c, check.DeepEquals, false, "", &simpleStruct{1}, &simpleStruct{2}) + s1 := &simpleStruct{1} + s2 := &simpleStruct{2} + testCheck(c, check.DeepEquals, false, `Difference: +... i: 1 != 2 +`, s1, s2) } func (s *CheckersS) TestHasLen(c *check.C) { diff --git a/vendor/gopkg.in/check.v1/integration_test.go b/vendor/gopkg.in/check.v1/integration_test.go new file mode 100644 index 0000000..dfcd952 --- /dev/null +++ b/vendor/gopkg.in/check.v1/integration_test.go @@ -0,0 +1,94 @@ +// Integration tests + +package check_test + +import ( + . "gopkg.in/check.v1" +) + +// ----------------------------------------------------------------------- +// Integration test suite. + +type integrationS struct{} + +var _ = Suite(&integrationS{}) + +type integrationTestHelper struct{} + +func (s *integrationTestHelper) TestMultiLineStringEqualFails(c *C) { + c.Check("foo\nbar\nbaz\nboom\n", Equals, "foo\nbaar\nbaz\nboom\n") +} + +func (s *integrationTestHelper) TestStringEqualFails(c *C) { + c.Check("foo", Equals, "bar") +} + +func (s *integrationTestHelper) TestIntEqualFails(c *C) { + c.Check(42, Equals, 43) +} + +type complexStruct struct { + r, i int +} + +func (s *integrationTestHelper) TestStructEqualFails(c *C) { + c.Check(complexStruct{1, 2}, Equals, complexStruct{3, 4}) +} + +func (s *integrationS) TestOutput(c *C) { + helper := integrationTestHelper{} + output := String{} + Run(&helper, &RunConf{Output: &output}) + c.Assert(output.value, Equals, ` +---------------------------------------------------------------------- +FAIL: integration_test.go:26: integrationTestHelper.TestIntEqualFails + +integration_test.go:27: + c.Check(42, Equals, 43) +... obtained int = 42 +... expected int = 43 + + +---------------------------------------------------------------------- +FAIL: integration_test.go:18: integrationTestHelper.TestMultiLineStringEqualFails + +integration_test.go:19: + c.Check("foo\nbar\nbaz\nboom\n", Equals, "foo\nbaar\nbaz\nboom\n") +... obtained string = "" + +... "foo\n" + +... "bar\n" + +... "baz\n" + +... "boom\n" +... expected string = "" + +... "foo\n" + +... "baar\n" + +... "baz\n" + +... "boom\n" +... String difference: +... [1]: "bar" != "baar" + + + +---------------------------------------------------------------------- +FAIL: integration_test.go:22: integrationTestHelper.TestStringEqualFails + +integration_test.go:23: + c.Check("foo", Equals, "bar") +... obtained string = "foo" +... expected string = "bar" + + +---------------------------------------------------------------------- +FAIL: integration_test.go:34: integrationTestHelper.TestStructEqualFails + +integration_test.go:35: + c.Check(complexStruct{1, 2}, Equals, complexStruct{3, 4}) +... obtained check_test.complexStruct = check_test.complexStruct{r:1, i:2} +... expected check_test.complexStruct = check_test.complexStruct{r:3, i:4} +... Difference: +... r: 1 != 3 +... i: 2 != 4 + + +`) +} diff --git a/vendor/novit.nc/direktil/pkg/cas/dir-store.go b/vendor/novit.nc/direktil/pkg/cas/dir-store.go index ed7c8df..ac50dd3 100644 --- a/vendor/novit.nc/direktil/pkg/cas/dir-store.go +++ b/vendor/novit.nc/direktil/pkg/cas/dir-store.go @@ -45,8 +45,11 @@ func (s *DirStore) GetOrCreate(tag, item string, create func(io.Writer) error) ( return } + partFile := fullPath + ".part" + os.Remove(partFile) + var out *os.File - out, err = os.OpenFile(fullPath+".part", os.O_CREATE|os.O_TRUNC|os.O_WRONLY|os.O_EXCL, 0600) + out, err = os.OpenFile(partFile, os.O_CREATE|os.O_TRUNC|os.O_WRONLY|os.O_EXCL, 0600) if err != nil { return } diff --git a/vendor/novit.nc/direktil/pkg/clustersconfig/clustersconfig.go b/vendor/novit.nc/direktil/pkg/clustersconfig/clustersconfig.go index df013d8..f84c11a 100644 --- a/vendor/novit.nc/direktil/pkg/clustersconfig/clustersconfig.go +++ b/vendor/novit.nc/direktil/pkg/clustersconfig/clustersconfig.go @@ -16,13 +16,14 @@ type Config struct { Groups []*Group Clusters []*Cluster Configs []*Template - StaticPods []*Template `yaml:"static_pods"` + StaticPods []*Template `yaml:"static_pods"` + Addons map[string][]*Template SSLConfig string `yaml:"ssl_config"` CertRequests []*CertRequest `yaml:"cert_requests"` } func FromBytes(data []byte) (*Config, error) { - config := &Config{} + config := &Config{Addons: make(map[string][]*Template)} if err := yaml.Unmarshal(data, config); err != nil { return nil, err } @@ -192,6 +193,7 @@ type Vars map[string]interface{} type Cluster struct { Name string Domain string + Addons string Subnets struct { Services string Pods string diff --git a/vendor/novit.nc/direktil/pkg/clustersconfig/dir.go b/vendor/novit.nc/direktil/pkg/clustersconfig/dir.go index 8049065..06a643d 100644 --- a/vendor/novit.nc/direktil/pkg/clustersconfig/dir.go +++ b/vendor/novit.nc/direktil/pkg/clustersconfig/dir.go @@ -11,7 +11,7 @@ import ( ) func FromDir(dirPath string) (*Config, error) { - config := &Config{} + config := &Config{Addons: make(map[string][]*Template)} store := dirStore{dirPath} load := func(dir, name string, out interface{}) error { @@ -95,6 +95,23 @@ func FromDir(dirPath string) (*Config, error) { return nil, err } + { + addonSets, err := store.listDir("addons") + if err != nil { + return nil, err + } + + for _, addonSet := range addonSets { + templates := make([]*Template, 0) + if err = loadTemplates(path.Join("addons", addonSet), &templates); err != nil { + return nil, err + } + + config.Addons[addonSet] = templates + } + } + + // load SSL configuration if ba, err := ioutil.ReadFile(filepath.Join(dirPath, "ssl-config.json")); err == nil { config.SSLConfig = string(ba) @@ -121,6 +138,32 @@ type dirStore struct { path string } +// listDir +func (b *dirStore) listDir(prefix string) (subDirs []string, err error) { + entries, err := ioutil.ReadDir(filepath.Join(b.path, prefix)) + if err != nil { + return + } + + subDirs = make([]string, 0, len(entries)) + + for _, entry := range entries { + if !entry.IsDir() { + continue + } + + name := entry.Name() + + if len(name) == 0 || name[0] == '.' { + continue + } + + subDirs = append(subDirs, name) + } + + return +} + // Names is part of the kvStore interface func (b *dirStore) List(prefix string) ([]string, error) { files, err := filepath.Glob(filepath.Join(b.path, filepath.Join(path.Split(prefix)), "*.yaml")) diff --git a/vendor/novit.nc/direktil/pkg/config/config.go b/vendor/novit.nc/direktil/pkg/config/config.go index ca246db..dc9a902 100644 --- a/vendor/novit.nc/direktil/pkg/config/config.go +++ b/vendor/novit.nc/direktil/pkg/config/config.go @@ -2,12 +2,54 @@ package config import ( "fmt" - "io/ioutil" + "io" "os" yaml "gopkg.in/yaml.v2" ) +// Load a config from a file. +func Load(file string) (config *Config, err error) { + f, err := os.Open(file) + if err != nil { + return + } + + defer f.Close() + + config, err = Read(f) + if err != nil { + return nil, fmt.Errorf("failed to parse %s: %v", file, err) + } + + return +} + +// Read a config from a reader. +func Read(reader io.Reader) (config *Config, err error) { + config = &Config{} + + err = yaml.NewDecoder(reader).Decode(config) + + if err != nil { + return nil, err + } + + return +} + +// Parse the config in data. +func Parse(data []byte) (config *Config, err error) { + config = &Config{} + + err = yaml.Unmarshal(data, config) + if err != nil { + return nil, err + } + + return +} + // Config represent this system's configuration type Config struct { Vars []VarDefault @@ -83,19 +125,3 @@ type NetworkDef struct { Optional bool Script string } - -func Load(file string) (config *Config, err error) { - config = &Config{} - - configData, err := ioutil.ReadFile(file) - if err != nil { - return nil, fmt.Errorf("failed to read %s: %v", file, err) - } - - err = yaml.Unmarshal(configData, config) - if err != nil { - return nil, fmt.Errorf("failed to parse %s: %v", file, err) - } - - return -} diff --git a/vendor/vgo.list b/vendor/vgo.list index 3f48ba8..a76ca07 100644 --- a/vendor/vgo.list +++ b/vendor/vgo.list @@ -1,6 +1,6 @@ # github.com/cavaliercoder/go-cpio v0.0.0-20180626203310-925f9528c45e github.com/cavaliercoder/go-cpio -# github.com/cloudflare/cfssl v0.0.0-20180530085446-275fb308ac70 +# github.com/cloudflare/cfssl v0.0.0-20180705210102-ff56ab5eb62a github.com/cloudflare/cfssl/auth github.com/cloudflare/cfssl/certdb github.com/cloudflare/cfssl/config @@ -24,33 +24,38 @@ github.com/golang/protobuf/ptypes github.com/golang/protobuf/ptypes/any github.com/golang/protobuf/ptypes/duration github.com/golang/protobuf/ptypes/timestamp -# github.com/google/certificate-transparency-go v1.0.19 +# github.com/google/certificate-transparency-go v1.0.20 github.com/google/certificate-transparency-go github.com/google/certificate-transparency-go/asn1 github.com/google/certificate-transparency-go/client github.com/google/certificate-transparency-go/client/configpb +github.com/google/certificate-transparency-go/gossip/minimal/x509ext github.com/google/certificate-transparency-go/jsonclient github.com/google/certificate-transparency-go/testdata github.com/google/certificate-transparency-go/tls github.com/google/certificate-transparency-go/x509 github.com/google/certificate-transparency-go/x509/pkix github.com/google/certificate-transparency-go/x509util -# golang.org/x/crypto v0.0.0-20180214000028-650f4a345ab4 +# github.com/kr/pretty v0.1.0 +github.com/kr/pretty +# github.com/kr/text v0.1.0 +github.com/kr/text +# golang.org/x/crypto v0.0.0-20180621125126-a49355c7e3f8 golang.org/x/crypto/cryptobyte golang.org/x/crypto/cryptobyte/asn1 golang.org/x/crypto/ocsp golang.org/x/crypto/pkcs12 golang.org/x/crypto/pkcs12/internal/rc2 -# golang.org/x/net v0.0.0-20180208041118-f5dfe339be1d +# golang.org/x/net v0.0.0-20180706051357-32a936f46389 golang.org/x/net/context golang.org/x/net/context/ctxhttp # golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f golang.org/x/sync/errgroup -# gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 +# gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 gopkg.in/check.v1 # gopkg.in/yaml.v2 v2.2.1 gopkg.in/yaml.v2 -# novit.nc/direktil/pkg v0.0.0-20180619202319-3b512e61055e +# novit.nc/direktil/pkg v0.0.0-20180707011528-e82b59c0324d novit.nc/direktil/pkg/cas novit.nc/direktil/pkg/clustersconfig novit.nc/direktil/pkg/config