diff --git a/glide.lock b/glide.lock
index 0d6e387..8660567 100644
--- a/glide.lock
+++ b/glide.lock
@@ -1,8 +1,14 @@
-hash: 90db837f2d27de645d9f48fa1be54b4f9d83f0cb9343ce98fa61e1b55b2828b5
-updated: 2017-01-19T17:18:33.464668206-05:00
+hash: c4cfd3ace8e3926093aacecfa0f22fbeb5b2a7cb53e0b12a48b5108f6c83d9b8
+updated: 2017-06-24T14:24:17.116476656-04:00
imports:
+- name: github.com/Sirupsen/logrus
+ version: 202f25545ea4cf9b191ff7f846df5d87c9382c2b
- name: golang.org/x/crypto
- version: b8a2a83acfe6e6770b75de42d5ff4c67596675c0
+ version: adbae1b6b6fb4b02448a0fc0dbbc9ba2b95b294d
subpackages:
- ripemd160
+- name: golang.org/x/sys
+ version: c23410a886927bab8ca5e80b08af6a56faeb330d
+ subpackages:
+ - unix
testImports: []
diff --git a/glide.yaml b/glide.yaml
index b20c029..ed19021 100644
--- a/glide.yaml
+++ b/glide.yaml
@@ -1,8 +1,10 @@
package: github.com/vbatts/go-mtree
+description: File systems verification utility and library, in likeness of mtree(8)
homepage: https://github.com/vbatts/go-mtree
license: BSD-3-Clause
-description: File systems verification utility and library, in likeness of mtree(8)
import:
- package: golang.org/x/crypto
subpackages:
- ripemd160
+- package: github.com/Sirupsen/logrus
+ version: ^1.0.0
diff --git a/vendor/github.com/Sirupsen/logrus/.gitignore b/vendor/github.com/Sirupsen/logrus/.gitignore
new file mode 100644
index 0000000..66be63a
--- /dev/null
+++ b/vendor/github.com/Sirupsen/logrus/.gitignore
@@ -0,0 +1 @@
+logrus
diff --git a/vendor/github.com/Sirupsen/logrus/.travis.yml b/vendor/github.com/Sirupsen/logrus/.travis.yml
new file mode 100644
index 0000000..924f3c4
--- /dev/null
+++ b/vendor/github.com/Sirupsen/logrus/.travis.yml
@@ -0,0 +1,13 @@
+language: go
+go:
+ - 1.6.x
+ - 1.7.x
+ - 1.8.x
+ - tip
+env:
+ - GOMAXPROCS=4 GORACE=halt_on_error=1
+install:
+ - go get github.com/stretchr/testify/assert
+script:
+ - go test -race -v .
+ - cd hooks/null && go test -race -v .
diff --git a/vendor/github.com/Sirupsen/logrus/CHANGELOG.md b/vendor/github.com/Sirupsen/logrus/CHANGELOG.md
new file mode 100644
index 0000000..63d415e
--- /dev/null
+++ b/vendor/github.com/Sirupsen/logrus/CHANGELOG.md
@@ -0,0 +1,100 @@
+# 1.0.0
+
+* Officially changed name to lower-case
+* bug: colors on Windows 10 (#541)
+* bug: fix race in accessing level (#512)
+
+# 0.11.5
+
+* feature: add writer and writerlevel to entry (#372)
+
+# 0.11.4
+
+* bug: fix undefined variable on solaris (#493)
+
+# 0.11.3
+
+* formatter: configure quoting of empty values (#484)
+* formatter: configure quoting character (default is `"`) (#484)
+* bug: fix not importing io correctly in non-linux environments (#481)
+
+# 0.11.2
+
+* bug: fix windows terminal detection (#476)
+
+# 0.11.1
+
+* bug: fix tty detection with custom out (#471)
+
+# 0.11.0
+
+* performance: Use bufferpool to allocate (#370)
+* terminal: terminal detection for app-engine (#343)
+* feature: exit handler (#375)
+
+# 0.10.0
+
+* feature: Add a test hook (#180)
+* feature: `ParseLevel` is now case-insensitive (#326)
+* feature: `FieldLogger` interface that generalizes `Logger` and `Entry` (#308)
+* performance: avoid re-allocations on `WithFields` (#335)
+
+# 0.9.0
+
+* logrus/text_formatter: don't emit empty msg
+* logrus/hooks/airbrake: move out of main repository
+* logrus/hooks/sentry: move out of main repository
+* logrus/hooks/papertrail: move out of main repository
+* logrus/hooks/bugsnag: move out of main repository
+* logrus/core: run tests with `-race`
+* logrus/core: detect TTY based on `stderr`
+* logrus/core: support `WithError` on logger
+* logrus/core: Solaris support
+
+# 0.8.7
+
+* logrus/core: fix possible race (#216)
+* logrus/doc: small typo fixes and doc improvements
+
+
+# 0.8.6
+
+* hooks/raven: allow passing an initialized client
+
+# 0.8.5
+
+* logrus/core: revert #208
+
+# 0.8.4
+
+* formatter/text: fix data race (#218)
+
+# 0.8.3
+
+* logrus/core: fix entry log level (#208)
+* logrus/core: improve performance of text formatter by 40%
+* logrus/core: expose `LevelHooks` type
+* logrus/core: add support for DragonflyBSD and NetBSD
+* formatter/text: print structs more verbosely
+
+# 0.8.2
+
+* logrus: fix more Fatal family functions
+
+# 0.8.1
+
+* logrus: fix not exiting on `Fatalf` and `Fatalln`
+
+# 0.8.0
+
+* logrus: defaults to stderr instead of stdout
+* hooks/sentry: add special field for `*http.Request`
+* formatter/text: ignore Windows for colors
+
+# 0.7.3
+
+* formatter/\*: allow configuration of timestamp layout
+
+# 0.7.2
+
+* formatter/text: Add configuration option for time format (#158)
diff --git a/vendor/github.com/Sirupsen/logrus/LICENSE b/vendor/github.com/Sirupsen/logrus/LICENSE
new file mode 100644
index 0000000..f090cb4
--- /dev/null
+++ b/vendor/github.com/Sirupsen/logrus/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2014 Simon Eskildsen
+
+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/Sirupsen/logrus/README.md b/vendor/github.com/Sirupsen/logrus/README.md
new file mode 100644
index 0000000..cbe8b69
--- /dev/null
+++ b/vendor/github.com/Sirupsen/logrus/README.md
@@ -0,0 +1,501 @@
+# Logrus [![Build Status](https://travis-ci.org/sirupsen/logrus.svg?branch=master)](https://travis-ci.org/sirupsen/logrus) [![GoDoc](https://godoc.org/github.com/sirupsen/logrus?status.svg)](https://godoc.org/github.com/sirupsen/logrus)
+
+Logrus is a structured logger for Go (golang), completely API compatible with
+the standard library logger. [Godoc][godoc]. **Please note the Logrus API is not
+yet stable (pre 1.0). Logrus itself is completely stable and has been used in
+many large deployments. The core API is unlikely to change much but please
+version control your Logrus to make sure you aren't fetching latest `master` on
+every build.**
+
+**Seeing weird case-sensitive problems?** Unfortunately, the author failed to
+realize the consequences of renaming to lower-case. Due to the Go package
+environment, this caused issues. Regretfully, there's no turning back now.
+Everything using `logrus` will need to use the lower-case:
+`github.com/sirupsen/logrus`. Any package that isn't, should be changed.
+
+I am terribly sorry for this inconvenience. Logrus strives hard for backwards
+compatibility, and the author failed to realize the cascading consequences of
+such a name-change. To fix Glide, see [these
+comments](https://github.com/sirupsen/logrus/issues/553#issuecomment-306591437).
+
+Nicely color-coded in development (when a TTY is attached, otherwise just
+plain text):
+
+![Colored](http://i.imgur.com/PY7qMwd.png)
+
+With `log.SetFormatter(&log.JSONFormatter{})`, for easy parsing by logstash
+or Splunk:
+
+```json
+{"animal":"walrus","level":"info","msg":"A group of walrus emerges from the
+ocean","size":10,"time":"2014-03-10 19:57:38.562264131 -0400 EDT"}
+
+{"level":"warning","msg":"The group's number increased tremendously!",
+"number":122,"omg":true,"time":"2014-03-10 19:57:38.562471297 -0400 EDT"}
+
+{"animal":"walrus","level":"info","msg":"A giant walrus appears!",
+"size":10,"time":"2014-03-10 19:57:38.562500591 -0400 EDT"}
+
+{"animal":"walrus","level":"info","msg":"Tremendously sized cow enters the ocean.",
+"size":9,"time":"2014-03-10 19:57:38.562527896 -0400 EDT"}
+
+{"level":"fatal","msg":"The ice breaks!","number":100,"omg":true,
+"time":"2014-03-10 19:57:38.562543128 -0400 EDT"}
+```
+
+With the default `log.SetFormatter(&log.TextFormatter{})` when a TTY is not
+attached, the output is compatible with the
+[logfmt](http://godoc.org/github.com/kr/logfmt) format:
+
+```text
+time="2015-03-26T01:27:38-04:00" level=debug msg="Started observing beach" animal=walrus number=8
+time="2015-03-26T01:27:38-04:00" level=info msg="A group of walrus emerges from the ocean" animal=walrus size=10
+time="2015-03-26T01:27:38-04:00" level=warning msg="The group's number increased tremendously!" number=122 omg=true
+time="2015-03-26T01:27:38-04:00" level=debug msg="Temperature changes" temperature=-4
+time="2015-03-26T01:27:38-04:00" level=panic msg="It's over 9000!" animal=orca size=9009
+time="2015-03-26T01:27:38-04:00" level=fatal msg="The ice breaks!" err=&{0x2082280c0 map[animal:orca size:9009] 2015-03-26 01:27:38.441574009 -0400 EDT panic It's over 9000!} number=100 omg=true
+exit status 1
+```
+
+#### Case-sensitivity
+
+The organization's name was changed to lower-case--and this will not be changed
+back. If you are getting import conflicts due to case sensitivity, please use
+the lower-case import: `github.com/sirupsen/logrus`.
+
+#### Example
+
+The simplest way to use Logrus is simply the package-level exported logger:
+
+```go
+package main
+
+import (
+ log "github.com/sirupsen/logrus"
+)
+
+func main() {
+ log.WithFields(log.Fields{
+ "animal": "walrus",
+ }).Info("A walrus appears")
+}
+```
+
+Note that it's completely api-compatible with the stdlib logger, so you can
+replace your `log` imports everywhere with `log "github.com/sirupsen/logrus"`
+and you'll now have the flexibility of Logrus. You can customize it all you
+want:
+
+```go
+package main
+
+import (
+ "os"
+ log "github.com/sirupsen/logrus"
+)
+
+func init() {
+ // Log as JSON instead of the default ASCII formatter.
+ log.SetFormatter(&log.JSONFormatter{})
+
+ // Output to stdout instead of the default stderr
+ // Can be any io.Writer, see below for File example
+ log.SetOutput(os.Stdout)
+
+ // Only log the warning severity or above.
+ log.SetLevel(log.WarnLevel)
+}
+
+func main() {
+ log.WithFields(log.Fields{
+ "animal": "walrus",
+ "size": 10,
+ }).Info("A group of walrus emerges from the ocean")
+
+ log.WithFields(log.Fields{
+ "omg": true,
+ "number": 122,
+ }).Warn("The group's number increased tremendously!")
+
+ log.WithFields(log.Fields{
+ "omg": true,
+ "number": 100,
+ }).Fatal("The ice breaks!")
+
+ // A common pattern is to re-use fields between logging statements by re-using
+ // the logrus.Entry returned from WithFields()
+ contextLogger := log.WithFields(log.Fields{
+ "common": "this is a common field",
+ "other": "I also should be logged always",
+ })
+
+ contextLogger.Info("I'll be logged with common and other field")
+ contextLogger.Info("Me too")
+}
+```
+
+For more advanced usage such as logging to multiple locations from the same
+application, you can also create an instance of the `logrus` Logger:
+
+```go
+package main
+
+import (
+ "os"
+ "github.com/sirupsen/logrus"
+)
+
+// Create a new instance of the logger. You can have any number of instances.
+var log = logrus.New()
+
+func main() {
+ // The API for setting attributes is a little different than the package level
+ // exported logger. See Godoc.
+ log.Out = os.Stdout
+
+ // You could set this to any `io.Writer` such as a file
+ // file, err := os.OpenFile("logrus.log", os.O_CREATE|os.O_WRONLY, 0666)
+ // if err == nil {
+ // log.Out = file
+ // } else {
+ // log.Info("Failed to log to file, using default stderr")
+ // }
+
+ log.WithFields(logrus.Fields{
+ "animal": "walrus",
+ "size": 10,
+ }).Info("A group of walrus emerges from the ocean")
+}
+```
+
+#### Fields
+
+Logrus encourages careful, structured logging through logging fields instead of
+long, unparseable error messages. For example, instead of: `log.Fatalf("Failed
+to send event %s to topic %s with key %d")`, you should log the much more
+discoverable:
+
+```go
+log.WithFields(log.Fields{
+ "event": event,
+ "topic": topic,
+ "key": key,
+}).Fatal("Failed to send event")
+```
+
+We've found this API forces you to think about logging in a way that produces
+much more useful logging messages. We've been in countless situations where just
+a single added field to a log statement that was already there would've saved us
+hours. The `WithFields` call is optional.
+
+In general, with Logrus using any of the `printf`-family functions should be
+seen as a hint you should add a field, however, you can still use the
+`printf`-family functions with Logrus.
+
+#### Default Fields
+
+Often it's helpful to have fields _always_ attached to log statements in an
+application or parts of one. For example, you may want to always log the
+`request_id` and `user_ip` in the context of a request. Instead of writing
+`log.WithFields(log.Fields{"request_id": request_id, "user_ip": user_ip})` on
+every line, you can create a `logrus.Entry` to pass around instead:
+
+```go
+requestLogger := log.WithFields(log.Fields{"request_id": request_id, "user_ip": user_ip})
+requestLogger.Info("something happened on that request") # will log request_id and user_ip
+requestLogger.Warn("something not great happened")
+```
+
+#### Hooks
+
+You can add hooks for logging levels. For example to send errors to an exception
+tracking service on `Error`, `Fatal` and `Panic`, info to StatsD or log to
+multiple places simultaneously, e.g. syslog.
+
+Logrus comes with [built-in hooks](hooks/). Add those, or your custom hook, in
+`init`:
+
+```go
+import (
+ log "github.com/sirupsen/logrus"
+ "gopkg.in/gemnasium/logrus-airbrake-hook.v2" // the package is named "aibrake"
+ logrus_syslog "github.com/sirupsen/logrus/hooks/syslog"
+ "log/syslog"
+)
+
+func init() {
+
+ // Use the Airbrake hook to report errors that have Error severity or above to
+ // an exception tracker. You can create custom hooks, see the Hooks section.
+ log.AddHook(airbrake.NewHook(123, "xyz", "production"))
+
+ hook, err := logrus_syslog.NewSyslogHook("udp", "localhost:514", syslog.LOG_INFO, "")
+ if err != nil {
+ log.Error("Unable to connect to local syslog daemon")
+ } else {
+ log.AddHook(hook)
+ }
+}
+```
+Note: Syslog hook also support connecting to local syslog (Ex. "/dev/log" or "/var/run/syslog" or "/var/run/log"). For the detail, please check the [syslog hook README](hooks/syslog/README.md).
+
+| Hook | Description |
+| ----- | ----------- |
+| [Airbrake "legacy"](https://github.com/gemnasium/logrus-airbrake-legacy-hook) | Send errors to an exception tracking service compatible with the Airbrake API V2. Uses [`airbrake-go`](https://github.com/tobi/airbrake-go) behind the scenes. |
+| [Airbrake](https://github.com/gemnasium/logrus-airbrake-hook) | Send errors to the Airbrake API V3. Uses the official [`gobrake`](https://github.com/airbrake/gobrake) behind the scenes. |
+| [Amazon Kinesis](https://github.com/evalphobia/logrus_kinesis) | Hook for logging to [Amazon Kinesis](https://aws.amazon.com/kinesis/) |
+| [Amqp-Hook](https://github.com/vladoatanasov/logrus_amqp) | Hook for logging to Amqp broker (Like RabbitMQ) |
+| [Bugsnag](https://github.com/Shopify/logrus-bugsnag/blob/master/bugsnag.go) | Send errors to the Bugsnag exception tracking service. |
+| [DeferPanic](https://github.com/deferpanic/dp-logrus) | Hook for logging to DeferPanic |
+| [Discordrus](https://github.com/kz/discordrus) | Hook for logging to [Discord](https://discordapp.com/) |
+| [ElasticSearch](https://github.com/sohlich/elogrus) | Hook for logging to ElasticSearch|
+| [Firehose](https://github.com/beaubrewer/logrus_firehose) | Hook for logging to [Amazon Firehose](https://aws.amazon.com/kinesis/firehose/)
+| [Fluentd](https://github.com/evalphobia/logrus_fluent) | Hook for logging to fluentd |
+| [Go-Slack](https://github.com/multiplay/go-slack) | Hook for logging to [Slack](https://slack.com) |
+| [Graylog](https://github.com/gemnasium/logrus-graylog-hook) | Hook for logging to [Graylog](http://graylog2.org/) |
+| [Hiprus](https://github.com/nubo/hiprus) | Send errors to a channel in hipchat. |
+| [Honeybadger](https://github.com/agonzalezro/logrus_honeybadger) | Hook for sending exceptions to Honeybadger |
+| [InfluxDB](https://github.com/Abramovic/logrus_influxdb) | Hook for logging to influxdb |
+| [Influxus](http://github.com/vlad-doru/influxus) | Hook for concurrently logging to [InfluxDB](http://influxdata.com/) |
+| [Journalhook](https://github.com/wercker/journalhook) | Hook for logging to `systemd-journald` |
+| [KafkaLogrus](https://github.com/goibibo/KafkaLogrus) | Hook for logging to kafka |
+| [LFShook](https://github.com/rifflock/lfshook) | Hook for logging to the local filesystem |
+| [Logentries](https://github.com/jcftang/logentriesrus) | Hook for logging to [Logentries](https://logentries.com/) |
+| [Logentrus](https://github.com/puddingfactory/logentrus) | Hook for logging to [Logentries](https://logentries.com/) |
+| [Logmatic.io](https://github.com/logmatic/logmatic-go) | Hook for logging to [Logmatic.io](http://logmatic.io/) |
+| [Logrusly](https://github.com/sebest/logrusly) | Send logs to [Loggly](https://www.loggly.com/) |
+| [Logstash](https://github.com/bshuster-repo/logrus-logstash-hook) | Hook for logging to [Logstash](https://www.elastic.co/products/logstash) |
+| [Mail](https://github.com/zbindenren/logrus_mail) | Hook for sending exceptions via mail |
+| [Mongodb](https://github.com/weekface/mgorus) | Hook for logging to mongodb |
+| [NATS-Hook](https://github.com/rybit/nats_logrus_hook) | Hook for logging to [NATS](https://nats.io) |
+| [Octokit](https://github.com/dorajistyle/logrus-octokit-hook) | Hook for logging to github via octokit |
+| [Papertrail](https://github.com/polds/logrus-papertrail-hook) | Send errors to the [Papertrail](https://papertrailapp.com) hosted logging service via UDP. |
+| [PostgreSQL](https://github.com/gemnasium/logrus-postgresql-hook) | Send logs to [PostgreSQL](http://postgresql.org) |
+| [Pushover](https://github.com/toorop/logrus_pushover) | Send error via [Pushover](https://pushover.net) |
+| [Raygun](https://github.com/squirkle/logrus-raygun-hook) | Hook for logging to [Raygun.io](http://raygun.io/) |
+| [Redis-Hook](https://github.com/rogierlommers/logrus-redis-hook) | Hook for logging to a ELK stack (through Redis) |
+| [Rollrus](https://github.com/heroku/rollrus) | Hook for sending errors to rollbar |
+| [Scribe](https://github.com/sagar8192/logrus-scribe-hook) | Hook for logging to [Scribe](https://github.com/facebookarchive/scribe)|
+| [Sentry](https://github.com/evalphobia/logrus_sentry) | Send errors to the Sentry error logging and aggregation service. |
+| [Slackrus](https://github.com/johntdyer/slackrus) | Hook for Slack chat. |
+| [Stackdriver](https://github.com/knq/sdhook) | Hook for logging to [Google Stackdriver](https://cloud.google.com/logging/) |
+| [Sumorus](https://github.com/doublefree/sumorus) | Hook for logging to [SumoLogic](https://www.sumologic.com/)|
+| [Syslog](https://github.com/Sirupsen/logrus/blob/master/hooks/syslog/syslog.go) | Send errors to remote syslog server. Uses standard library `log/syslog` behind the scenes. |
+| [Syslog TLS](https://github.com/shinji62/logrus-syslog-ng) | Send errors to remote syslog server with TLS support. |
+| [TraceView](https://github.com/evalphobia/logrus_appneta) | Hook for logging to [AppNeta TraceView](https://www.appneta.com/products/traceview/) |
+| [Typetalk](https://github.com/dragon3/logrus-typetalk-hook) | Hook for logging to [Typetalk](https://www.typetalk.in/) |
+| [logz.io](https://github.com/ripcurld00d/logrus-logzio-hook) | Hook for logging to [logz.io](https://logz.io), a Log as a Service using Logstash |
+| [SQS-Hook](https://github.com/tsarpaul/logrus_sqs) | Hook for logging to [Amazon Simple Queue Service (SQS)](https://aws.amazon.com/sqs/) |
+
+#### Level logging
+
+Logrus has six logging levels: Debug, Info, Warning, Error, Fatal and Panic.
+
+```go
+log.Debug("Useful debugging information.")
+log.Info("Something noteworthy happened!")
+log.Warn("You should probably take a look at this.")
+log.Error("Something failed but I'm not quitting.")
+// Calls os.Exit(1) after logging
+log.Fatal("Bye.")
+// Calls panic() after logging
+log.Panic("I'm bailing.")
+```
+
+You can set the logging level on a `Logger`, then it will only log entries with
+that severity or anything above it:
+
+```go
+// Will log anything that is info or above (warn, error, fatal, panic). Default.
+log.SetLevel(log.InfoLevel)
+```
+
+It may be useful to set `log.Level = logrus.DebugLevel` in a debug or verbose
+environment if your application has that.
+
+#### Entries
+
+Besides the fields added with `WithField` or `WithFields` some fields are
+automatically added to all logging events:
+
+1. `time`. The timestamp when the entry was created.
+2. `msg`. The logging message passed to `{Info,Warn,Error,Fatal,Panic}` after
+ the `AddFields` call. E.g. `Failed to send event.`
+3. `level`. The logging level. E.g. `info`.
+
+#### Environments
+
+Logrus has no notion of environment.
+
+If you wish for hooks and formatters to only be used in specific environments,
+you should handle that yourself. For example, if your application has a global
+variable `Environment`, which is a string representation of the environment you
+could do:
+
+```go
+import (
+ log "github.com/sirupsen/logrus"
+)
+
+init() {
+ // do something here to set environment depending on an environment variable
+ // or command-line flag
+ if Environment == "production" {
+ log.SetFormatter(&log.JSONFormatter{})
+ } else {
+ // The TextFormatter is default, you don't actually have to do this.
+ log.SetFormatter(&log.TextFormatter{})
+ }
+}
+```
+
+This configuration is how `logrus` was intended to be used, but JSON in
+production is mostly only useful if you do log aggregation with tools like
+Splunk or Logstash.
+
+#### Formatters
+
+The built-in logging formatters are:
+
+* `logrus.TextFormatter`. Logs the event in colors if stdout is a tty, otherwise
+ without colors.
+ * *Note:* to force colored output when there is no TTY, set the `ForceColors`
+ field to `true`. To force no colored output even if there is a TTY set the
+ `DisableColors` field to `true`. For Windows, see
+ [github.com/mattn/go-colorable](https://github.com/mattn/go-colorable).
+ * All options are listed in the [generated docs](https://godoc.org/github.com/sirupsen/logrus#TextFormatter).
+* `logrus.JSONFormatter`. Logs fields as JSON.
+ * All options are listed in the [generated docs](https://godoc.org/github.com/sirupsen/logrus#JSONFormatter).
+
+Third party logging formatters:
+
+* [`logstash`](https://github.com/bshuster-repo/logrus-logstash-hook). Logs fields as [Logstash](http://logstash.net) Events.
+* [`prefixed`](https://github.com/x-cray/logrus-prefixed-formatter). Displays log entry source along with alternative layout.
+* [`zalgo`](https://github.com/aybabtme/logzalgo). Invoking the P͉̫o̳̼̊w̖͈̰͎e̬͔̭͂r͚̼̹̲ ̫͓͉̳͈ō̠͕͖̚f̝͍̠ ͕̲̞͖͑Z̖̫̤̫ͪa͉̬͈̗l͖͎g̳̥o̰̥̅!̣͔̲̻͊̄ ̙̘̦̹̦.
+
+You can define your formatter by implementing the `Formatter` interface,
+requiring a `Format` method. `Format` takes an `*Entry`. `entry.Data` is a
+`Fields` type (`map[string]interface{}`) with all your fields as well as the
+default ones (see Entries section above):
+
+```go
+type MyJSONFormatter struct {
+}
+
+log.SetFormatter(new(MyJSONFormatter))
+
+func (f *MyJSONFormatter) Format(entry *Entry) ([]byte, error) {
+ // Note this doesn't include Time, Level and Message which are available on
+ // the Entry. Consult `godoc` on information about those fields or read the
+ // source of the official loggers.
+ serialized, err := json.Marshal(entry.Data)
+ if err != nil {
+ return nil, fmt.Errorf("Failed to marshal fields to JSON, %v", err)
+ }
+ return append(serialized, '\n'), nil
+}
+```
+
+#### Logger as an `io.Writer`
+
+Logrus can be transformed into an `io.Writer`. That writer is the end of an `io.Pipe` and it is your responsibility to close it.
+
+```go
+w := logger.Writer()
+defer w.Close()
+
+srv := http.Server{
+ // create a stdlib log.Logger that writes to
+ // logrus.Logger.
+ ErrorLog: log.New(w, "", 0),
+}
+```
+
+Each line written to that writer will be printed the usual way, using formatters
+and hooks. The level for those entries is `info`.
+
+This means that we can override the standard library logger easily:
+
+```go
+logger := logrus.New()
+logger.Formatter = &logrus.JSONFormatter{}
+
+// Use logrus for standard log output
+// Note that `log` here references stdlib's log
+// Not logrus imported under the name `log`.
+log.SetOutput(logger.Writer())
+```
+
+#### Rotation
+
+Log rotation is not provided with Logrus. Log rotation should be done by an
+external program (like `logrotate(8)`) that can compress and delete old log
+entries. It should not be a feature of the application-level logger.
+
+#### Tools
+
+| Tool | Description |
+| ---- | ----------- |
+|[Logrus Mate](https://github.com/gogap/logrus_mate)|Logrus mate is a tool for Logrus to manage loggers, you can initial logger's level, hook and formatter by config file, the logger will generated with different config at different environment.|
+|[Logrus Viper Helper](https://github.com/heirko/go-contrib/tree/master/logrusHelper)|An Helper around Logrus to wrap with spf13/Viper to load configuration with fangs! And to simplify Logrus configuration use some behavior of [Logrus Mate](https://github.com/gogap/logrus_mate). [sample](https://github.com/heirko/iris-contrib/blob/master/middleware/logrus-logger/example) |
+
+#### Testing
+
+Logrus has a built in facility for asserting the presence of log messages. This is implemented through the `test` hook and provides:
+
+* decorators for existing logger (`test.NewLocal` and `test.NewGlobal`) which basically just add the `test` hook
+* a test logger (`test.NewNullLogger`) that just records log messages (and does not output any):
+
+```go
+import(
+ "github.com/sirupsen/logrus"
+ "github.com/sirupsen/logrus/hooks/null"
+ "github.com/stretchr/testify/assert"
+ "testing"
+)
+
+func TestSomething(t*testing.T){
+ logger, hook := null.NewNullLogger()
+ logger.Error("Helloerror")
+
+ assert.Equal(t, 1, len(hook.Entries))
+ assert.Equal(t, logrus.ErrorLevel, hook.LastEntry().Level)
+ assert.Equal(t, "Helloerror", hook.LastEntry().Message)
+
+ hook.Reset()
+ assert.Nil(t, hook.LastEntry())
+}
+```
+
+#### Fatal handlers
+
+Logrus can register one or more functions that will be called when any `fatal`
+level message is logged. The registered handlers will be executed before
+logrus performs a `os.Exit(1)`. This behavior may be helpful if callers need
+to gracefully shutdown. Unlike a `panic("Something went wrong...")` call which can be intercepted with a deferred `recover` a call to `os.Exit(1)` can not be intercepted.
+
+```
+...
+handler := func() {
+ // gracefully shutdown something...
+}
+logrus.RegisterExitHandler(handler)
+...
+```
+
+#### Thread safety
+
+By default Logger is protected by mutex for concurrent writes, this mutex is invoked when calling hooks and writing logs.
+If you are sure such locking is not needed, you can call logger.SetNoLock() to disable the locking.
+
+Situation when locking is not needed includes:
+
+* You have no hooks registered, or hooks calling is already thread-safe.
+
+* Writing to logger.Out is already thread-safe, for example:
+
+ 1) logger.Out is protected by locks.
+
+ 2) logger.Out is a os.File handler opened with `O_APPEND` flag, and every write is smaller than 4k. (This allow multi-thread/multi-process writing)
+
+ (Refer to http://www.notthewizard.com/2014/06/17/are-files-appends-really-atomic/)
diff --git a/vendor/github.com/Sirupsen/logrus/alt_exit.go b/vendor/github.com/Sirupsen/logrus/alt_exit.go
new file mode 100644
index 0000000..8af9063
--- /dev/null
+++ b/vendor/github.com/Sirupsen/logrus/alt_exit.go
@@ -0,0 +1,64 @@
+package logrus
+
+// The following code was sourced and modified from the
+// https://github.com/tebeka/atexit package governed by the following license:
+//
+// Copyright (c) 2012 Miki Tebeka .
+//
+// 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.
+
+import (
+ "fmt"
+ "os"
+)
+
+var handlers = []func(){}
+
+func runHandler(handler func()) {
+ defer func() {
+ if err := recover(); err != nil {
+ fmt.Fprintln(os.Stderr, "Error: Logrus exit handler error:", err)
+ }
+ }()
+
+ handler()
+}
+
+func runHandlers() {
+ for _, handler := range handlers {
+ runHandler(handler)
+ }
+}
+
+// Exit runs all the Logrus atexit handlers and then terminates the program using os.Exit(code)
+func Exit(code int) {
+ runHandlers()
+ os.Exit(code)
+}
+
+// RegisterExitHandler adds a Logrus Exit handler, call logrus.Exit to invoke
+// all handlers. The handlers will also be invoked when any Fatal log entry is
+// made.
+//
+// This method is useful when a caller wishes to use logrus to log a fatal
+// message but also needs to gracefully shutdown. An example usecase could be
+// closing database connections, or sending a alert that the application is
+// closing.
+func RegisterExitHandler(handler func()) {
+ handlers = append(handlers, handler)
+}
diff --git a/vendor/github.com/Sirupsen/logrus/alt_exit_test.go b/vendor/github.com/Sirupsen/logrus/alt_exit_test.go
new file mode 100644
index 0000000..d182963
--- /dev/null
+++ b/vendor/github.com/Sirupsen/logrus/alt_exit_test.go
@@ -0,0 +1,74 @@
+package logrus
+
+import (
+ "io/ioutil"
+ "os/exec"
+ "testing"
+ "time"
+)
+
+func TestRegister(t *testing.T) {
+ current := len(handlers)
+ RegisterExitHandler(func() {})
+ if len(handlers) != current+1 {
+ t.Fatalf("can't add handler")
+ }
+}
+
+func TestHandler(t *testing.T) {
+ gofile := "/tmp/testprog.go"
+ if err := ioutil.WriteFile(gofile, testprog, 0666); err != nil {
+ t.Fatalf("can't create go file")
+ }
+
+ outfile := "/tmp/testprog.out"
+ arg := time.Now().UTC().String()
+ err := exec.Command("go", "run", gofile, outfile, arg).Run()
+ if err == nil {
+ t.Fatalf("completed normally, should have failed")
+ }
+
+ data, err := ioutil.ReadFile(outfile)
+ if err != nil {
+ t.Fatalf("can't read output file %s", outfile)
+ }
+
+ if string(data) != arg {
+ t.Fatalf("bad data")
+ }
+}
+
+var testprog = []byte(`
+// Test program for atexit, gets output file and data as arguments and writes
+// data to output file in atexit handler.
+package main
+
+import (
+ "github.com/sirupsen/logrus"
+ "flag"
+ "fmt"
+ "io/ioutil"
+)
+
+var outfile = ""
+var data = ""
+
+func handler() {
+ ioutil.WriteFile(outfile, []byte(data), 0666)
+}
+
+func badHandler() {
+ n := 0
+ fmt.Println(1/n)
+}
+
+func main() {
+ flag.Parse()
+ outfile = flag.Arg(0)
+ data = flag.Arg(1)
+
+ logrus.RegisterExitHandler(handler)
+ logrus.RegisterExitHandler(badHandler)
+ logrus.Fatal("Bye bye")
+}
+`)
diff --git a/vendor/github.com/Sirupsen/logrus/doc.go b/vendor/github.com/Sirupsen/logrus/doc.go
new file mode 100644
index 0000000..da67aba
--- /dev/null
+++ b/vendor/github.com/Sirupsen/logrus/doc.go
@@ -0,0 +1,26 @@
+/*
+Package logrus is a structured logger for Go, completely API compatible with the standard library logger.
+
+
+The simplest way to use Logrus is simply the package-level exported logger:
+
+ package main
+
+ import (
+ log "github.com/sirupsen/logrus"
+ )
+
+ func main() {
+ log.WithFields(log.Fields{
+ "animal": "walrus",
+ "number": 1,
+ "size": 10,
+ }).Info("A walrus appears")
+ }
+
+Output:
+ time="2015-09-07T08:48:33Z" level=info msg="A walrus appears" animal=walrus number=1 size=10
+
+For a full guide visit https://github.com/sirupsen/logrus
+*/
+package logrus
diff --git a/vendor/github.com/Sirupsen/logrus/entry.go b/vendor/github.com/Sirupsen/logrus/entry.go
new file mode 100644
index 0000000..320e5d5
--- /dev/null
+++ b/vendor/github.com/Sirupsen/logrus/entry.go
@@ -0,0 +1,275 @@
+package logrus
+
+import (
+ "bytes"
+ "fmt"
+ "os"
+ "sync"
+ "time"
+)
+
+var bufferPool *sync.Pool
+
+func init() {
+ bufferPool = &sync.Pool{
+ New: func() interface{} {
+ return new(bytes.Buffer)
+ },
+ }
+}
+
+// Defines the key when adding errors using WithError.
+var ErrorKey = "error"
+
+// An entry is the final or intermediate Logrus logging entry. It contains all
+// the fields passed with WithField{,s}. It's finally logged when Debug, Info,
+// Warn, Error, Fatal or Panic is called on it. These objects can be reused and
+// passed around as much as you wish to avoid field duplication.
+type Entry struct {
+ Logger *Logger
+
+ // Contains all the fields set by the user.
+ Data Fields
+
+ // Time at which the log entry was created
+ Time time.Time
+
+ // Level the log entry was logged at: Debug, Info, Warn, Error, Fatal or Panic
+ Level Level
+
+ // Message passed to Debug, Info, Warn, Error, Fatal or Panic
+ Message string
+
+ // When formatter is called in entry.log(), an Buffer may be set to entry
+ Buffer *bytes.Buffer
+}
+
+func NewEntry(logger *Logger) *Entry {
+ return &Entry{
+ Logger: logger,
+ // Default is three fields, give a little extra room
+ Data: make(Fields, 5),
+ }
+}
+
+// Returns the string representation from the reader and ultimately the
+// formatter.
+func (entry *Entry) String() (string, error) {
+ serialized, err := entry.Logger.Formatter.Format(entry)
+ if err != nil {
+ return "", err
+ }
+ str := string(serialized)
+ return str, nil
+}
+
+// Add an error as single field (using the key defined in ErrorKey) to the Entry.
+func (entry *Entry) WithError(err error) *Entry {
+ return entry.WithField(ErrorKey, err)
+}
+
+// Add a single field to the Entry.
+func (entry *Entry) WithField(key string, value interface{}) *Entry {
+ return entry.WithFields(Fields{key: value})
+}
+
+// Add a map of fields to the Entry.
+func (entry *Entry) WithFields(fields Fields) *Entry {
+ data := make(Fields, len(entry.Data)+len(fields))
+ for k, v := range entry.Data {
+ data[k] = v
+ }
+ for k, v := range fields {
+ data[k] = v
+ }
+ return &Entry{Logger: entry.Logger, Data: data}
+}
+
+// This function is not declared with a pointer value because otherwise
+// race conditions will occur when using multiple goroutines
+func (entry Entry) log(level Level, msg string) {
+ var buffer *bytes.Buffer
+ entry.Time = time.Now()
+ entry.Level = level
+ entry.Message = msg
+
+ if err := entry.Logger.Hooks.Fire(level, &entry); err != nil {
+ entry.Logger.mu.Lock()
+ fmt.Fprintf(os.Stderr, "Failed to fire hook: %v\n", err)
+ entry.Logger.mu.Unlock()
+ }
+ buffer = bufferPool.Get().(*bytes.Buffer)
+ buffer.Reset()
+ defer bufferPool.Put(buffer)
+ entry.Buffer = buffer
+ serialized, err := entry.Logger.Formatter.Format(&entry)
+ entry.Buffer = nil
+ if err != nil {
+ entry.Logger.mu.Lock()
+ fmt.Fprintf(os.Stderr, "Failed to obtain reader, %v\n", err)
+ entry.Logger.mu.Unlock()
+ } else {
+ entry.Logger.mu.Lock()
+ _, err = entry.Logger.Out.Write(serialized)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "Failed to write to log, %v\n", err)
+ }
+ entry.Logger.mu.Unlock()
+ }
+
+ // To avoid Entry#log() returning a value that only would make sense for
+ // panic() to use in Entry#Panic(), we avoid the allocation by checking
+ // directly here.
+ if level <= PanicLevel {
+ panic(&entry)
+ }
+}
+
+func (entry *Entry) Debug(args ...interface{}) {
+ if entry.Logger.level() >= DebugLevel {
+ entry.log(DebugLevel, fmt.Sprint(args...))
+ }
+}
+
+func (entry *Entry) Print(args ...interface{}) {
+ entry.Info(args...)
+}
+
+func (entry *Entry) Info(args ...interface{}) {
+ if entry.Logger.level() >= InfoLevel {
+ entry.log(InfoLevel, fmt.Sprint(args...))
+ }
+}
+
+func (entry *Entry) Warn(args ...interface{}) {
+ if entry.Logger.level() >= WarnLevel {
+ entry.log(WarnLevel, fmt.Sprint(args...))
+ }
+}
+
+func (entry *Entry) Warning(args ...interface{}) {
+ entry.Warn(args...)
+}
+
+func (entry *Entry) Error(args ...interface{}) {
+ if entry.Logger.level() >= ErrorLevel {
+ entry.log(ErrorLevel, fmt.Sprint(args...))
+ }
+}
+
+func (entry *Entry) Fatal(args ...interface{}) {
+ if entry.Logger.level() >= FatalLevel {
+ entry.log(FatalLevel, fmt.Sprint(args...))
+ }
+ Exit(1)
+}
+
+func (entry *Entry) Panic(args ...interface{}) {
+ if entry.Logger.level() >= PanicLevel {
+ entry.log(PanicLevel, fmt.Sprint(args...))
+ }
+ panic(fmt.Sprint(args...))
+}
+
+// Entry Printf family functions
+
+func (entry *Entry) Debugf(format string, args ...interface{}) {
+ if entry.Logger.level() >= DebugLevel {
+ entry.Debug(fmt.Sprintf(format, args...))
+ }
+}
+
+func (entry *Entry) Infof(format string, args ...interface{}) {
+ if entry.Logger.level() >= InfoLevel {
+ entry.Info(fmt.Sprintf(format, args...))
+ }
+}
+
+func (entry *Entry) Printf(format string, args ...interface{}) {
+ entry.Infof(format, args...)
+}
+
+func (entry *Entry) Warnf(format string, args ...interface{}) {
+ if entry.Logger.level() >= WarnLevel {
+ entry.Warn(fmt.Sprintf(format, args...))
+ }
+}
+
+func (entry *Entry) Warningf(format string, args ...interface{}) {
+ entry.Warnf(format, args...)
+}
+
+func (entry *Entry) Errorf(format string, args ...interface{}) {
+ if entry.Logger.level() >= ErrorLevel {
+ entry.Error(fmt.Sprintf(format, args...))
+ }
+}
+
+func (entry *Entry) Fatalf(format string, args ...interface{}) {
+ if entry.Logger.level() >= FatalLevel {
+ entry.Fatal(fmt.Sprintf(format, args...))
+ }
+ Exit(1)
+}
+
+func (entry *Entry) Panicf(format string, args ...interface{}) {
+ if entry.Logger.level() >= PanicLevel {
+ entry.Panic(fmt.Sprintf(format, args...))
+ }
+}
+
+// Entry Println family functions
+
+func (entry *Entry) Debugln(args ...interface{}) {
+ if entry.Logger.level() >= DebugLevel {
+ entry.Debug(entry.sprintlnn(args...))
+ }
+}
+
+func (entry *Entry) Infoln(args ...interface{}) {
+ if entry.Logger.level() >= InfoLevel {
+ entry.Info(entry.sprintlnn(args...))
+ }
+}
+
+func (entry *Entry) Println(args ...interface{}) {
+ entry.Infoln(args...)
+}
+
+func (entry *Entry) Warnln(args ...interface{}) {
+ if entry.Logger.level() >= WarnLevel {
+ entry.Warn(entry.sprintlnn(args...))
+ }
+}
+
+func (entry *Entry) Warningln(args ...interface{}) {
+ entry.Warnln(args...)
+}
+
+func (entry *Entry) Errorln(args ...interface{}) {
+ if entry.Logger.level() >= ErrorLevel {
+ entry.Error(entry.sprintlnn(args...))
+ }
+}
+
+func (entry *Entry) Fatalln(args ...interface{}) {
+ if entry.Logger.level() >= FatalLevel {
+ entry.Fatal(entry.sprintlnn(args...))
+ }
+ Exit(1)
+}
+
+func (entry *Entry) Panicln(args ...interface{}) {
+ if entry.Logger.level() >= PanicLevel {
+ entry.Panic(entry.sprintlnn(args...))
+ }
+}
+
+// Sprintlnn => Sprint no newline. This is to get the behavior of how
+// fmt.Sprintln where spaces are always added between operands, regardless of
+// their type. Instead of vendoring the Sprintln implementation to spare a
+// string allocation, we do the simplest thing.
+func (entry *Entry) sprintlnn(args ...interface{}) string {
+ msg := fmt.Sprintln(args...)
+ return msg[:len(msg)-1]
+}
diff --git a/vendor/github.com/Sirupsen/logrus/entry_test.go b/vendor/github.com/Sirupsen/logrus/entry_test.go
new file mode 100644
index 0000000..99c3b41
--- /dev/null
+++ b/vendor/github.com/Sirupsen/logrus/entry_test.go
@@ -0,0 +1,77 @@
+package logrus
+
+import (
+ "bytes"
+ "fmt"
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+)
+
+func TestEntryWithError(t *testing.T) {
+
+ assert := assert.New(t)
+
+ defer func() {
+ ErrorKey = "error"
+ }()
+
+ err := fmt.Errorf("kaboom at layer %d", 4711)
+
+ assert.Equal(err, WithError(err).Data["error"])
+
+ logger := New()
+ logger.Out = &bytes.Buffer{}
+ entry := NewEntry(logger)
+
+ assert.Equal(err, entry.WithError(err).Data["error"])
+
+ ErrorKey = "err"
+
+ assert.Equal(err, entry.WithError(err).Data["err"])
+
+}
+
+func TestEntryPanicln(t *testing.T) {
+ errBoom := fmt.Errorf("boom time")
+
+ defer func() {
+ p := recover()
+ assert.NotNil(t, p)
+
+ switch pVal := p.(type) {
+ case *Entry:
+ assert.Equal(t, "kaboom", pVal.Message)
+ assert.Equal(t, errBoom, pVal.Data["err"])
+ default:
+ t.Fatalf("want type *Entry, got %T: %#v", pVal, pVal)
+ }
+ }()
+
+ logger := New()
+ logger.Out = &bytes.Buffer{}
+ entry := NewEntry(logger)
+ entry.WithField("err", errBoom).Panicln("kaboom")
+}
+
+func TestEntryPanicf(t *testing.T) {
+ errBoom := fmt.Errorf("boom again")
+
+ defer func() {
+ p := recover()
+ assert.NotNil(t, p)
+
+ switch pVal := p.(type) {
+ case *Entry:
+ assert.Equal(t, "kaboom true", pVal.Message)
+ assert.Equal(t, errBoom, pVal.Data["err"])
+ default:
+ t.Fatalf("want type *Entry, got %T: %#v", pVal, pVal)
+ }
+ }()
+
+ logger := New()
+ logger.Out = &bytes.Buffer{}
+ entry := NewEntry(logger)
+ entry.WithField("err", errBoom).Panicf("kaboom %v", true)
+}
diff --git a/vendor/github.com/Sirupsen/logrus/examples/basic/basic.go b/vendor/github.com/Sirupsen/logrus/examples/basic/basic.go
new file mode 100644
index 0000000..3e112b4
--- /dev/null
+++ b/vendor/github.com/Sirupsen/logrus/examples/basic/basic.go
@@ -0,0 +1,59 @@
+package main
+
+import (
+ "github.com/sirupsen/logrus"
+ // "os"
+)
+
+var log = logrus.New()
+
+func init() {
+ log.Formatter = new(logrus.JSONFormatter)
+ log.Formatter = new(logrus.TextFormatter) // default
+
+ // file, err := os.OpenFile("logrus.log", os.O_CREATE|os.O_WRONLY, 0666)
+ // if err == nil {
+ // log.Out = file
+ // } else {
+ // log.Info("Failed to log to file, using default stderr")
+ // }
+
+ log.Level = logrus.DebugLevel
+}
+
+func main() {
+ defer func() {
+ err := recover()
+ if err != nil {
+ log.WithFields(logrus.Fields{
+ "omg": true,
+ "err": err,
+ "number": 100,
+ }).Fatal("The ice breaks!")
+ }
+ }()
+
+ log.WithFields(logrus.Fields{
+ "animal": "walrus",
+ "number": 8,
+ }).Debug("Started observing beach")
+
+ log.WithFields(logrus.Fields{
+ "animal": "walrus",
+ "size": 10,
+ }).Info("A group of walrus emerges from the ocean")
+
+ log.WithFields(logrus.Fields{
+ "omg": true,
+ "number": 122,
+ }).Warn("The group's number increased tremendously!")
+
+ log.WithFields(logrus.Fields{
+ "temperature": -4,
+ }).Debug("Temperature changes")
+
+ log.WithFields(logrus.Fields{
+ "animal": "orca",
+ "size": 9009,
+ }).Panic("It's over 9000!")
+}
diff --git a/vendor/github.com/Sirupsen/logrus/examples/hook/hook.go b/vendor/github.com/Sirupsen/logrus/examples/hook/hook.go
new file mode 100644
index 0000000..c8470c3
--- /dev/null
+++ b/vendor/github.com/Sirupsen/logrus/examples/hook/hook.go
@@ -0,0 +1,30 @@
+package main
+
+import (
+ "github.com/sirupsen/logrus"
+ "gopkg.in/gemnasium/logrus-airbrake-hook.v2"
+)
+
+var log = logrus.New()
+
+func init() {
+ log.Formatter = new(logrus.TextFormatter) // default
+ log.Hooks.Add(airbrake.NewHook(123, "xyz", "development"))
+}
+
+func main() {
+ log.WithFields(logrus.Fields{
+ "animal": "walrus",
+ "size": 10,
+ }).Info("A group of walrus emerges from the ocean")
+
+ log.WithFields(logrus.Fields{
+ "omg": true,
+ "number": 122,
+ }).Warn("The group's number increased tremendously!")
+
+ log.WithFields(logrus.Fields{
+ "omg": true,
+ "number": 100,
+ }).Fatal("The ice breaks!")
+}
diff --git a/vendor/github.com/Sirupsen/logrus/exported.go b/vendor/github.com/Sirupsen/logrus/exported.go
new file mode 100644
index 0000000..1aeaa90
--- /dev/null
+++ b/vendor/github.com/Sirupsen/logrus/exported.go
@@ -0,0 +1,193 @@
+package logrus
+
+import (
+ "io"
+)
+
+var (
+ // std is the name of the standard logger in stdlib `log`
+ std = New()
+)
+
+func StandardLogger() *Logger {
+ return std
+}
+
+// SetOutput sets the standard logger output.
+func SetOutput(out io.Writer) {
+ std.mu.Lock()
+ defer std.mu.Unlock()
+ std.Out = out
+}
+
+// SetFormatter sets the standard logger formatter.
+func SetFormatter(formatter Formatter) {
+ std.mu.Lock()
+ defer std.mu.Unlock()
+ std.Formatter = formatter
+}
+
+// SetLevel sets the standard logger level.
+func SetLevel(level Level) {
+ std.mu.Lock()
+ defer std.mu.Unlock()
+ std.setLevel(level)
+}
+
+// GetLevel returns the standard logger level.
+func GetLevel() Level {
+ std.mu.Lock()
+ defer std.mu.Unlock()
+ return std.level()
+}
+
+// AddHook adds a hook to the standard logger hooks.
+func AddHook(hook Hook) {
+ std.mu.Lock()
+ defer std.mu.Unlock()
+ std.Hooks.Add(hook)
+}
+
+// WithError creates an entry from the standard logger and adds an error to it, using the value defined in ErrorKey as key.
+func WithError(err error) *Entry {
+ return std.WithField(ErrorKey, err)
+}
+
+// WithField creates an entry from the standard logger and adds a field to
+// it. If you want multiple fields, use `WithFields`.
+//
+// Note that it doesn't log until you call Debug, Print, Info, Warn, Fatal
+// or Panic on the Entry it returns.
+func WithField(key string, value interface{}) *Entry {
+ return std.WithField(key, value)
+}
+
+// WithFields creates an entry from the standard logger and adds multiple
+// fields to it. This is simply a helper for `WithField`, invoking it
+// once for each field.
+//
+// Note that it doesn't log until you call Debug, Print, Info, Warn, Fatal
+// or Panic on the Entry it returns.
+func WithFields(fields Fields) *Entry {
+ return std.WithFields(fields)
+}
+
+// Debug logs a message at level Debug on the standard logger.
+func Debug(args ...interface{}) {
+ std.Debug(args...)
+}
+
+// Print logs a message at level Info on the standard logger.
+func Print(args ...interface{}) {
+ std.Print(args...)
+}
+
+// Info logs a message at level Info on the standard logger.
+func Info(args ...interface{}) {
+ std.Info(args...)
+}
+
+// Warn logs a message at level Warn on the standard logger.
+func Warn(args ...interface{}) {
+ std.Warn(args...)
+}
+
+// Warning logs a message at level Warn on the standard logger.
+func Warning(args ...interface{}) {
+ std.Warning(args...)
+}
+
+// Error logs a message at level Error on the standard logger.
+func Error(args ...interface{}) {
+ std.Error(args...)
+}
+
+// Panic logs a message at level Panic on the standard logger.
+func Panic(args ...interface{}) {
+ std.Panic(args...)
+}
+
+// Fatal logs a message at level Fatal on the standard logger.
+func Fatal(args ...interface{}) {
+ std.Fatal(args...)
+}
+
+// Debugf logs a message at level Debug on the standard logger.
+func Debugf(format string, args ...interface{}) {
+ std.Debugf(format, args...)
+}
+
+// Printf logs a message at level Info on the standard logger.
+func Printf(format string, args ...interface{}) {
+ std.Printf(format, args...)
+}
+
+// Infof logs a message at level Info on the standard logger.
+func Infof(format string, args ...interface{}) {
+ std.Infof(format, args...)
+}
+
+// Warnf logs a message at level Warn on the standard logger.
+func Warnf(format string, args ...interface{}) {
+ std.Warnf(format, args...)
+}
+
+// Warningf logs a message at level Warn on the standard logger.
+func Warningf(format string, args ...interface{}) {
+ std.Warningf(format, args...)
+}
+
+// Errorf logs a message at level Error on the standard logger.
+func Errorf(format string, args ...interface{}) {
+ std.Errorf(format, args...)
+}
+
+// Panicf logs a message at level Panic on the standard logger.
+func Panicf(format string, args ...interface{}) {
+ std.Panicf(format, args...)
+}
+
+// Fatalf logs a message at level Fatal on the standard logger.
+func Fatalf(format string, args ...interface{}) {
+ std.Fatalf(format, args...)
+}
+
+// Debugln logs a message at level Debug on the standard logger.
+func Debugln(args ...interface{}) {
+ std.Debugln(args...)
+}
+
+// Println logs a message at level Info on the standard logger.
+func Println(args ...interface{}) {
+ std.Println(args...)
+}
+
+// Infoln logs a message at level Info on the standard logger.
+func Infoln(args ...interface{}) {
+ std.Infoln(args...)
+}
+
+// Warnln logs a message at level Warn on the standard logger.
+func Warnln(args ...interface{}) {
+ std.Warnln(args...)
+}
+
+// Warningln logs a message at level Warn on the standard logger.
+func Warningln(args ...interface{}) {
+ std.Warningln(args...)
+}
+
+// Errorln logs a message at level Error on the standard logger.
+func Errorln(args ...interface{}) {
+ std.Errorln(args...)
+}
+
+// Panicln logs a message at level Panic on the standard logger.
+func Panicln(args ...interface{}) {
+ std.Panicln(args...)
+}
+
+// Fatalln logs a message at level Fatal on the standard logger.
+func Fatalln(args ...interface{}) {
+ std.Fatalln(args...)
+}
diff --git a/vendor/github.com/Sirupsen/logrus/formatter.go b/vendor/github.com/Sirupsen/logrus/formatter.go
new file mode 100644
index 0000000..b5fbe93
--- /dev/null
+++ b/vendor/github.com/Sirupsen/logrus/formatter.go
@@ -0,0 +1,45 @@
+package logrus
+
+import "time"
+
+const DefaultTimestampFormat = time.RFC3339
+
+// The Formatter interface is used to implement a custom Formatter. It takes an
+// `Entry`. It exposes all the fields, including the default ones:
+//
+// * `entry.Data["msg"]`. The message passed from Info, Warn, Error ..
+// * `entry.Data["time"]`. The timestamp.
+// * `entry.Data["level"]. The level the entry was logged at.
+//
+// Any additional fields added with `WithField` or `WithFields` are also in
+// `entry.Data`. Format is expected to return an array of bytes which are then
+// logged to `logger.Out`.
+type Formatter interface {
+ Format(*Entry) ([]byte, error)
+}
+
+// This is to not silently overwrite `time`, `msg` and `level` fields when
+// dumping it. If this code wasn't there doing:
+//
+// logrus.WithField("level", 1).Info("hello")
+//
+// Would just silently drop the user provided level. Instead with this code
+// it'll logged as:
+//
+// {"level": "info", "fields.level": 1, "msg": "hello", "time": "..."}
+//
+// It's not exported because it's still using Data in an opinionated way. It's to
+// avoid code duplication between the two default formatters.
+func prefixFieldClashes(data Fields) {
+ if t, ok := data["time"]; ok {
+ data["fields.time"] = t
+ }
+
+ if m, ok := data["msg"]; ok {
+ data["fields.msg"] = m
+ }
+
+ if l, ok := data["level"]; ok {
+ data["fields.level"] = l
+ }
+}
diff --git a/vendor/github.com/Sirupsen/logrus/formatter_bench_test.go b/vendor/github.com/Sirupsen/logrus/formatter_bench_test.go
new file mode 100644
index 0000000..d948158
--- /dev/null
+++ b/vendor/github.com/Sirupsen/logrus/formatter_bench_test.go
@@ -0,0 +1,101 @@
+package logrus
+
+import (
+ "fmt"
+ "testing"
+ "time"
+)
+
+// smallFields is a small size data set for benchmarking
+var smallFields = Fields{
+ "foo": "bar",
+ "baz": "qux",
+ "one": "two",
+ "three": "four",
+}
+
+// largeFields is a large size data set for benchmarking
+var largeFields = Fields{
+ "foo": "bar",
+ "baz": "qux",
+ "one": "two",
+ "three": "four",
+ "five": "six",
+ "seven": "eight",
+ "nine": "ten",
+ "eleven": "twelve",
+ "thirteen": "fourteen",
+ "fifteen": "sixteen",
+ "seventeen": "eighteen",
+ "nineteen": "twenty",
+ "a": "b",
+ "c": "d",
+ "e": "f",
+ "g": "h",
+ "i": "j",
+ "k": "l",
+ "m": "n",
+ "o": "p",
+ "q": "r",
+ "s": "t",
+ "u": "v",
+ "w": "x",
+ "y": "z",
+ "this": "will",
+ "make": "thirty",
+ "entries": "yeah",
+}
+
+var errorFields = Fields{
+ "foo": fmt.Errorf("bar"),
+ "baz": fmt.Errorf("qux"),
+}
+
+func BenchmarkErrorTextFormatter(b *testing.B) {
+ doBenchmark(b, &TextFormatter{DisableColors: true}, errorFields)
+}
+
+func BenchmarkSmallTextFormatter(b *testing.B) {
+ doBenchmark(b, &TextFormatter{DisableColors: true}, smallFields)
+}
+
+func BenchmarkLargeTextFormatter(b *testing.B) {
+ doBenchmark(b, &TextFormatter{DisableColors: true}, largeFields)
+}
+
+func BenchmarkSmallColoredTextFormatter(b *testing.B) {
+ doBenchmark(b, &TextFormatter{ForceColors: true}, smallFields)
+}
+
+func BenchmarkLargeColoredTextFormatter(b *testing.B) {
+ doBenchmark(b, &TextFormatter{ForceColors: true}, largeFields)
+}
+
+func BenchmarkSmallJSONFormatter(b *testing.B) {
+ doBenchmark(b, &JSONFormatter{}, smallFields)
+}
+
+func BenchmarkLargeJSONFormatter(b *testing.B) {
+ doBenchmark(b, &JSONFormatter{}, largeFields)
+}
+
+func doBenchmark(b *testing.B, formatter Formatter, fields Fields) {
+ logger := New()
+
+ entry := &Entry{
+ Time: time.Time{},
+ Level: InfoLevel,
+ Message: "message",
+ Data: fields,
+ Logger: logger,
+ }
+ var d []byte
+ var err error
+ for i := 0; i < b.N; i++ {
+ d, err = formatter.Format(entry)
+ if err != nil {
+ b.Fatal(err)
+ }
+ b.SetBytes(int64(len(d)))
+ }
+}
diff --git a/vendor/github.com/Sirupsen/logrus/hook_test.go b/vendor/github.com/Sirupsen/logrus/hook_test.go
new file mode 100644
index 0000000..13f34cb
--- /dev/null
+++ b/vendor/github.com/Sirupsen/logrus/hook_test.go
@@ -0,0 +1,122 @@
+package logrus
+
+import (
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+)
+
+type TestHook struct {
+ Fired bool
+}
+
+func (hook *TestHook) Fire(entry *Entry) error {
+ hook.Fired = true
+ return nil
+}
+
+func (hook *TestHook) Levels() []Level {
+ return []Level{
+ DebugLevel,
+ InfoLevel,
+ WarnLevel,
+ ErrorLevel,
+ FatalLevel,
+ PanicLevel,
+ }
+}
+
+func TestHookFires(t *testing.T) {
+ hook := new(TestHook)
+
+ LogAndAssertJSON(t, func(log *Logger) {
+ log.Hooks.Add(hook)
+ assert.Equal(t, hook.Fired, false)
+
+ log.Print("test")
+ }, func(fields Fields) {
+ assert.Equal(t, hook.Fired, true)
+ })
+}
+
+type ModifyHook struct {
+}
+
+func (hook *ModifyHook) Fire(entry *Entry) error {
+ entry.Data["wow"] = "whale"
+ return nil
+}
+
+func (hook *ModifyHook) Levels() []Level {
+ return []Level{
+ DebugLevel,
+ InfoLevel,
+ WarnLevel,
+ ErrorLevel,
+ FatalLevel,
+ PanicLevel,
+ }
+}
+
+func TestHookCanModifyEntry(t *testing.T) {
+ hook := new(ModifyHook)
+
+ LogAndAssertJSON(t, func(log *Logger) {
+ log.Hooks.Add(hook)
+ log.WithField("wow", "elephant").Print("test")
+ }, func(fields Fields) {
+ assert.Equal(t, fields["wow"], "whale")
+ })
+}
+
+func TestCanFireMultipleHooks(t *testing.T) {
+ hook1 := new(ModifyHook)
+ hook2 := new(TestHook)
+
+ LogAndAssertJSON(t, func(log *Logger) {
+ log.Hooks.Add(hook1)
+ log.Hooks.Add(hook2)
+
+ log.WithField("wow", "elephant").Print("test")
+ }, func(fields Fields) {
+ assert.Equal(t, fields["wow"], "whale")
+ assert.Equal(t, hook2.Fired, true)
+ })
+}
+
+type ErrorHook struct {
+ Fired bool
+}
+
+func (hook *ErrorHook) Fire(entry *Entry) error {
+ hook.Fired = true
+ return nil
+}
+
+func (hook *ErrorHook) Levels() []Level {
+ return []Level{
+ ErrorLevel,
+ }
+}
+
+func TestErrorHookShouldntFireOnInfo(t *testing.T) {
+ hook := new(ErrorHook)
+
+ LogAndAssertJSON(t, func(log *Logger) {
+ log.Hooks.Add(hook)
+ log.Info("test")
+ }, func(fields Fields) {
+ assert.Equal(t, hook.Fired, false)
+ })
+}
+
+func TestErrorHookShouldFireOnError(t *testing.T) {
+ hook := new(ErrorHook)
+
+ LogAndAssertJSON(t, func(log *Logger) {
+ log.Hooks.Add(hook)
+ log.Error("test")
+ }, func(fields Fields) {
+ assert.Equal(t, hook.Fired, true)
+ })
+}
diff --git a/vendor/github.com/Sirupsen/logrus/hooks.go b/vendor/github.com/Sirupsen/logrus/hooks.go
new file mode 100644
index 0000000..3f151cd
--- /dev/null
+++ b/vendor/github.com/Sirupsen/logrus/hooks.go
@@ -0,0 +1,34 @@
+package logrus
+
+// A hook to be fired when logging on the logging levels returned from
+// `Levels()` on your implementation of the interface. Note that this is not
+// fired in a goroutine or a channel with workers, you should handle such
+// functionality yourself if your call is non-blocking and you don't wish for
+// the logging calls for levels returned from `Levels()` to block.
+type Hook interface {
+ Levels() []Level
+ Fire(*Entry) error
+}
+
+// Internal type for storing the hooks on a logger instance.
+type LevelHooks map[Level][]Hook
+
+// Add a hook to an instance of logger. This is called with
+// `log.Hooks.Add(new(MyHook))` where `MyHook` implements the `Hook` interface.
+func (hooks LevelHooks) Add(hook Hook) {
+ for _, level := range hook.Levels() {
+ hooks[level] = append(hooks[level], hook)
+ }
+}
+
+// Fire all the hooks for the passed level. Used by `entry.log` to fire
+// appropriate hooks for a log entry.
+func (hooks LevelHooks) Fire(level Level, entry *Entry) error {
+ for _, hook := range hooks[level] {
+ if err := hook.Fire(entry); err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
diff --git a/vendor/github.com/Sirupsen/logrus/hooks/syslog/README.md b/vendor/github.com/Sirupsen/logrus/hooks/syslog/README.md
new file mode 100644
index 0000000..92b391c
--- /dev/null
+++ b/vendor/github.com/Sirupsen/logrus/hooks/syslog/README.md
@@ -0,0 +1,39 @@
+# Syslog Hooks for Logrus
+
+## Usage
+
+```go
+import (
+ "log/syslog"
+ "github.com/sirupsen/logrus"
+ logrus_syslog "github.com/sirupsen/logrus/hooks/syslog"
+)
+
+func main() {
+ log := logrus.New()
+ hook, err := logrus_syslog.NewSyslogHook("udp", "localhost:514", syslog.LOG_INFO, "")
+
+ if err == nil {
+ log.Hooks.Add(hook)
+ }
+}
+```
+
+If you want to connect to local syslog (Ex. "/dev/log" or "/var/run/syslog" or "/var/run/log"). Just assign empty string to the first two parameters of `NewSyslogHook`. It should look like the following.
+
+```go
+import (
+ "log/syslog"
+ "github.com/sirupsen/logrus"
+ logrus_syslog "github.com/sirupsen/logrus/hooks/syslog"
+)
+
+func main() {
+ log := logrus.New()
+ hook, err := logrus_syslog.NewSyslogHook("", "", syslog.LOG_INFO, "")
+
+ if err == nil {
+ log.Hooks.Add(hook)
+ }
+}
+```
diff --git a/vendor/github.com/Sirupsen/logrus/hooks/syslog/syslog.go b/vendor/github.com/Sirupsen/logrus/hooks/syslog/syslog.go
new file mode 100644
index 0000000..204f001
--- /dev/null
+++ b/vendor/github.com/Sirupsen/logrus/hooks/syslog/syslog.go
@@ -0,0 +1,54 @@
+// +build !windows,!nacl,!plan9
+
+package logrus_syslog
+
+import (
+ "fmt"
+ "github.com/sirupsen/logrus"
+ "log/syslog"
+ "os"
+)
+
+// SyslogHook to send logs via syslog.
+type SyslogHook struct {
+ Writer *syslog.Writer
+ SyslogNetwork string
+ SyslogRaddr string
+}
+
+// Creates a hook to be added to an instance of logger. This is called with
+// `hook, err := NewSyslogHook("udp", "localhost:514", syslog.LOG_DEBUG, "")`
+// `if err == nil { log.Hooks.Add(hook) }`
+func NewSyslogHook(network, raddr string, priority syslog.Priority, tag string) (*SyslogHook, error) {
+ w, err := syslog.Dial(network, raddr, priority, tag)
+ return &SyslogHook{w, network, raddr}, err
+}
+
+func (hook *SyslogHook) Fire(entry *logrus.Entry) error {
+ line, err := entry.String()
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "Unable to read entry, %v", err)
+ return err
+ }
+
+ switch entry.Level {
+ case logrus.PanicLevel:
+ return hook.Writer.Crit(line)
+ case logrus.FatalLevel:
+ return hook.Writer.Crit(line)
+ case logrus.ErrorLevel:
+ return hook.Writer.Err(line)
+ case logrus.WarnLevel:
+ return hook.Writer.Warning(line)
+ case logrus.InfoLevel:
+ return hook.Writer.Info(line)
+ case logrus.DebugLevel:
+ return hook.Writer.Debug(line)
+ default:
+ return nil
+ }
+}
+
+func (hook *SyslogHook) Levels() []logrus.Level {
+ return logrus.AllLevels
+}
diff --git a/vendor/github.com/Sirupsen/logrus/hooks/syslog/syslog_test.go b/vendor/github.com/Sirupsen/logrus/hooks/syslog/syslog_test.go
new file mode 100644
index 0000000..8d7fbe4
--- /dev/null
+++ b/vendor/github.com/Sirupsen/logrus/hooks/syslog/syslog_test.go
@@ -0,0 +1,26 @@
+package logrus_syslog
+
+import (
+ "github.com/sirupsen/logrus"
+ "log/syslog"
+ "testing"
+)
+
+func TestLocalhostAddAndPrint(t *testing.T) {
+ log := logrus.New()
+ hook, err := NewSyslogHook("udp", "localhost:514", syslog.LOG_INFO, "")
+
+ if err != nil {
+ t.Errorf("Unable to connect to local syslog.")
+ }
+
+ log.Hooks.Add(hook)
+
+ for _, level := range hook.Levels() {
+ if len(log.Hooks[level]) != 1 {
+ t.Errorf("SyslogHook was not added. The length of log.Hooks[%v]: %v", level, len(log.Hooks[level]))
+ }
+ }
+
+ log.Info("Congratulations!")
+}
diff --git a/vendor/github.com/Sirupsen/logrus/hooks/test/test.go b/vendor/github.com/Sirupsen/logrus/hooks/test/test.go
new file mode 100644
index 0000000..62c4845
--- /dev/null
+++ b/vendor/github.com/Sirupsen/logrus/hooks/test/test.go
@@ -0,0 +1,95 @@
+// The Test package is used for testing logrus. It is here for backwards
+// compatibility from when logrus' organization was upper-case. Please use
+// lower-case logrus and the `null` package instead of this one.
+package test
+
+import (
+ "io/ioutil"
+ "sync"
+
+ "github.com/sirupsen/logrus"
+)
+
+// Hook is a hook designed for dealing with logs in test scenarios.
+type Hook struct {
+ // Entries is an array of all entries that have been received by this hook.
+ // For safe access, use the AllEntries() method, rather than reading this
+ // value directly.
+ Entries []*logrus.Entry
+ mu sync.RWMutex
+}
+
+// NewGlobal installs a test hook for the global logger.
+func NewGlobal() *Hook {
+
+ hook := new(Hook)
+ logrus.AddHook(hook)
+
+ return hook
+
+}
+
+// NewLocal installs a test hook for a given local logger.
+func NewLocal(logger *logrus.Logger) *Hook {
+
+ hook := new(Hook)
+ logger.Hooks.Add(hook)
+
+ return hook
+
+}
+
+// NewNullLogger creates a discarding logger and installs the test hook.
+func NewNullLogger() (*logrus.Logger, *Hook) {
+
+ logger := logrus.New()
+ logger.Out = ioutil.Discard
+
+ return logger, NewLocal(logger)
+
+}
+
+func (t *Hook) Fire(e *logrus.Entry) error {
+ t.mu.Lock()
+ defer t.mu.Unlock()
+ t.Entries = append(t.Entries, e)
+ return nil
+}
+
+func (t *Hook) Levels() []logrus.Level {
+ return logrus.AllLevels
+}
+
+// LastEntry returns the last entry that was logged or nil.
+func (t *Hook) LastEntry() *logrus.Entry {
+ t.mu.RLock()
+ defer t.mu.RUnlock()
+ i := len(t.Entries) - 1
+ if i < 0 {
+ return nil
+ }
+ // Make a copy, for safety
+ e := *t.Entries[i]
+ return &e
+}
+
+// AllEntries returns all entries that were logged.
+func (t *Hook) AllEntries() []*logrus.Entry {
+ t.mu.RLock()
+ defer t.mu.RUnlock()
+ // Make a copy so the returned value won't race with future log requests
+ entries := make([]*logrus.Entry, len(t.Entries))
+ for i, entry := range t.Entries {
+ // Make a copy, for safety
+ e := *entry
+ entries[i] = &e
+ }
+ return entries
+}
+
+// Reset removes all Entries from this test hook.
+func (t *Hook) Reset() {
+ t.mu.Lock()
+ defer t.mu.Unlock()
+ t.Entries = make([]*logrus.Entry, 0)
+}
diff --git a/vendor/github.com/Sirupsen/logrus/hooks/test/test_test.go b/vendor/github.com/Sirupsen/logrus/hooks/test/test_test.go
new file mode 100644
index 0000000..3f55cfe
--- /dev/null
+++ b/vendor/github.com/Sirupsen/logrus/hooks/test/test_test.go
@@ -0,0 +1,39 @@
+package test
+
+import (
+ "testing"
+
+ "github.com/sirupsen/logrus"
+ "github.com/stretchr/testify/assert"
+)
+
+func TestAllHooks(t *testing.T) {
+
+ assert := assert.New(t)
+
+ logger, hook := NewNullLogger()
+ assert.Nil(hook.LastEntry())
+ assert.Equal(0, len(hook.Entries))
+
+ logger.Error("Hello error")
+ assert.Equal(logrus.ErrorLevel, hook.LastEntry().Level)
+ assert.Equal("Hello error", hook.LastEntry().Message)
+ assert.Equal(1, len(hook.Entries))
+
+ logger.Warn("Hello warning")
+ assert.Equal(logrus.WarnLevel, hook.LastEntry().Level)
+ assert.Equal("Hello warning", hook.LastEntry().Message)
+ assert.Equal(2, len(hook.Entries))
+
+ hook.Reset()
+ assert.Nil(hook.LastEntry())
+ assert.Equal(0, len(hook.Entries))
+
+ hook = NewGlobal()
+
+ logrus.Error("Hello error")
+ assert.Equal(logrus.ErrorLevel, hook.LastEntry().Level)
+ assert.Equal("Hello error", hook.LastEntry().Message)
+ assert.Equal(1, len(hook.Entries))
+
+}
diff --git a/vendor/github.com/Sirupsen/logrus/json_formatter.go b/vendor/github.com/Sirupsen/logrus/json_formatter.go
new file mode 100644
index 0000000..e787ea1
--- /dev/null
+++ b/vendor/github.com/Sirupsen/logrus/json_formatter.go
@@ -0,0 +1,74 @@
+package logrus
+
+import (
+ "encoding/json"
+ "fmt"
+)
+
+type fieldKey string
+type FieldMap map[fieldKey]string
+
+const (
+ FieldKeyMsg = "msg"
+ FieldKeyLevel = "level"
+ FieldKeyTime = "time"
+)
+
+func (f FieldMap) resolve(key fieldKey) string {
+ if k, ok := f[key]; ok {
+ return k
+ }
+
+ return string(key)
+}
+
+type JSONFormatter struct {
+ // TimestampFormat sets the format used for marshaling timestamps.
+ TimestampFormat string
+
+ // DisableTimestamp allows disabling automatic timestamps in output
+ DisableTimestamp bool
+
+ // FieldMap allows users to customize the names of keys for various fields.
+ // As an example:
+ // formatter := &JSONFormatter{
+ // FieldMap: FieldMap{
+ // FieldKeyTime: "@timestamp",
+ // FieldKeyLevel: "@level",
+ // FieldKeyMsg: "@message",
+ // },
+ // }
+ FieldMap FieldMap
+}
+
+func (f *JSONFormatter) Format(entry *Entry) ([]byte, error) {
+ data := make(Fields, len(entry.Data)+3)
+ for k, v := range entry.Data {
+ switch v := v.(type) {
+ case error:
+ // Otherwise errors are ignored by `encoding/json`
+ // https://github.com/sirupsen/logrus/issues/137
+ data[k] = v.Error()
+ default:
+ data[k] = v
+ }
+ }
+ prefixFieldClashes(data)
+
+ timestampFormat := f.TimestampFormat
+ if timestampFormat == "" {
+ timestampFormat = DefaultTimestampFormat
+ }
+
+ if !f.DisableTimestamp {
+ data[f.FieldMap.resolve(FieldKeyTime)] = entry.Time.Format(timestampFormat)
+ }
+ data[f.FieldMap.resolve(FieldKeyMsg)] = entry.Message
+ data[f.FieldMap.resolve(FieldKeyLevel)] = entry.Level.String()
+
+ serialized, err := json.Marshal(data)
+ if err != nil {
+ return nil, fmt.Errorf("Failed to marshal fields to JSON, %v", err)
+ }
+ return append(serialized, '\n'), nil
+}
diff --git a/vendor/github.com/Sirupsen/logrus/json_formatter_test.go b/vendor/github.com/Sirupsen/logrus/json_formatter_test.go
new file mode 100644
index 0000000..51093a7
--- /dev/null
+++ b/vendor/github.com/Sirupsen/logrus/json_formatter_test.go
@@ -0,0 +1,199 @@
+package logrus
+
+import (
+ "encoding/json"
+ "errors"
+ "strings"
+ "testing"
+)
+
+func TestErrorNotLost(t *testing.T) {
+ formatter := &JSONFormatter{}
+
+ b, err := formatter.Format(WithField("error", errors.New("wild walrus")))
+ if err != nil {
+ t.Fatal("Unable to format entry: ", err)
+ }
+
+ entry := make(map[string]interface{})
+ err = json.Unmarshal(b, &entry)
+ if err != nil {
+ t.Fatal("Unable to unmarshal formatted entry: ", err)
+ }
+
+ if entry["error"] != "wild walrus" {
+ t.Fatal("Error field not set")
+ }
+}
+
+func TestErrorNotLostOnFieldNotNamedError(t *testing.T) {
+ formatter := &JSONFormatter{}
+
+ b, err := formatter.Format(WithField("omg", errors.New("wild walrus")))
+ if err != nil {
+ t.Fatal("Unable to format entry: ", err)
+ }
+
+ entry := make(map[string]interface{})
+ err = json.Unmarshal(b, &entry)
+ if err != nil {
+ t.Fatal("Unable to unmarshal formatted entry: ", err)
+ }
+
+ if entry["omg"] != "wild walrus" {
+ t.Fatal("Error field not set")
+ }
+}
+
+func TestFieldClashWithTime(t *testing.T) {
+ formatter := &JSONFormatter{}
+
+ b, err := formatter.Format(WithField("time", "right now!"))
+ if err != nil {
+ t.Fatal("Unable to format entry: ", err)
+ }
+
+ entry := make(map[string]interface{})
+ err = json.Unmarshal(b, &entry)
+ if err != nil {
+ t.Fatal("Unable to unmarshal formatted entry: ", err)
+ }
+
+ if entry["fields.time"] != "right now!" {
+ t.Fatal("fields.time not set to original time field")
+ }
+
+ if entry["time"] != "0001-01-01T00:00:00Z" {
+ t.Fatal("time field not set to current time, was: ", entry["time"])
+ }
+}
+
+func TestFieldClashWithMsg(t *testing.T) {
+ formatter := &JSONFormatter{}
+
+ b, err := formatter.Format(WithField("msg", "something"))
+ if err != nil {
+ t.Fatal("Unable to format entry: ", err)
+ }
+
+ entry := make(map[string]interface{})
+ err = json.Unmarshal(b, &entry)
+ if err != nil {
+ t.Fatal("Unable to unmarshal formatted entry: ", err)
+ }
+
+ if entry["fields.msg"] != "something" {
+ t.Fatal("fields.msg not set to original msg field")
+ }
+}
+
+func TestFieldClashWithLevel(t *testing.T) {
+ formatter := &JSONFormatter{}
+
+ b, err := formatter.Format(WithField("level", "something"))
+ if err != nil {
+ t.Fatal("Unable to format entry: ", err)
+ }
+
+ entry := make(map[string]interface{})
+ err = json.Unmarshal(b, &entry)
+ if err != nil {
+ t.Fatal("Unable to unmarshal formatted entry: ", err)
+ }
+
+ if entry["fields.level"] != "something" {
+ t.Fatal("fields.level not set to original level field")
+ }
+}
+
+func TestJSONEntryEndsWithNewline(t *testing.T) {
+ formatter := &JSONFormatter{}
+
+ b, err := formatter.Format(WithField("level", "something"))
+ if err != nil {
+ t.Fatal("Unable to format entry: ", err)
+ }
+
+ if b[len(b)-1] != '\n' {
+ t.Fatal("Expected JSON log entry to end with a newline")
+ }
+}
+
+func TestJSONMessageKey(t *testing.T) {
+ formatter := &JSONFormatter{
+ FieldMap: FieldMap{
+ FieldKeyMsg: "message",
+ },
+ }
+
+ b, err := formatter.Format(&Entry{Message: "oh hai"})
+ if err != nil {
+ t.Fatal("Unable to format entry: ", err)
+ }
+ s := string(b)
+ if !(strings.Contains(s, "message") && strings.Contains(s, "oh hai")) {
+ t.Fatal("Expected JSON to format message key")
+ }
+}
+
+func TestJSONLevelKey(t *testing.T) {
+ formatter := &JSONFormatter{
+ FieldMap: FieldMap{
+ FieldKeyLevel: "somelevel",
+ },
+ }
+
+ b, err := formatter.Format(WithField("level", "something"))
+ if err != nil {
+ t.Fatal("Unable to format entry: ", err)
+ }
+ s := string(b)
+ if !strings.Contains(s, "somelevel") {
+ t.Fatal("Expected JSON to format level key")
+ }
+}
+
+func TestJSONTimeKey(t *testing.T) {
+ formatter := &JSONFormatter{
+ FieldMap: FieldMap{
+ FieldKeyTime: "timeywimey",
+ },
+ }
+
+ b, err := formatter.Format(WithField("level", "something"))
+ if err != nil {
+ t.Fatal("Unable to format entry: ", err)
+ }
+ s := string(b)
+ if !strings.Contains(s, "timeywimey") {
+ t.Fatal("Expected JSON to format time key")
+ }
+}
+
+func TestJSONDisableTimestamp(t *testing.T) {
+ formatter := &JSONFormatter{
+ DisableTimestamp: true,
+ }
+
+ b, err := formatter.Format(WithField("level", "something"))
+ if err != nil {
+ t.Fatal("Unable to format entry: ", err)
+ }
+ s := string(b)
+ if strings.Contains(s, FieldKeyTime) {
+ t.Error("Did not prevent timestamp", s)
+ }
+}
+
+func TestJSONEnableTimestamp(t *testing.T) {
+ formatter := &JSONFormatter{}
+
+ b, err := formatter.Format(WithField("level", "something"))
+ if err != nil {
+ t.Fatal("Unable to format entry: ", err)
+ }
+ s := string(b)
+ if !strings.Contains(s, FieldKeyTime) {
+ t.Error("Timestamp not present", s)
+ }
+}
diff --git a/vendor/github.com/Sirupsen/logrus/logger.go b/vendor/github.com/Sirupsen/logrus/logger.go
new file mode 100644
index 0000000..370fff5
--- /dev/null
+++ b/vendor/github.com/Sirupsen/logrus/logger.go
@@ -0,0 +1,317 @@
+package logrus
+
+import (
+ "io"
+ "os"
+ "sync"
+ "sync/atomic"
+)
+
+type Logger struct {
+ // The logs are `io.Copy`'d to this in a mutex. It's common to set this to a
+ // file, or leave it default which is `os.Stderr`. You can also set this to
+ // something more adventorous, such as logging to Kafka.
+ Out io.Writer
+ // Hooks for the logger instance. These allow firing events based on logging
+ // levels and log entries. For example, to send errors to an error tracking
+ // service, log to StatsD or dump the core on fatal errors.
+ Hooks LevelHooks
+ // All log entries pass through the formatter before logged to Out. The
+ // included formatters are `TextFormatter` and `JSONFormatter` for which
+ // TextFormatter is the default. In development (when a TTY is attached) it
+ // logs with colors, but to a file it wouldn't. You can easily implement your
+ // own that implements the `Formatter` interface, see the `README` or included
+ // formatters for examples.
+ Formatter Formatter
+ // The logging level the logger should log at. This is typically (and defaults
+ // to) `logrus.Info`, which allows Info(), Warn(), Error() and Fatal() to be
+ // logged. `logrus.Debug` is useful in
+ Level Level
+ // Used to sync writing to the log. Locking is enabled by Default
+ mu MutexWrap
+ // Reusable empty entry
+ entryPool sync.Pool
+}
+
+type MutexWrap struct {
+ lock sync.Mutex
+ disabled bool
+}
+
+func (mw *MutexWrap) Lock() {
+ if !mw.disabled {
+ mw.lock.Lock()
+ }
+}
+
+func (mw *MutexWrap) Unlock() {
+ if !mw.disabled {
+ mw.lock.Unlock()
+ }
+}
+
+func (mw *MutexWrap) Disable() {
+ mw.disabled = true
+}
+
+// Creates a new logger. Configuration should be set by changing `Formatter`,
+// `Out` and `Hooks` directly on the default logger instance. You can also just
+// instantiate your own:
+//
+// var log = &Logger{
+// Out: os.Stderr,
+// Formatter: new(JSONFormatter),
+// Hooks: make(LevelHooks),
+// Level: logrus.DebugLevel,
+// }
+//
+// It's recommended to make this a global instance called `log`.
+func New() *Logger {
+ return &Logger{
+ Out: os.Stderr,
+ Formatter: new(TextFormatter),
+ Hooks: make(LevelHooks),
+ Level: InfoLevel,
+ }
+}
+
+func (logger *Logger) newEntry() *Entry {
+ entry, ok := logger.entryPool.Get().(*Entry)
+ if ok {
+ return entry
+ }
+ return NewEntry(logger)
+}
+
+func (logger *Logger) releaseEntry(entry *Entry) {
+ logger.entryPool.Put(entry)
+}
+
+// Adds a field to the log entry, note that it doesn't log until you call
+// Debug, Print, Info, Warn, Fatal or Panic. It only creates a log entry.
+// If you want multiple fields, use `WithFields`.
+func (logger *Logger) WithField(key string, value interface{}) *Entry {
+ entry := logger.newEntry()
+ defer logger.releaseEntry(entry)
+ return entry.WithField(key, value)
+}
+
+// Adds a struct of fields to the log entry. All it does is call `WithField` for
+// each `Field`.
+func (logger *Logger) WithFields(fields Fields) *Entry {
+ entry := logger.newEntry()
+ defer logger.releaseEntry(entry)
+ return entry.WithFields(fields)
+}
+
+// Add an error as single field to the log entry. All it does is call
+// `WithError` for the given `error`.
+func (logger *Logger) WithError(err error) *Entry {
+ entry := logger.newEntry()
+ defer logger.releaseEntry(entry)
+ return entry.WithError(err)
+}
+
+func (logger *Logger) Debugf(format string, args ...interface{}) {
+ if logger.level() >= DebugLevel {
+ entry := logger.newEntry()
+ entry.Debugf(format, args...)
+ logger.releaseEntry(entry)
+ }
+}
+
+func (logger *Logger) Infof(format string, args ...interface{}) {
+ if logger.level() >= InfoLevel {
+ entry := logger.newEntry()
+ entry.Infof(format, args...)
+ logger.releaseEntry(entry)
+ }
+}
+
+func (logger *Logger) Printf(format string, args ...interface{}) {
+ entry := logger.newEntry()
+ entry.Printf(format, args...)
+ logger.releaseEntry(entry)
+}
+
+func (logger *Logger) Warnf(format string, args ...interface{}) {
+ if logger.level() >= WarnLevel {
+ entry := logger.newEntry()
+ entry.Warnf(format, args...)
+ logger.releaseEntry(entry)
+ }
+}
+
+func (logger *Logger) Warningf(format string, args ...interface{}) {
+ if logger.level() >= WarnLevel {
+ entry := logger.newEntry()
+ entry.Warnf(format, args...)
+ logger.releaseEntry(entry)
+ }
+}
+
+func (logger *Logger) Errorf(format string, args ...interface{}) {
+ if logger.level() >= ErrorLevel {
+ entry := logger.newEntry()
+ entry.Errorf(format, args...)
+ logger.releaseEntry(entry)
+ }
+}
+
+func (logger *Logger) Fatalf(format string, args ...interface{}) {
+ if logger.level() >= FatalLevel {
+ entry := logger.newEntry()
+ entry.Fatalf(format, args...)
+ logger.releaseEntry(entry)
+ }
+ Exit(1)
+}
+
+func (logger *Logger) Panicf(format string, args ...interface{}) {
+ if logger.level() >= PanicLevel {
+ entry := logger.newEntry()
+ entry.Panicf(format, args...)
+ logger.releaseEntry(entry)
+ }
+}
+
+func (logger *Logger) Debug(args ...interface{}) {
+ if logger.level() >= DebugLevel {
+ entry := logger.newEntry()
+ entry.Debug(args...)
+ logger.releaseEntry(entry)
+ }
+}
+
+func (logger *Logger) Info(args ...interface{}) {
+ if logger.level() >= InfoLevel {
+ entry := logger.newEntry()
+ entry.Info(args...)
+ logger.releaseEntry(entry)
+ }
+}
+
+func (logger *Logger) Print(args ...interface{}) {
+ entry := logger.newEntry()
+ entry.Info(args...)
+ logger.releaseEntry(entry)
+}
+
+func (logger *Logger) Warn(args ...interface{}) {
+ if logger.level() >= WarnLevel {
+ entry := logger.newEntry()
+ entry.Warn(args...)
+ logger.releaseEntry(entry)
+ }
+}
+
+func (logger *Logger) Warning(args ...interface{}) {
+ if logger.level() >= WarnLevel {
+ entry := logger.newEntry()
+ entry.Warn(args...)
+ logger.releaseEntry(entry)
+ }
+}
+
+func (logger *Logger) Error(args ...interface{}) {
+ if logger.level() >= ErrorLevel {
+ entry := logger.newEntry()
+ entry.Error(args...)
+ logger.releaseEntry(entry)
+ }
+}
+
+func (logger *Logger) Fatal(args ...interface{}) {
+ if logger.level() >= FatalLevel {
+ entry := logger.newEntry()
+ entry.Fatal(args...)
+ logger.releaseEntry(entry)
+ }
+ Exit(1)
+}
+
+func (logger *Logger) Panic(args ...interface{}) {
+ if logger.level() >= PanicLevel {
+ entry := logger.newEntry()
+ entry.Panic(args...)
+ logger.releaseEntry(entry)
+ }
+}
+
+func (logger *Logger) Debugln(args ...interface{}) {
+ if logger.level() >= DebugLevel {
+ entry := logger.newEntry()
+ entry.Debugln(args...)
+ logger.releaseEntry(entry)
+ }
+}
+
+func (logger *Logger) Infoln(args ...interface{}) {
+ if logger.level() >= InfoLevel {
+ entry := logger.newEntry()
+ entry.Infoln(args...)
+ logger.releaseEntry(entry)
+ }
+}
+
+func (logger *Logger) Println(args ...interface{}) {
+ entry := logger.newEntry()
+ entry.Println(args...)
+ logger.releaseEntry(entry)
+}
+
+func (logger *Logger) Warnln(args ...interface{}) {
+ if logger.level() >= WarnLevel {
+ entry := logger.newEntry()
+ entry.Warnln(args...)
+ logger.releaseEntry(entry)
+ }
+}
+
+func (logger *Logger) Warningln(args ...interface{}) {
+ if logger.level() >= WarnLevel {
+ entry := logger.newEntry()
+ entry.Warnln(args...)
+ logger.releaseEntry(entry)
+ }
+}
+
+func (logger *Logger) Errorln(args ...interface{}) {
+ if logger.level() >= ErrorLevel {
+ entry := logger.newEntry()
+ entry.Errorln(args...)
+ logger.releaseEntry(entry)
+ }
+}
+
+func (logger *Logger) Fatalln(args ...interface{}) {
+ if logger.level() >= FatalLevel {
+ entry := logger.newEntry()
+ entry.Fatalln(args...)
+ logger.releaseEntry(entry)
+ }
+ Exit(1)
+}
+
+func (logger *Logger) Panicln(args ...interface{}) {
+ if logger.level() >= PanicLevel {
+ entry := logger.newEntry()
+ entry.Panicln(args...)
+ logger.releaseEntry(entry)
+ }
+}
+
+//When file is opened with appending mode, it's safe to
+//write concurrently to a file (within 4k message on Linux).
+//In these cases user can choose to disable the lock.
+func (logger *Logger) SetNoLock() {
+ logger.mu.Disable()
+}
+
+func (logger *Logger) level() Level {
+ return Level(atomic.LoadUint32((*uint32)(&logger.Level)))
+}
+
+func (logger *Logger) setLevel(level Level) {
+ atomic.StoreUint32((*uint32)(&logger.Level), uint32(level))
+}
diff --git a/vendor/github.com/Sirupsen/logrus/logger_bench_test.go b/vendor/github.com/Sirupsen/logrus/logger_bench_test.go
new file mode 100644
index 0000000..dd23a35
--- /dev/null
+++ b/vendor/github.com/Sirupsen/logrus/logger_bench_test.go
@@ -0,0 +1,61 @@
+package logrus
+
+import (
+ "os"
+ "testing"
+)
+
+// smallFields is a small size data set for benchmarking
+var loggerFields = Fields{
+ "foo": "bar",
+ "baz": "qux",
+ "one": "two",
+ "three": "four",
+}
+
+func BenchmarkDummyLogger(b *testing.B) {
+ nullf, err := os.OpenFile("/dev/null", os.O_WRONLY, 0666)
+ if err != nil {
+ b.Fatalf("%v", err)
+ }
+ defer nullf.Close()
+ doLoggerBenchmark(b, nullf, &TextFormatter{DisableColors: true}, smallFields)
+}
+
+func BenchmarkDummyLoggerNoLock(b *testing.B) {
+ nullf, err := os.OpenFile("/dev/null", os.O_WRONLY|os.O_APPEND, 0666)
+ if err != nil {
+ b.Fatalf("%v", err)
+ }
+ defer nullf.Close()
+ doLoggerBenchmarkNoLock(b, nullf, &TextFormatter{DisableColors: true}, smallFields)
+}
+
+func doLoggerBenchmark(b *testing.B, out *os.File, formatter Formatter, fields Fields) {
+ logger := Logger{
+ Out: out,
+ Level: InfoLevel,
+ Formatter: formatter,
+ }
+ entry := logger.WithFields(fields)
+ b.RunParallel(func(pb *testing.PB) {
+ for pb.Next() {
+ entry.Info("aaa")
+ }
+ })
+}
+
+func doLoggerBenchmarkNoLock(b *testing.B, out *os.File, formatter Formatter, fields Fields) {
+ logger := Logger{
+ Out: out,
+ Level: InfoLevel,
+ Formatter: formatter,
+ }
+ logger.SetNoLock()
+ entry := logger.WithFields(fields)
+ b.RunParallel(func(pb *testing.PB) {
+ for pb.Next() {
+ entry.Info("aaa")
+ }
+ })
+}
diff --git a/vendor/github.com/Sirupsen/logrus/logrus.go b/vendor/github.com/Sirupsen/logrus/logrus.go
new file mode 100644
index 0000000..dd38999
--- /dev/null
+++ b/vendor/github.com/Sirupsen/logrus/logrus.go
@@ -0,0 +1,143 @@
+package logrus
+
+import (
+ "fmt"
+ "log"
+ "strings"
+)
+
+// Fields type, used to pass to `WithFields`.
+type Fields map[string]interface{}
+
+// Level type
+type Level uint32
+
+// Convert the Level to a string. E.g. PanicLevel becomes "panic".
+func (level Level) String() string {
+ switch level {
+ case DebugLevel:
+ return "debug"
+ case InfoLevel:
+ return "info"
+ case WarnLevel:
+ return "warning"
+ case ErrorLevel:
+ return "error"
+ case FatalLevel:
+ return "fatal"
+ case PanicLevel:
+ return "panic"
+ }
+
+ return "unknown"
+}
+
+// ParseLevel takes a string level and returns the Logrus log level constant.
+func ParseLevel(lvl string) (Level, error) {
+ switch strings.ToLower(lvl) {
+ case "panic":
+ return PanicLevel, nil
+ case "fatal":
+ return FatalLevel, nil
+ case "error":
+ return ErrorLevel, nil
+ case "warn", "warning":
+ return WarnLevel, nil
+ case "info":
+ return InfoLevel, nil
+ case "debug":
+ return DebugLevel, nil
+ }
+
+ var l Level
+ return l, fmt.Errorf("not a valid logrus Level: %q", lvl)
+}
+
+// A constant exposing all logging levels
+var AllLevels = []Level{
+ PanicLevel,
+ FatalLevel,
+ ErrorLevel,
+ WarnLevel,
+ InfoLevel,
+ DebugLevel,
+}
+
+// These are the different logging levels. You can set the logging level to log
+// on your instance of logger, obtained with `logrus.New()`.
+const (
+ // PanicLevel level, highest level of severity. Logs and then calls panic with the
+ // message passed to Debug, Info, ...
+ PanicLevel Level = iota
+ // FatalLevel level. Logs and then calls `os.Exit(1)`. It will exit even if the
+ // logging level is set to Panic.
+ FatalLevel
+ // ErrorLevel level. Logs. Used for errors that should definitely be noted.
+ // Commonly used for hooks to send errors to an error tracking service.
+ ErrorLevel
+ // WarnLevel level. Non-critical entries that deserve eyes.
+ WarnLevel
+ // InfoLevel level. General operational entries about what's going on inside the
+ // application.
+ InfoLevel
+ // DebugLevel level. Usually only enabled when debugging. Very verbose logging.
+ DebugLevel
+)
+
+// Won't compile if StdLogger can't be realized by a log.Logger
+var (
+ _ StdLogger = &log.Logger{}
+ _ StdLogger = &Entry{}
+ _ StdLogger = &Logger{}
+)
+
+// StdLogger is what your logrus-enabled library should take, that way
+// it'll accept a stdlib logger and a logrus logger. There's no standard
+// interface, this is the closest we get, unfortunately.
+type StdLogger interface {
+ Print(...interface{})
+ Printf(string, ...interface{})
+ Println(...interface{})
+
+ Fatal(...interface{})
+ Fatalf(string, ...interface{})
+ Fatalln(...interface{})
+
+ Panic(...interface{})
+ Panicf(string, ...interface{})
+ Panicln(...interface{})
+}
+
+// The FieldLogger interface generalizes the Entry and Logger types
+type FieldLogger interface {
+ WithField(key string, value interface{}) *Entry
+ WithFields(fields Fields) *Entry
+ WithError(err error) *Entry
+
+ Debugf(format string, args ...interface{})
+ Infof(format string, args ...interface{})
+ Printf(format string, args ...interface{})
+ Warnf(format string, args ...interface{})
+ Warningf(format string, args ...interface{})
+ Errorf(format string, args ...interface{})
+ Fatalf(format string, args ...interface{})
+ Panicf(format string, args ...interface{})
+
+ Debug(args ...interface{})
+ Info(args ...interface{})
+ Print(args ...interface{})
+ Warn(args ...interface{})
+ Warning(args ...interface{})
+ Error(args ...interface{})
+ Fatal(args ...interface{})
+ Panic(args ...interface{})
+
+ Debugln(args ...interface{})
+ Infoln(args ...interface{})
+ Println(args ...interface{})
+ Warnln(args ...interface{})
+ Warningln(args ...interface{})
+ Errorln(args ...interface{})
+ Fatalln(args ...interface{})
+ Panicln(args ...interface{})
+}
diff --git a/vendor/github.com/Sirupsen/logrus/logrus_test.go b/vendor/github.com/Sirupsen/logrus/logrus_test.go
new file mode 100644
index 0000000..78cbc28
--- /dev/null
+++ b/vendor/github.com/Sirupsen/logrus/logrus_test.go
@@ -0,0 +1,386 @@
+package logrus
+
+import (
+ "bytes"
+ "encoding/json"
+ "strconv"
+ "strings"
+ "sync"
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+)
+
+func LogAndAssertJSON(t *testing.T, log func(*Logger), assertions func(fields Fields)) {
+ var buffer bytes.Buffer
+ var fields Fields
+
+ logger := New()
+ logger.Out = &buffer
+ logger.Formatter = new(JSONFormatter)
+
+ log(logger)
+
+ err := json.Unmarshal(buffer.Bytes(), &fields)
+ assert.Nil(t, err)
+
+ assertions(fields)
+}
+
+func LogAndAssertText(t *testing.T, log func(*Logger), assertions func(fields map[string]string)) {
+ var buffer bytes.Buffer
+
+ logger := New()
+ logger.Out = &buffer
+ logger.Formatter = &TextFormatter{
+ DisableColors: true,
+ }
+
+ log(logger)
+
+ fields := make(map[string]string)
+ for _, kv := range strings.Split(buffer.String(), " ") {
+ if !strings.Contains(kv, "=") {
+ continue
+ }
+ kvArr := strings.Split(kv, "=")
+ key := strings.TrimSpace(kvArr[0])
+ val := kvArr[1]
+ if kvArr[1][0] == '"' {
+ var err error
+ val, err = strconv.Unquote(val)
+ assert.NoError(t, err)
+ }
+ fields[key] = val
+ }
+ assertions(fields)
+}
+
+func TestPrint(t *testing.T) {
+ LogAndAssertJSON(t, func(log *Logger) {
+ log.Print("test")
+ }, func(fields Fields) {
+ assert.Equal(t, fields["msg"], "test")
+ assert.Equal(t, fields["level"], "info")
+ })
+}
+
+func TestInfo(t *testing.T) {
+ LogAndAssertJSON(t, func(log *Logger) {
+ log.Info("test")
+ }, func(fields Fields) {
+ assert.Equal(t, fields["msg"], "test")
+ assert.Equal(t, fields["level"], "info")
+ })
+}
+
+func TestWarn(t *testing.T) {
+ LogAndAssertJSON(t, func(log *Logger) {
+ log.Warn("test")
+ }, func(fields Fields) {
+ assert.Equal(t, fields["msg"], "test")
+ assert.Equal(t, fields["level"], "warning")
+ })
+}
+
+func TestInfolnShouldAddSpacesBetweenStrings(t *testing.T) {
+ LogAndAssertJSON(t, func(log *Logger) {
+ log.Infoln("test", "test")
+ }, func(fields Fields) {
+ assert.Equal(t, fields["msg"], "test test")
+ })
+}
+
+func TestInfolnShouldAddSpacesBetweenStringAndNonstring(t *testing.T) {
+ LogAndAssertJSON(t, func(log *Logger) {
+ log.Infoln("test", 10)
+ }, func(fields Fields) {
+ assert.Equal(t, fields["msg"], "test 10")
+ })
+}
+
+func TestInfolnShouldAddSpacesBetweenTwoNonStrings(t *testing.T) {
+ LogAndAssertJSON(t, func(log *Logger) {
+ log.Infoln(10, 10)
+ }, func(fields Fields) {
+ assert.Equal(t, fields["msg"], "10 10")
+ })
+}
+
+func TestInfoShouldAddSpacesBetweenTwoNonStrings(t *testing.T) {
+ LogAndAssertJSON(t, func(log *Logger) {
+ log.Infoln(10, 10)
+ }, func(fields Fields) {
+ assert.Equal(t, fields["msg"], "10 10")
+ })
+}
+
+func TestInfoShouldNotAddSpacesBetweenStringAndNonstring(t *testing.T) {
+ LogAndAssertJSON(t, func(log *Logger) {
+ log.Info("test", 10)
+ }, func(fields Fields) {
+ assert.Equal(t, fields["msg"], "test10")
+ })
+}
+
+func TestInfoShouldNotAddSpacesBetweenStrings(t *testing.T) {
+ LogAndAssertJSON(t, func(log *Logger) {
+ log.Info("test", "test")
+ }, func(fields Fields) {
+ assert.Equal(t, fields["msg"], "testtest")
+ })
+}
+
+func TestWithFieldsShouldAllowAssignments(t *testing.T) {
+ var buffer bytes.Buffer
+ var fields Fields
+
+ logger := New()
+ logger.Out = &buffer
+ logger.Formatter = new(JSONFormatter)
+
+ localLog := logger.WithFields(Fields{
+ "key1": "value1",
+ })
+
+ localLog.WithField("key2", "value2").Info("test")
+ err := json.Unmarshal(buffer.Bytes(), &fields)
+ assert.Nil(t, err)
+
+ assert.Equal(t, "value2", fields["key2"])
+ assert.Equal(t, "value1", fields["key1"])
+
+ buffer = bytes.Buffer{}
+ fields = Fields{}
+ localLog.Info("test")
+ err = json.Unmarshal(buffer.Bytes(), &fields)
+ assert.Nil(t, err)
+
+ _, ok := fields["key2"]
+ assert.Equal(t, false, ok)
+ assert.Equal(t, "value1", fields["key1"])
+}
+
+func TestUserSuppliedFieldDoesNotOverwriteDefaults(t *testing.T) {
+ LogAndAssertJSON(t, func(log *Logger) {
+ log.WithField("msg", "hello").Info("test")
+ }, func(fields Fields) {
+ assert.Equal(t, fields["msg"], "test")
+ })
+}
+
+func TestUserSuppliedMsgFieldHasPrefix(t *testing.T) {
+ LogAndAssertJSON(t, func(log *Logger) {
+ log.WithField("msg", "hello").Info("test")
+ }, func(fields Fields) {
+ assert.Equal(t, fields["msg"], "test")
+ assert.Equal(t, fields["fields.msg"], "hello")
+ })
+}
+
+func TestUserSuppliedTimeFieldHasPrefix(t *testing.T) {
+ LogAndAssertJSON(t, func(log *Logger) {
+ log.WithField("time", "hello").Info("test")
+ }, func(fields Fields) {
+ assert.Equal(t, fields["fields.time"], "hello")
+ })
+}
+
+func TestUserSuppliedLevelFieldHasPrefix(t *testing.T) {
+ LogAndAssertJSON(t, func(log *Logger) {
+ log.WithField("level", 1).Info("test")
+ }, func(fields Fields) {
+ assert.Equal(t, fields["level"], "info")
+ assert.Equal(t, fields["fields.level"], 1.0) // JSON has floats only
+ })
+}
+
+func TestDefaultFieldsAreNotPrefixed(t *testing.T) {
+ LogAndAssertText(t, func(log *Logger) {
+ ll := log.WithField("herp", "derp")
+ ll.Info("hello")
+ ll.Info("bye")
+ }, func(fields map[string]string) {
+ for _, fieldName := range []string{"fields.level", "fields.time", "fields.msg"} {
+ if _, ok := fields[fieldName]; ok {
+ t.Fatalf("should not have prefixed %q: %v", fieldName, fields)
+ }
+ }
+ })
+}
+
+func TestDoubleLoggingDoesntPrefixPreviousFields(t *testing.T) {
+
+ var buffer bytes.Buffer
+ var fields Fields
+
+ logger := New()
+ logger.Out = &buffer
+ logger.Formatter = new(JSONFormatter)
+
+ llog := logger.WithField("context", "eating raw fish")
+
+ llog.Info("looks delicious")
+
+ err := json.Unmarshal(buffer.Bytes(), &fields)
+ assert.NoError(t, err, "should have decoded first message")
+ assert.Equal(t, len(fields), 4, "should only have msg/time/level/context fields")
+ assert.Equal(t, fields["msg"], "looks delicious")
+ assert.Equal(t, fields["context"], "eating raw fish")
+
+ buffer.Reset()
+
+ llog.Warn("omg it is!")
+
+ err = json.Unmarshal(buffer.Bytes(), &fields)
+ assert.NoError(t, err, "should have decoded second message")
+ assert.Equal(t, len(fields), 4, "should only have msg/time/level/context fields")
+ assert.Equal(t, fields["msg"], "omg it is!")
+ assert.Equal(t, fields["context"], "eating raw fish")
+ assert.Nil(t, fields["fields.msg"], "should not have prefixed previous `msg` entry")
+
+}
+
+func TestConvertLevelToString(t *testing.T) {
+ assert.Equal(t, "debug", DebugLevel.String())
+ assert.Equal(t, "info", InfoLevel.String())
+ assert.Equal(t, "warning", WarnLevel.String())
+ assert.Equal(t, "error", ErrorLevel.String())
+ assert.Equal(t, "fatal", FatalLevel.String())
+ assert.Equal(t, "panic", PanicLevel.String())
+}
+
+func TestParseLevel(t *testing.T) {
+ l, err := ParseLevel("panic")
+ assert.Nil(t, err)
+ assert.Equal(t, PanicLevel, l)
+
+ l, err = ParseLevel("PANIC")
+ assert.Nil(t, err)
+ assert.Equal(t, PanicLevel, l)
+
+ l, err = ParseLevel("fatal")
+ assert.Nil(t, err)
+ assert.Equal(t, FatalLevel, l)
+
+ l, err = ParseLevel("FATAL")
+ assert.Nil(t, err)
+ assert.Equal(t, FatalLevel, l)
+
+ l, err = ParseLevel("error")
+ assert.Nil(t, err)
+ assert.Equal(t, ErrorLevel, l)
+
+ l, err = ParseLevel("ERROR")
+ assert.Nil(t, err)
+ assert.Equal(t, ErrorLevel, l)
+
+ l, err = ParseLevel("warn")
+ assert.Nil(t, err)
+ assert.Equal(t, WarnLevel, l)
+
+ l, err = ParseLevel("WARN")
+ assert.Nil(t, err)
+ assert.Equal(t, WarnLevel, l)
+
+ l, err = ParseLevel("warning")
+ assert.Nil(t, err)
+ assert.Equal(t, WarnLevel, l)
+
+ l, err = ParseLevel("WARNING")
+ assert.Nil(t, err)
+ assert.Equal(t, WarnLevel, l)
+
+ l, err = ParseLevel("info")
+ assert.Nil(t, err)
+ assert.Equal(t, InfoLevel, l)
+
+ l, err = ParseLevel("INFO")
+ assert.Nil(t, err)
+ assert.Equal(t, InfoLevel, l)
+
+ l, err = ParseLevel("debug")
+ assert.Nil(t, err)
+ assert.Equal(t, DebugLevel, l)
+
+ l, err = ParseLevel("DEBUG")
+ assert.Nil(t, err)
+ assert.Equal(t, DebugLevel, l)
+
+ l, err = ParseLevel("invalid")
+ assert.Equal(t, "not a valid logrus Level: \"invalid\"", err.Error())
+}
+
+func TestGetSetLevelRace(t *testing.T) {
+ wg := sync.WaitGroup{}
+ for i := 0; i < 100; i++ {
+ wg.Add(1)
+ go func(i int) {
+ defer wg.Done()
+ if i%2 == 0 {
+ SetLevel(InfoLevel)
+ } else {
+ GetLevel()
+ }
+ }(i)
+
+ }
+ wg.Wait()
+}
+
+func TestLoggingRace(t *testing.T) {
+ logger := New()
+
+ var wg sync.WaitGroup
+ wg.Add(100)
+
+ for i := 0; i < 100; i++ {
+ go func() {
+ logger.Info("info")
+ wg.Done()
+ }()
+ }
+ wg.Wait()
+}
+
+// Compile test
+func TestLogrusInterface(t *testing.T) {
+ var buffer bytes.Buffer
+ fn := func(l FieldLogger) {
+ b := l.WithField("key", "value")
+ b.Debug("Test")
+ }
+ // test logger
+ logger := New()
+ logger.Out = &buffer
+ fn(logger)
+
+ // test Entry
+ e := logger.WithField("another", "value")
+ fn(e)
+}
+
+// Implements io.Writer using channels for synchronization, so we can wait on
+// the Entry.Writer goroutine to write in a non-racey way. This does assume that
+// there is a single call to Logger.Out for each message.
+type channelWriter chan []byte
+
+func (cw channelWriter) Write(p []byte) (int, error) {
+ cw <- p
+ return len(p), nil
+}
+
+func TestEntryWriter(t *testing.T) {
+ cw := channelWriter(make(chan []byte, 1))
+ log := New()
+ log.Out = cw
+ log.Formatter = new(JSONFormatter)
+ log.WithField("foo", "bar").WriterLevel(WarnLevel).Write([]byte("hello\n"))
+
+ bs := <-cw
+ var fields Fields
+ err := json.Unmarshal(bs, &fields)
+ assert.Nil(t, err)
+ assert.Equal(t, fields["foo"], "bar")
+ assert.Equal(t, fields["level"], "warning")
+}
diff --git a/vendor/github.com/Sirupsen/logrus/terminal_appengine.go b/vendor/github.com/Sirupsen/logrus/terminal_appengine.go
new file mode 100644
index 0000000..e011a86
--- /dev/null
+++ b/vendor/github.com/Sirupsen/logrus/terminal_appengine.go
@@ -0,0 +1,10 @@
+// +build appengine
+
+package logrus
+
+import "io"
+
+// IsTerminal returns true if stderr's file descriptor is a terminal.
+func IsTerminal(f io.Writer) bool {
+ return true
+}
diff --git a/vendor/github.com/Sirupsen/logrus/terminal_bsd.go b/vendor/github.com/Sirupsen/logrus/terminal_bsd.go
new file mode 100644
index 0000000..5f6be4d
--- /dev/null
+++ b/vendor/github.com/Sirupsen/logrus/terminal_bsd.go
@@ -0,0 +1,10 @@
+// +build darwin freebsd openbsd netbsd dragonfly
+// +build !appengine
+
+package logrus
+
+import "syscall"
+
+const ioctlReadTermios = syscall.TIOCGETA
+
+type Termios syscall.Termios
diff --git a/vendor/github.com/Sirupsen/logrus/terminal_linux.go b/vendor/github.com/Sirupsen/logrus/terminal_linux.go
new file mode 100644
index 0000000..308160c
--- /dev/null
+++ b/vendor/github.com/Sirupsen/logrus/terminal_linux.go
@@ -0,0 +1,14 @@
+// Based on ssh/terminal:
+// Copyright 2013 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 !appengine
+
+package logrus
+
+import "syscall"
+
+const ioctlReadTermios = syscall.TCGETS
+
+type Termios syscall.Termios
diff --git a/vendor/github.com/Sirupsen/logrus/terminal_notwindows.go b/vendor/github.com/Sirupsen/logrus/terminal_notwindows.go
new file mode 100644
index 0000000..190297a
--- /dev/null
+++ b/vendor/github.com/Sirupsen/logrus/terminal_notwindows.go
@@ -0,0 +1,28 @@
+// Based on ssh/terminal:
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build linux darwin freebsd openbsd netbsd dragonfly
+// +build !appengine
+
+package logrus
+
+import (
+ "io"
+ "os"
+ "syscall"
+ "unsafe"
+)
+
+// IsTerminal returns true if stderr's file descriptor is a terminal.
+func IsTerminal(f io.Writer) bool {
+ var termios Termios
+ switch v := f.(type) {
+ case *os.File:
+ _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(v.Fd()), ioctlReadTermios, uintptr(unsafe.Pointer(&termios)), 0, 0, 0)
+ return err == 0
+ default:
+ return false
+ }
+}
diff --git a/vendor/github.com/Sirupsen/logrus/terminal_solaris.go b/vendor/github.com/Sirupsen/logrus/terminal_solaris.go
new file mode 100644
index 0000000..3c86b1a
--- /dev/null
+++ b/vendor/github.com/Sirupsen/logrus/terminal_solaris.go
@@ -0,0 +1,21 @@
+// +build solaris,!appengine
+
+package logrus
+
+import (
+ "io"
+ "os"
+
+ "golang.org/x/sys/unix"
+)
+
+// IsTerminal returns true if the given file descriptor is a terminal.
+func IsTerminal(f io.Writer) bool {
+ switch v := f.(type) {
+ case *os.File:
+ _, err := unix.IoctlGetTermios(int(v.Fd()), unix.TCGETA)
+ return err == nil
+ default:
+ return false
+ }
+}
diff --git a/vendor/github.com/Sirupsen/logrus/terminal_windows.go b/vendor/github.com/Sirupsen/logrus/terminal_windows.go
new file mode 100644
index 0000000..7a33630
--- /dev/null
+++ b/vendor/github.com/Sirupsen/logrus/terminal_windows.go
@@ -0,0 +1,82 @@
+// Based on ssh/terminal:
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build windows,!appengine
+
+package logrus
+
+import (
+ "bytes"
+ "errors"
+ "io"
+ "os"
+ "os/exec"
+ "strconv"
+ "strings"
+ "syscall"
+ "unsafe"
+)
+
+var kernel32 = syscall.NewLazyDLL("kernel32.dll")
+
+var (
+ procGetConsoleMode = kernel32.NewProc("GetConsoleMode")
+ procSetConsoleMode = kernel32.NewProc("SetConsoleMode")
+)
+
+const (
+ enableProcessedOutput = 0x0001
+ enableWrapAtEolOutput = 0x0002
+ enableVirtualTerminalProcessing = 0x0004
+)
+
+func getVersion() (float64, error) {
+ stdout, stderr := &bytes.Buffer{}, &bytes.Buffer{}
+ cmd := exec.Command("cmd", "ver")
+ cmd.Stdout = stdout
+ cmd.Stderr = stderr
+ err := cmd.Run()
+ if err != nil {
+ return -1, err
+ }
+
+ // The output should be like "Microsoft Windows [Version XX.X.XXXXXX]"
+ version := strings.Replace(stdout.String(), "\n", "", -1)
+ version = strings.Replace(version, "\r\n", "", -1)
+
+ x1 := strings.Index(version, "[Version")
+
+ if x1 == -1 || strings.Index(version, "]") == -1 {
+ return -1, errors.New("Can't determine Windows version")
+ }
+
+ return strconv.ParseFloat(version[x1+9:x1+13], 64)
+}
+
+func init() {
+ ver, err := getVersion()
+ if err != nil {
+ return
+ }
+
+ // Activate Virtual Processing for Windows CMD
+ // Info: https://msdn.microsoft.com/en-us/library/windows/desktop/ms686033(v=vs.85).aspx
+ if ver >= 10 {
+ handle := syscall.Handle(os.Stderr.Fd())
+ procSetConsoleMode.Call(uintptr(handle), enableProcessedOutput|enableWrapAtEolOutput|enableVirtualTerminalProcessing)
+ }
+}
+
+// IsTerminal returns true if stderr's file descriptor is a terminal.
+func IsTerminal(f io.Writer) bool {
+ switch v := f.(type) {
+ case *os.File:
+ var st uint32
+ r, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, uintptr(v.Fd()), uintptr(unsafe.Pointer(&st)), 0)
+ return r != 0 && e == 0
+ default:
+ return false
+ }
+}
diff --git a/vendor/github.com/Sirupsen/logrus/text_formatter.go b/vendor/github.com/Sirupsen/logrus/text_formatter.go
new file mode 100644
index 0000000..ba88854
--- /dev/null
+++ b/vendor/github.com/Sirupsen/logrus/text_formatter.go
@@ -0,0 +1,189 @@
+package logrus
+
+import (
+ "bytes"
+ "fmt"
+ "sort"
+ "strings"
+ "sync"
+ "time"
+)
+
+const (
+ nocolor = 0
+ red = 31
+ green = 32
+ yellow = 33
+ blue = 34
+ gray = 37
+)
+
+var (
+ baseTimestamp time.Time
+)
+
+func init() {
+ baseTimestamp = time.Now()
+}
+
+type TextFormatter struct {
+ // Set to true to bypass checking for a TTY before outputting colors.
+ ForceColors bool
+
+ // Force disabling colors.
+ DisableColors bool
+
+ // Disable timestamp logging. useful when output is redirected to logging
+ // system that already adds timestamps.
+ DisableTimestamp bool
+
+ // Enable logging the full timestamp when a TTY is attached instead of just
+ // the time passed since beginning of execution.
+ FullTimestamp bool
+
+ // TimestampFormat to use for display when a full timestamp is printed
+ TimestampFormat string
+
+ // The fields are sorted by default for a consistent output. For applications
+ // that log extremely frequently and don't use the JSON formatter this may not
+ // be desired.
+ DisableSorting bool
+
+ // QuoteEmptyFields will wrap empty fields in quotes if true
+ QuoteEmptyFields bool
+
+ // QuoteCharacter can be set to the override the default quoting character "
+ // with something else. For example: ', or `.
+ QuoteCharacter string
+
+ // Whether the logger's out is to a terminal
+ isTerminal bool
+
+ sync.Once
+}
+
+func (f *TextFormatter) init(entry *Entry) {
+ if len(f.QuoteCharacter) == 0 {
+ f.QuoteCharacter = "\""
+ }
+ if entry.Logger != nil {
+ f.isTerminal = IsTerminal(entry.Logger.Out)
+ }
+}
+
+func (f *TextFormatter) Format(entry *Entry) ([]byte, error) {
+ var b *bytes.Buffer
+ keys := make([]string, 0, len(entry.Data))
+ for k := range entry.Data {
+ keys = append(keys, k)
+ }
+
+ if !f.DisableSorting {
+ sort.Strings(keys)
+ }
+ if entry.Buffer != nil {
+ b = entry.Buffer
+ } else {
+ b = &bytes.Buffer{}
+ }
+
+ prefixFieldClashes(entry.Data)
+
+ f.Do(func() { f.init(entry) })
+
+ isColored := (f.ForceColors || f.isTerminal) && !f.DisableColors
+
+ timestampFormat := f.TimestampFormat
+ if timestampFormat == "" {
+ timestampFormat = DefaultTimestampFormat
+ }
+ if isColored {
+ f.printColored(b, entry, keys, timestampFormat)
+ } else {
+ if !f.DisableTimestamp {
+ f.appendKeyValue(b, "time", entry.Time.Format(timestampFormat))
+ }
+ f.appendKeyValue(b, "level", entry.Level.String())
+ if entry.Message != "" {
+ f.appendKeyValue(b, "msg", entry.Message)
+ }
+ for _, key := range keys {
+ f.appendKeyValue(b, key, entry.Data[key])
+ }
+ }
+
+ b.WriteByte('\n')
+ return b.Bytes(), nil
+}
+
+func (f *TextFormatter) printColored(b *bytes.Buffer, entry *Entry, keys []string, timestampFormat string) {
+ var levelColor int
+ switch entry.Level {
+ case DebugLevel:
+ levelColor = gray
+ case WarnLevel:
+ levelColor = yellow
+ case ErrorLevel, FatalLevel, PanicLevel:
+ levelColor = red
+ default:
+ levelColor = blue
+ }
+
+ levelText := strings.ToUpper(entry.Level.String())[0:4]
+
+ if f.DisableTimestamp {
+ fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m %-44s ", levelColor, levelText, entry.Message)
+ } else if !f.FullTimestamp {
+ fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%04d] %-44s ", levelColor, levelText, int(entry.Time.Sub(baseTimestamp)/time.Second), entry.Message)
+ } else {
+ fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%s] %-44s ", levelColor, levelText, entry.Time.Format(timestampFormat), entry.Message)
+ }
+ for _, k := range keys {
+ v := entry.Data[k]
+ fmt.Fprintf(b, " \x1b[%dm%s\x1b[0m=", levelColor, k)
+ f.appendValue(b, v)
+ }
+}
+
+func (f *TextFormatter) needsQuoting(text string) bool {
+ if f.QuoteEmptyFields && len(text) == 0 {
+ return true
+ }
+ for _, ch := range text {
+ if !((ch >= 'a' && ch <= 'z') ||
+ (ch >= 'A' && ch <= 'Z') ||
+ (ch >= '0' && ch <= '9') ||
+ ch == '-' || ch == '.') {
+ return true
+ }
+ }
+ return false
+}
+
+func (f *TextFormatter) appendKeyValue(b *bytes.Buffer, key string, value interface{}) {
+
+ b.WriteString(key)
+ b.WriteByte('=')
+ f.appendValue(b, value)
+ b.WriteByte(' ')
+}
+
+func (f *TextFormatter) appendValue(b *bytes.Buffer, value interface{}) {
+ switch value := value.(type) {
+ case string:
+ if !f.needsQuoting(value) {
+ b.WriteString(value)
+ } else {
+ fmt.Fprintf(b, "%s%v%s", f.QuoteCharacter, value, f.QuoteCharacter)
+ }
+ case error:
+ errmsg := value.Error()
+ if !f.needsQuoting(errmsg) {
+ b.WriteString(errmsg)
+ } else {
+ fmt.Fprintf(b, "%s%v%s", f.QuoteCharacter, errmsg, f.QuoteCharacter)
+ }
+ default:
+ fmt.Fprint(b, value)
+ }
+}
diff --git a/vendor/github.com/Sirupsen/logrus/text_formatter_test.go b/vendor/github.com/Sirupsen/logrus/text_formatter_test.go
new file mode 100644
index 0000000..9793b5f
--- /dev/null
+++ b/vendor/github.com/Sirupsen/logrus/text_formatter_test.go
@@ -0,0 +1,87 @@
+package logrus
+
+import (
+ "bytes"
+ "errors"
+ "strings"
+ "testing"
+ "time"
+)
+
+func TestQuoting(t *testing.T) {
+ tf := &TextFormatter{DisableColors: true}
+
+ checkQuoting := func(q bool, value interface{}) {
+ b, _ := tf.Format(WithField("test", value))
+ idx := bytes.Index(b, ([]byte)("test="))
+ cont := bytes.Contains(b[idx+5:], []byte(tf.QuoteCharacter))
+ if cont != q {
+ if q {
+ t.Errorf("quoting expected for: %#v", value)
+ } else {
+ t.Errorf("quoting not expected for: %#v", value)
+ }
+ }
+ }
+
+ checkQuoting(false, "")
+ checkQuoting(false, "abcd")
+ checkQuoting(false, "v1.0")
+ checkQuoting(false, "1234567890")
+ checkQuoting(true, "/foobar")
+ checkQuoting(true, "x y")
+ checkQuoting(true, "x,y")
+ checkQuoting(false, errors.New("invalid"))
+ checkQuoting(true, errors.New("invalid argument"))
+
+ // Test for custom quote character.
+ tf.QuoteCharacter = "`"
+ checkQuoting(false, "")
+ checkQuoting(false, "abcd")
+ checkQuoting(true, "/foobar")
+ checkQuoting(true, errors.New("invalid argument"))
+
+ // Test for multi-character quotes.
+ tf.QuoteCharacter = "§~±"
+ checkQuoting(false, "abcd")
+ checkQuoting(true, errors.New("invalid argument"))
+
+ // Test for quoting empty fields.
+ tf.QuoteEmptyFields = true
+ checkQuoting(true, "")
+ checkQuoting(false, "abcd")
+ checkQuoting(true, errors.New("invalid argument"))
+}
+
+func TestTimestampFormat(t *testing.T) {
+ checkTimeStr := func(format string) {
+ customFormatter := &TextFormatter{DisableColors: true, TimestampFormat: format}
+ customStr, _ := customFormatter.Format(WithField("test", "test"))
+ timeStart := bytes.Index(customStr, ([]byte)("time="))
+ timeEnd := bytes.Index(customStr, ([]byte)("level="))
+ timeStr := customStr[timeStart+5+len(customFormatter.QuoteCharacter) : timeEnd-1-len(customFormatter.QuoteCharacter)]
+ if format == "" {
+ format = time.RFC3339
+ }
+ _, e := time.Parse(format, (string)(timeStr))
+ if e != nil {
+ t.Errorf("time string \"%s\" did not match provided time format \"%s\": %s", timeStr, format, e)
+ }
+ }
+
+ checkTimeStr("2006-01-02T15:04:05.000000000Z07:00")
+ checkTimeStr("Mon Jan _2 15:04:05 2006")
+ checkTimeStr("")
+}
+
+func TestDisableTimestampWithColoredOutput(t *testing.T) {
+ tf := &TextFormatter{DisableTimestamp: true, ForceColors: true}
+
+ b, _ := tf.Format(WithField("test", "test"))
+ if strings.Contains(string(b), "[0000]") {
+ t.Error("timestamp not expected when DisableTimestamp is true")
+ }
+}
+
+// TODO add tests for sorting etc., this requires a parser for the text
+// formatter output.
diff --git a/vendor/github.com/Sirupsen/logrus/writer.go b/vendor/github.com/Sirupsen/logrus/writer.go
new file mode 100644
index 0000000..7bdebed
--- /dev/null
+++ b/vendor/github.com/Sirupsen/logrus/writer.go
@@ -0,0 +1,62 @@
+package logrus
+
+import (
+ "bufio"
+ "io"
+ "runtime"
+)
+
+func (logger *Logger) Writer() *io.PipeWriter {
+ return logger.WriterLevel(InfoLevel)
+}
+
+func (logger *Logger) WriterLevel(level Level) *io.PipeWriter {
+ return NewEntry(logger).WriterLevel(level)
+}
+
+func (entry *Entry) Writer() *io.PipeWriter {
+ return entry.WriterLevel(InfoLevel)
+}
+
+func (entry *Entry) WriterLevel(level Level) *io.PipeWriter {
+ reader, writer := io.Pipe()
+
+ var printFunc func(args ...interface{})
+
+ switch level {
+ case DebugLevel:
+ printFunc = entry.Debug
+ case InfoLevel:
+ printFunc = entry.Info
+ case WarnLevel:
+ printFunc = entry.Warn
+ case ErrorLevel:
+ printFunc = entry.Error
+ case FatalLevel:
+ printFunc = entry.Fatal
+ case PanicLevel:
+ printFunc = entry.Panic
+ default:
+ printFunc = entry.Print
+ }
+
+ go entry.writerScanner(reader, printFunc)
+ runtime.SetFinalizer(writer, writerFinalizer)
+
+ return writer
+}
+
+func (entry *Entry) writerScanner(reader *io.PipeReader, printFunc func(args ...interface{})) {
+ scanner := bufio.NewScanner(reader)
+ for scanner.Scan() {
+ printFunc(scanner.Text())
+ }
+ if err := scanner.Err(); err != nil {
+ entry.Errorf("Error while reading from Writer: %s", err)
+ }
+ reader.Close()
+}
+
+func writerFinalizer(writer *io.PipeWriter) {
+ writer.Close()
+}
diff --git a/vendor/golang.org/x/crypto/acme/acme.go b/vendor/golang.org/x/crypto/acme/acme.go
index 8aafada..a7b6ce4 100644
--- a/vendor/golang.org/x/crypto/acme/acme.go
+++ b/vendor/golang.org/x/crypto/acme/acme.go
@@ -15,6 +15,7 @@ package acme
import (
"bytes"
+ "context"
"crypto"
"crypto/ecdsa"
"crypto/elliptic"
@@ -36,9 +37,6 @@ import (
"strings"
"sync"
"time"
-
- "golang.org/x/net/context"
- "golang.org/x/net/context/ctxhttp"
)
// LetsEncryptURL is the Directory endpoint of Let's Encrypt CA.
@@ -47,6 +45,10 @@ const LetsEncryptURL = "https://acme-v01.api.letsencrypt.org/directory"
const (
maxChainLen = 5 // max depth and breadth of a certificate chain
maxCertSize = 1 << 20 // max size of a certificate, in bytes
+
+ // Max number of collected nonces kept in memory.
+ // Expect usual peak of 1 or 2.
+ maxNonces = 100
)
// CertOption is an optional argument type for Client methods which manipulate
@@ -108,6 +110,9 @@ type Client struct {
dirMu sync.Mutex // guards writes to dir
dir *Directory // cached result of Client's Discover method
+
+ noncesMu sync.Mutex
+ nonces map[string]struct{} // nonces collected from previous responses
}
// Discover performs ACME server discovery using c.DirectoryURL.
@@ -126,11 +131,12 @@ func (c *Client) Discover(ctx context.Context) (Directory, error) {
if dirURL == "" {
dirURL = LetsEncryptURL
}
- res, err := ctxhttp.Get(ctx, c.HTTPClient, dirURL)
+ res, err := c.get(ctx, dirURL)
if err != nil {
return Directory{}, err
}
defer res.Body.Close()
+ c.addNonce(res.Header)
if res.StatusCode != http.StatusOK {
return Directory{}, responseError(res)
}
@@ -146,7 +152,7 @@ func (c *Client) Discover(ctx context.Context) (Directory, error) {
CAA []string `json:"caa-identities"`
}
}
- if json.NewDecoder(res.Body).Decode(&v); err != nil {
+ if err := json.NewDecoder(res.Body).Decode(&v); err != nil {
return Directory{}, err
}
c.dir = &Directory{
@@ -192,7 +198,7 @@ func (c *Client) CreateCert(ctx context.Context, csr []byte, exp time.Duration,
req.NotAfter = now.Add(exp).Format(time.RFC3339)
}
- res, err := postJWS(ctx, c.HTTPClient, c.Key, c.dir.CertURL, req)
+ res, err := c.retryPostJWS(ctx, c.Key, c.dir.CertURL, req)
if err != nil {
return nil, "", err
}
@@ -208,7 +214,7 @@ func (c *Client) CreateCert(ctx context.Context, csr []byte, exp time.Duration,
return cert, curl, err
}
// slurp issued cert and CA chain, if requested
- cert, err := responseCert(ctx, c.HTTPClient, res, bundle)
+ cert, err := c.responseCert(ctx, res, bundle)
return cert, curl, err
}
@@ -223,13 +229,13 @@ func (c *Client) CreateCert(ctx context.Context, csr []byte, exp time.Duration,
// and has expected features.
func (c *Client) FetchCert(ctx context.Context, url string, bundle bool) ([][]byte, error) {
for {
- res, err := ctxhttp.Get(ctx, c.HTTPClient, url)
+ res, err := c.get(ctx, url)
if err != nil {
return nil, err
}
defer res.Body.Close()
if res.StatusCode == http.StatusOK {
- return responseCert(ctx, c.HTTPClient, res, bundle)
+ return c.responseCert(ctx, res, bundle)
}
if res.StatusCode > 299 {
return nil, responseError(res)
@@ -267,7 +273,7 @@ func (c *Client) RevokeCert(ctx context.Context, key crypto.Signer, cert []byte,
if key == nil {
key = c.Key
}
- res, err := postJWS(ctx, c.HTTPClient, key, c.dir.RevokeURL, body)
+ res, err := c.retryPostJWS(ctx, key, c.dir.RevokeURL, body)
if err != nil {
return err
}
@@ -355,7 +361,7 @@ func (c *Client) Authorize(ctx context.Context, domain string) (*Authorization,
Resource: "new-authz",
Identifier: authzID{Type: "dns", Value: domain},
}
- res, err := postJWS(ctx, c.HTTPClient, c.Key, c.dir.AuthzURL, req)
+ res, err := c.retryPostJWS(ctx, c.Key, c.dir.AuthzURL, req)
if err != nil {
return nil, err
}
@@ -379,7 +385,7 @@ func (c *Client) Authorize(ctx context.Context, domain string) (*Authorization,
// If a caller needs to poll an authorization until its status is final,
// see the WaitAuthorization method.
func (c *Client) GetAuthorization(ctx context.Context, url string) (*Authorization, error) {
- res, err := ctxhttp.Get(ctx, c.HTTPClient, url)
+ res, err := c.get(ctx, url)
if err != nil {
return nil, err
}
@@ -413,7 +419,7 @@ func (c *Client) RevokeAuthorization(ctx context.Context, url string) error {
Status: "deactivated",
Delete: true,
}
- res, err := postJWS(ctx, c.HTTPClient, c.Key, url, req)
+ res, err := c.retryPostJWS(ctx, c.Key, url, req)
if err != nil {
return err
}
@@ -430,25 +436,11 @@ func (c *Client) RevokeAuthorization(ctx context.Context, url string) error {
//
// It returns a non-nil Authorization only if its Status is StatusValid.
// In all other cases WaitAuthorization returns an error.
-// If the Status is StatusInvalid, the returned error is ErrAuthorizationFailed.
+// If the Status is StatusInvalid, the returned error is of type *AuthorizationError.
func (c *Client) WaitAuthorization(ctx context.Context, url string) (*Authorization, error) {
- var count int
- sleep := func(v string, inc int) error {
- count += inc
- d := backoff(count, 10*time.Second)
- d = retryAfter(v, d)
- wakeup := time.NewTimer(d)
- defer wakeup.Stop()
- select {
- case <-ctx.Done():
- return ctx.Err()
- case <-wakeup.C:
- return nil
- }
- }
-
+ sleep := sleeper(ctx)
for {
- res, err := ctxhttp.Get(ctx, c.HTTPClient, url)
+ res, err := c.get(ctx, url)
if err != nil {
return nil, err
}
@@ -473,7 +465,7 @@ func (c *Client) WaitAuthorization(ctx context.Context, url string) (*Authorizat
return raw.authorization(url), nil
}
if raw.Status == StatusInvalid {
- return nil, ErrAuthorizationFailed
+ return nil, raw.error(url)
}
if err := sleep(retry, 0); err != nil {
return nil, err
@@ -485,7 +477,7 @@ func (c *Client) WaitAuthorization(ctx context.Context, url string) (*Authorizat
//
// A client typically polls a challenge status using this method.
func (c *Client) GetChallenge(ctx context.Context, url string) (*Challenge, error) {
- res, err := ctxhttp.Get(ctx, c.HTTPClient, url)
+ res, err := c.get(ctx, url)
if err != nil {
return nil, err
}
@@ -519,7 +511,7 @@ func (c *Client) Accept(ctx context.Context, chal *Challenge) (*Challenge, error
Type: chal.Type,
Auth: auth,
}
- res, err := postJWS(ctx, c.HTTPClient, c.Key, chal.URI, req)
+ res, err := c.retryPostJWS(ctx, c.Key, chal.URI, req)
if err != nil {
return nil, err
}
@@ -652,7 +644,7 @@ func (c *Client) doReg(ctx context.Context, url string, typ string, acct *Accoun
req.Contact = acct.Contact
req.Agreement = acct.AgreedTerms
}
- res, err := postJWS(ctx, c.HTTPClient, c.Key, url, req)
+ res, err := c.retryPostJWS(ctx, c.Key, url, req)
if err != nil {
return nil, err
}
@@ -689,7 +681,170 @@ func (c *Client) doReg(ctx context.Context, url string, typ string, acct *Accoun
}, nil
}
-func responseCert(ctx context.Context, client *http.Client, res *http.Response, bundle bool) ([][]byte, error) {
+// retryPostJWS will retry calls to postJWS if there is a badNonce error,
+// clearing the stored nonces after each error.
+// If the response was 4XX-5XX, then responseError is called on the body,
+// the body is closed, and the error returned.
+func (c *Client) retryPostJWS(ctx context.Context, key crypto.Signer, url string, body interface{}) (*http.Response, error) {
+ sleep := sleeper(ctx)
+ for {
+ res, err := c.postJWS(ctx, key, url, body)
+ if err != nil {
+ return nil, err
+ }
+ // handle errors 4XX-5XX with responseError
+ if res.StatusCode >= 400 && res.StatusCode <= 599 {
+ err := responseError(res)
+ res.Body.Close()
+ // according to spec badNonce is urn:ietf:params:acme:error:badNonce
+ // however, acme servers in the wild return their version of the error
+ // https://tools.ietf.org/html/draft-ietf-acme-acme-02#section-5.4
+ if ae, ok := err.(*Error); ok && strings.HasSuffix(strings.ToLower(ae.ProblemType), ":badnonce") {
+ // clear any nonces that we might've stored that might now be
+ // considered bad
+ c.clearNonces()
+ retry := res.Header.Get("retry-after")
+ if err := sleep(retry, 1); err != nil {
+ return nil, err
+ }
+ continue
+ }
+ return nil, err
+ }
+ return res, nil
+ }
+}
+
+// postJWS signs the body with the given key and POSTs it to the provided url.
+// The body argument must be JSON-serializable.
+func (c *Client) postJWS(ctx context.Context, key crypto.Signer, url string, body interface{}) (*http.Response, error) {
+ nonce, err := c.popNonce(ctx, url)
+ if err != nil {
+ return nil, err
+ }
+ b, err := jwsEncodeJSON(body, key, nonce)
+ if err != nil {
+ return nil, err
+ }
+ res, err := c.post(ctx, url, "application/jose+json", bytes.NewReader(b))
+ if err != nil {
+ return nil, err
+ }
+ c.addNonce(res.Header)
+ return res, nil
+}
+
+// popNonce returns a nonce value previously stored with c.addNonce
+// or fetches a fresh one from the given URL.
+func (c *Client) popNonce(ctx context.Context, url string) (string, error) {
+ c.noncesMu.Lock()
+ defer c.noncesMu.Unlock()
+ if len(c.nonces) == 0 {
+ return c.fetchNonce(ctx, url)
+ }
+ var nonce string
+ for nonce = range c.nonces {
+ delete(c.nonces, nonce)
+ break
+ }
+ return nonce, nil
+}
+
+// clearNonces clears any stored nonces
+func (c *Client) clearNonces() {
+ c.noncesMu.Lock()
+ defer c.noncesMu.Unlock()
+ c.nonces = make(map[string]struct{})
+}
+
+// addNonce stores a nonce value found in h (if any) for future use.
+func (c *Client) addNonce(h http.Header) {
+ v := nonceFromHeader(h)
+ if v == "" {
+ return
+ }
+ c.noncesMu.Lock()
+ defer c.noncesMu.Unlock()
+ if len(c.nonces) >= maxNonces {
+ return
+ }
+ if c.nonces == nil {
+ c.nonces = make(map[string]struct{})
+ }
+ c.nonces[v] = struct{}{}
+}
+
+func (c *Client) httpClient() *http.Client {
+ if c.HTTPClient != nil {
+ return c.HTTPClient
+ }
+ return http.DefaultClient
+}
+
+func (c *Client) get(ctx context.Context, urlStr string) (*http.Response, error) {
+ req, err := http.NewRequest("GET", urlStr, nil)
+ if err != nil {
+ return nil, err
+ }
+ return c.do(ctx, req)
+}
+
+func (c *Client) head(ctx context.Context, urlStr string) (*http.Response, error) {
+ req, err := http.NewRequest("HEAD", urlStr, nil)
+ if err != nil {
+ return nil, err
+ }
+ return c.do(ctx, req)
+}
+
+func (c *Client) post(ctx context.Context, urlStr, contentType string, body io.Reader) (*http.Response, error) {
+ req, err := http.NewRequest("POST", urlStr, body)
+ if err != nil {
+ return nil, err
+ }
+ req.Header.Set("Content-Type", contentType)
+ return c.do(ctx, req)
+}
+
+func (c *Client) do(ctx context.Context, req *http.Request) (*http.Response, error) {
+ res, err := c.httpClient().Do(req.WithContext(ctx))
+ if err != nil {
+ select {
+ case <-ctx.Done():
+ // Prefer the unadorned context error.
+ // (The acme package had tests assuming this, previously from ctxhttp's
+ // behavior, predating net/http supporting contexts natively)
+ // TODO(bradfitz): reconsider this in the future. But for now this
+ // requires no test updates.
+ return nil, ctx.Err()
+ default:
+ return nil, err
+ }
+ }
+ return res, nil
+}
+
+func (c *Client) fetchNonce(ctx context.Context, url string) (string, error) {
+ resp, err := c.head(ctx, url)
+ if err != nil {
+ return "", err
+ }
+ defer resp.Body.Close()
+ nonce := nonceFromHeader(resp.Header)
+ if nonce == "" {
+ if resp.StatusCode > 299 {
+ return "", responseError(resp)
+ }
+ return "", errors.New("acme: nonce not found")
+ }
+ return nonce, nil
+}
+
+func nonceFromHeader(h http.Header) string {
+ return h.Get("Replay-Nonce")
+}
+
+func (c *Client) responseCert(ctx context.Context, res *http.Response, bundle bool) ([][]byte, error) {
b, err := ioutil.ReadAll(io.LimitReader(res.Body, maxCertSize+1))
if err != nil {
return nil, fmt.Errorf("acme: response stream: %v", err)
@@ -713,7 +868,7 @@ func responseCert(ctx context.Context, client *http.Client, res *http.Response,
return nil, errors.New("acme: rel=up link is too large")
}
for _, url := range up {
- cc, err := chainCert(ctx, client, url, 0)
+ cc, err := c.chainCert(ctx, url, 0)
if err != nil {
return nil, err
}
@@ -727,14 +882,8 @@ func responseError(resp *http.Response) error {
// don't care if ReadAll returns an error:
// json.Unmarshal will fail in that case anyway
b, _ := ioutil.ReadAll(resp.Body)
- e := struct {
- Status int
- Type string
- Detail string
- }{
- Status: resp.StatusCode,
- }
- if err := json.Unmarshal(b, &e); err != nil {
+ e := &wireError{Status: resp.StatusCode}
+ if err := json.Unmarshal(b, e); err != nil {
// this is not a regular error response:
// populate detail with anything we received,
// e.Status will already contain HTTP response code value
@@ -743,12 +892,7 @@ func responseError(resp *http.Response) error {
e.Detail = resp.Status
}
}
- return &Error{
- StatusCode: e.Status,
- ProblemType: e.Type,
- Detail: e.Detail,
- Header: resp.Header,
- }
+ return e.error(resp.Header)
}
// chainCert fetches CA certificate chain recursively by following "up" links.
@@ -756,12 +900,12 @@ func responseError(resp *http.Response) error {
// if the recursion level reaches maxChainLen.
//
// First chainCert call starts with depth of 0.
-func chainCert(ctx context.Context, client *http.Client, url string, depth int) ([][]byte, error) {
+func (c *Client) chainCert(ctx context.Context, url string, depth int) ([][]byte, error) {
if depth >= maxChainLen {
return nil, errors.New("acme: certificate chain is too deep")
}
- res, err := ctxhttp.Get(ctx, client, url)
+ res, err := c.get(ctx, url)
if err != nil {
return nil, err
}
@@ -783,7 +927,7 @@ func chainCert(ctx context.Context, client *http.Client, url string, depth int)
return nil, errors.New("acme: certificate chain is too large")
}
for _, up := range uplink {
- cc, err := chainCert(ctx, client, up, depth+1)
+ cc, err := c.chainCert(ctx, up, depth+1)
if err != nil {
return nil, err
}
@@ -793,33 +937,6 @@ func chainCert(ctx context.Context, client *http.Client, url string, depth int)
return chain, nil
}
-// postJWS signs the body with the given key and POSTs it to the provided url.
-// The body argument must be JSON-serializable.
-func postJWS(ctx context.Context, client *http.Client, key crypto.Signer, url string, body interface{}) (*http.Response, error) {
- nonce, err := fetchNonce(ctx, client, url)
- if err != nil {
- return nil, err
- }
- b, err := jwsEncodeJSON(body, key, nonce)
- if err != nil {
- return nil, err
- }
- return ctxhttp.Post(ctx, client, url, "application/jose+json", bytes.NewReader(b))
-}
-
-func fetchNonce(ctx context.Context, client *http.Client, url string) (string, error) {
- resp, err := ctxhttp.Head(ctx, client, url)
- if err != nil {
- return "", nil
- }
- defer resp.Body.Close()
- enc := resp.Header.Get("replay-nonce")
- if enc == "" {
- return "", errors.New("acme: nonce not found")
- }
- return enc, nil
-}
-
// linkHeader returns URI-Reference values of all Link headers
// with relation-type rel.
// See https://tools.ietf.org/html/rfc5988#section-5 for details.
@@ -840,6 +957,28 @@ func linkHeader(h http.Header, rel string) []string {
return links
}
+// sleeper returns a function that accepts the Retry-After HTTP header value
+// and an increment that's used with backoff to increasingly sleep on
+// consecutive calls until the context is done. If the Retry-After header
+// cannot be parsed, then backoff is used with a maximum sleep time of 10
+// seconds.
+func sleeper(ctx context.Context) func(ra string, inc int) error {
+ var count int
+ return func(ra string, inc int) error {
+ count += inc
+ d := backoff(count, 10*time.Second)
+ d = retryAfter(ra, d)
+ wakeup := time.NewTimer(d)
+ defer wakeup.Stop()
+ select {
+ case <-ctx.Done():
+ return ctx.Err()
+ case <-wakeup.C:
+ return nil
+ }
+ }
+}
+
// retryAfter parses a Retry-After HTTP header value,
// trying to convert v into an int (seconds) or use http.ParseTime otherwise.
// It returns d if v cannot be parsed.
@@ -921,7 +1060,8 @@ func tlsChallengeCert(san []string, opt []CertOption) (tls.Certificate, error) {
NotBefore: time.Now(),
NotAfter: time.Now().Add(24 * time.Hour),
BasicConstraintsValid: true,
- KeyUsage: x509.KeyUsageKeyEncipherment,
+ KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
+ ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
}
}
tmpl.DNSNames = san
diff --git a/vendor/golang.org/x/crypto/acme/acme_test.go b/vendor/golang.org/x/crypto/acme/acme_test.go
index 4e618f2..a4d276d 100644
--- a/vendor/golang.org/x/crypto/acme/acme_test.go
+++ b/vendor/golang.org/x/crypto/acme/acme_test.go
@@ -6,6 +6,7 @@ package acme
import (
"bytes"
+ "context"
"crypto/rand"
"crypto/rsa"
"crypto/tls"
@@ -23,8 +24,6 @@ import (
"strings"
"testing"
"time"
-
- "golang.org/x/net/context"
)
// Decodes a JWS-encoded request and unmarshals the decoded JSON into a provided
@@ -45,6 +44,28 @@ func decodeJWSRequest(t *testing.T, v interface{}, r *http.Request) {
}
}
+type jwsHead struct {
+ Alg string
+ Nonce string
+ JWK map[string]string `json:"jwk"`
+}
+
+func decodeJWSHead(r *http.Request) (*jwsHead, error) {
+ var req struct{ Protected string }
+ if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
+ return nil, err
+ }
+ b, err := base64.RawURLEncoding.DecodeString(req.Protected)
+ if err != nil {
+ return nil, err
+ }
+ var head jwsHead
+ if err := json.Unmarshal(b, &head); err != nil {
+ return nil, err
+ }
+ return &head, nil
+}
+
func TestDiscover(t *testing.T) {
const (
reg = "https://example.com/acme/new-reg"
@@ -522,6 +543,9 @@ func TestWaitAuthorizationInvalid(t *testing.T) {
if err == nil {
t.Error("err is nil")
}
+ if _, ok := err.(*AuthorizationError); !ok {
+ t.Errorf("err is %T; want *AuthorizationError", err)
+ }
}
}
@@ -916,7 +940,30 @@ func TestRevokeCert(t *testing.T) {
}
}
-func TestFetchNonce(t *testing.T) {
+func TestNonce_add(t *testing.T) {
+ var c Client
+ c.addNonce(http.Header{"Replay-Nonce": {"nonce"}})
+ c.addNonce(http.Header{"Replay-Nonce": {}})
+ c.addNonce(http.Header{"Replay-Nonce": {"nonce"}})
+
+ nonces := map[string]struct{}{"nonce": struct{}{}}
+ if !reflect.DeepEqual(c.nonces, nonces) {
+ t.Errorf("c.nonces = %q; want %q", c.nonces, nonces)
+ }
+}
+
+func TestNonce_addMax(t *testing.T) {
+ c := &Client{nonces: make(map[string]struct{})}
+ for i := 0; i < maxNonces; i++ {
+ c.nonces[fmt.Sprintf("%d", i)] = struct{}{}
+ }
+ c.addNonce(http.Header{"Replay-Nonce": {"nonce"}})
+ if n := len(c.nonces); n != maxNonces {
+ t.Errorf("len(c.nonces) = %d; want %d", n, maxNonces)
+ }
+}
+
+func TestNonce_fetch(t *testing.T) {
tests := []struct {
code int
nonce string
@@ -936,7 +983,8 @@ func TestFetchNonce(t *testing.T) {
defer ts.Close()
for ; i < len(tests); i++ {
test := tests[i]
- n, err := fetchNonce(context.Background(), http.DefaultClient, ts.URL)
+ c := &Client{}
+ n, err := c.fetchNonce(context.Background(), ts.URL)
if n != test.nonce {
t.Errorf("%d: n=%q; want %q", i, n, test.nonce)
}
@@ -949,6 +997,115 @@ func TestFetchNonce(t *testing.T) {
}
}
+func TestNonce_fetchError(t *testing.T) {
+ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.WriteHeader(http.StatusTooManyRequests)
+ }))
+ defer ts.Close()
+ c := &Client{}
+ _, err := c.fetchNonce(context.Background(), ts.URL)
+ e, ok := err.(*Error)
+ if !ok {
+ t.Fatalf("err is %T; want *Error", err)
+ }
+ if e.StatusCode != http.StatusTooManyRequests {
+ t.Errorf("e.StatusCode = %d; want %d", e.StatusCode, http.StatusTooManyRequests)
+ }
+}
+
+func TestNonce_postJWS(t *testing.T) {
+ var count int
+ seen := make(map[string]bool)
+ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ count++
+ w.Header().Set("replay-nonce", fmt.Sprintf("nonce%d", count))
+ if r.Method == "HEAD" {
+ // We expect the client do a HEAD request
+ // but only to fetch the first nonce.
+ return
+ }
+ // Make client.Authorize happy; we're not testing its result.
+ defer func() {
+ w.WriteHeader(http.StatusCreated)
+ w.Write([]byte(`{"status":"valid"}`))
+ }()
+
+ head, err := decodeJWSHead(r)
+ if err != nil {
+ t.Errorf("decodeJWSHead: %v", err)
+ return
+ }
+ if head.Nonce == "" {
+ t.Error("head.Nonce is empty")
+ return
+ }
+ if seen[head.Nonce] {
+ t.Errorf("nonce is already used: %q", head.Nonce)
+ }
+ seen[head.Nonce] = true
+ }))
+ defer ts.Close()
+
+ client := Client{Key: testKey, dir: &Directory{AuthzURL: ts.URL}}
+ if _, err := client.Authorize(context.Background(), "example.com"); err != nil {
+ t.Errorf("client.Authorize 1: %v", err)
+ }
+ // The second call should not generate another extra HEAD request.
+ if _, err := client.Authorize(context.Background(), "example.com"); err != nil {
+ t.Errorf("client.Authorize 2: %v", err)
+ }
+
+ if count != 3 {
+ t.Errorf("total requests count: %d; want 3", count)
+ }
+ if n := len(client.nonces); n != 1 {
+ t.Errorf("len(client.nonces) = %d; want 1", n)
+ }
+ for k := range seen {
+ if _, exist := client.nonces[k]; exist {
+ t.Errorf("used nonce %q in client.nonces", k)
+ }
+ }
+}
+
+func TestRetryPostJWS(t *testing.T) {
+ var count int
+ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ count++
+ w.Header().Set("replay-nonce", fmt.Sprintf("nonce%d", count))
+ if r.Method == "HEAD" {
+ // We expect the client to do 2 head requests to fetch
+ // nonces, one to start and another after getting badNonce
+ return
+ }
+
+ head, err := decodeJWSHead(r)
+ if err != nil {
+ t.Errorf("decodeJWSHead: %v", err)
+ } else if head.Nonce == "" {
+ t.Error("head.Nonce is empty")
+ } else if head.Nonce == "nonce1" {
+ // return a badNonce error to force the call to retry
+ w.WriteHeader(http.StatusBadRequest)
+ w.Write([]byte(`{"type":"urn:ietf:params:acme:error:badNonce"}`))
+ return
+ }
+ // Make client.Authorize happy; we're not testing its result.
+ w.WriteHeader(http.StatusCreated)
+ w.Write([]byte(`{"status":"valid"}`))
+ }))
+ defer ts.Close()
+
+ client := Client{Key: testKey, dir: &Directory{AuthzURL: ts.URL}}
+ // This call will fail with badNonce, causing a retry
+ if _, err := client.Authorize(context.Background(), "example.com"); err != nil {
+ t.Errorf("client.Authorize 1: %v", err)
+ }
+ if count != 4 {
+ t.Errorf("total requests count: %d; want 4", count)
+ }
+}
+
func TestLinkHeader(t *testing.T) {
h := http.Header{"Link": {
`;rel="next"`,
diff --git a/vendor/golang.org/x/crypto/acme/autocert/autocert.go b/vendor/golang.org/x/crypto/acme/autocert/autocert.go
index 4b15816..a478eff 100644
--- a/vendor/golang.org/x/crypto/acme/autocert/autocert.go
+++ b/vendor/golang.org/x/crypto/acme/autocert/autocert.go
@@ -10,6 +10,7 @@ package autocert
import (
"bytes"
+ "context"
"crypto"
"crypto/ecdsa"
"crypto/elliptic"
@@ -30,9 +31,14 @@ import (
"time"
"golang.org/x/crypto/acme"
- "golang.org/x/net/context"
)
+// createCertRetryAfter is how much time to wait before removing a failed state
+// entry due to an unsuccessful createCert call.
+// This is a variable instead of a const for testing.
+// TODO: Consider making it configurable or an exp backoff?
+var createCertRetryAfter = time.Minute
+
// pseudoRand is safe for concurrent use.
var pseudoRand *lockedMathRand
@@ -41,8 +47,9 @@ func init() {
pseudoRand = &lockedMathRand{rnd: mathrand.New(src)}
}
-// AcceptTOS always returns true to indicate the acceptance of a CA Terms of Service
-// during account registration.
+// AcceptTOS is a Manager.Prompt function that always returns true to
+// indicate acceptance of the CA's Terms of Service during account
+// registration.
func AcceptTOS(tosURL string) bool { return true }
// HostPolicy specifies which host names the Manager is allowed to respond to.
@@ -76,18 +83,6 @@ func defaultHostPolicy(context.Context, string) error {
// It obtains and refreshes certificates automatically,
// as well as providing them to a TLS server via tls.Config.
//
-// A simple usage example:
-//
-// m := autocert.Manager{
-// Prompt: autocert.AcceptTOS,
-// HostPolicy: autocert.HostWhitelist("example.org"),
-// }
-// s := &http.Server{
-// Addr: ":https",
-// TLSConfig: &tls.Config{GetCertificate: m.GetCertificate},
-// }
-// s.ListenAndServeTLS("", "")
-//
// To preserve issued certificates and improve overall performance,
// use a cache implementation of Cache. For instance, DirCache.
type Manager struct {
@@ -123,7 +118,7 @@ type Manager struct {
// RenewBefore optionally specifies how early certificates should
// be renewed before they expire.
//
- // If zero, they're renewed 1 week before expiration.
+ // If zero, they're renewed 30 days before expiration.
RenewBefore time.Duration
// Client is used to perform low-level operations, such as account registration
@@ -173,10 +168,23 @@ type Manager struct {
// The error is propagated back to the caller of GetCertificate and is user-visible.
// This does not affect cached certs. See HostPolicy field description for more details.
func (m *Manager) GetCertificate(hello *tls.ClientHelloInfo) (*tls.Certificate, error) {
+ if m.Prompt == nil {
+ return nil, errors.New("acme/autocert: Manager.Prompt not set")
+ }
+
name := hello.ServerName
if name == "" {
return nil, errors.New("acme/autocert: missing server name")
}
+ if !strings.Contains(strings.Trim(name, "."), ".") {
+ return nil, errors.New("acme/autocert: server name component count invalid")
+ }
+ if strings.ContainsAny(name, `/\`) {
+ return nil, errors.New("acme/autocert: server name contains invalid character")
+ }
+
+ ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
+ defer cancel()
// check whether this is a token cert requested for TLS-SNI challenge
if strings.HasSuffix(name, ".acme.invalid") {
@@ -185,7 +193,7 @@ func (m *Manager) GetCertificate(hello *tls.ClientHelloInfo) (*tls.Certificate,
if cert := m.tokenCert[name]; cert != nil {
return cert, nil
}
- if cert, err := m.cacheGet(name); err == nil {
+ if cert, err := m.cacheGet(ctx, name); err == nil {
return cert, nil
}
// TODO: cache error results?
@@ -194,7 +202,7 @@ func (m *Manager) GetCertificate(hello *tls.ClientHelloInfo) (*tls.Certificate,
// regular domain
name = strings.TrimSuffix(name, ".") // golang.org/issue/18114
- cert, err := m.cert(name)
+ cert, err := m.cert(ctx, name)
if err == nil {
return cert, nil
}
@@ -203,7 +211,6 @@ func (m *Manager) GetCertificate(hello *tls.ClientHelloInfo) (*tls.Certificate,
}
// first-time
- ctx := context.Background() // TODO: use a deadline?
if err := m.hostPolicy()(ctx, name); err != nil {
return nil, err
}
@@ -211,14 +218,14 @@ func (m *Manager) GetCertificate(hello *tls.ClientHelloInfo) (*tls.Certificate,
if err != nil {
return nil, err
}
- m.cachePut(name, cert)
+ m.cachePut(ctx, name, cert)
return cert, nil
}
// cert returns an existing certificate either from m.state or cache.
// If a certificate is found in cache but not in m.state, the latter will be filled
// with the cached value.
-func (m *Manager) cert(name string) (*tls.Certificate, error) {
+func (m *Manager) cert(ctx context.Context, name string) (*tls.Certificate, error) {
m.stateMu.Lock()
if s, ok := m.state[name]; ok {
m.stateMu.Unlock()
@@ -227,7 +234,7 @@ func (m *Manager) cert(name string) (*tls.Certificate, error) {
return s.tlscert()
}
defer m.stateMu.Unlock()
- cert, err := m.cacheGet(name)
+ cert, err := m.cacheGet(ctx, name)
if err != nil {
return nil, err
}
@@ -249,12 +256,11 @@ func (m *Manager) cert(name string) (*tls.Certificate, error) {
}
// cacheGet always returns a valid certificate, or an error otherwise.
-func (m *Manager) cacheGet(domain string) (*tls.Certificate, error) {
+// If a cached certficate exists but is not valid, ErrCacheMiss is returned.
+func (m *Manager) cacheGet(ctx context.Context, domain string) (*tls.Certificate, error) {
if m.Cache == nil {
return nil, ErrCacheMiss
}
- // TODO: might want to define a cache timeout on m
- ctx := context.Background()
data, err := m.Cache.Get(ctx, domain)
if err != nil {
return nil, err
@@ -263,7 +269,7 @@ func (m *Manager) cacheGet(domain string) (*tls.Certificate, error) {
// private
priv, pub := pem.Decode(data)
if priv == nil || !strings.Contains(priv.Type, "PRIVATE") {
- return nil, errors.New("acme/autocert: no private key found in cache")
+ return nil, ErrCacheMiss
}
privKey, err := parsePrivateKey(priv.Bytes)
if err != nil {
@@ -281,13 +287,14 @@ func (m *Manager) cacheGet(domain string) (*tls.Certificate, error) {
pubDER = append(pubDER, b.Bytes)
}
if len(pub) > 0 {
- return nil, errors.New("acme/autocert: invalid public key")
+ // Leftover content not consumed by pem.Decode. Corrupt. Ignore.
+ return nil, ErrCacheMiss
}
// verify and create TLS cert
leaf, err := validCert(domain, pubDER, privKey)
if err != nil {
- return nil, err
+ return nil, ErrCacheMiss
}
tlscert := &tls.Certificate{
Certificate: pubDER,
@@ -297,7 +304,7 @@ func (m *Manager) cacheGet(domain string) (*tls.Certificate, error) {
return tlscert, nil
}
-func (m *Manager) cachePut(domain string, tlscert *tls.Certificate) error {
+func (m *Manager) cachePut(ctx context.Context, domain string, tlscert *tls.Certificate) error {
if m.Cache == nil {
return nil
}
@@ -329,8 +336,6 @@ func (m *Manager) cachePut(domain string, tlscert *tls.Certificate) error {
}
}
- // TODO: might want to define a cache timeout on m
- ctx := context.Background()
return m.Cache.Put(ctx, domain, buf.Bytes())
}
@@ -370,6 +375,23 @@ func (m *Manager) createCert(ctx context.Context, domain string) (*tls.Certifica
der, leaf, err := m.authorizedCert(ctx, state.key, domain)
if err != nil {
+ // Remove the failed state after some time,
+ // making the manager call createCert again on the following TLS hello.
+ time.AfterFunc(createCertRetryAfter, func() {
+ defer testDidRemoveState(domain)
+ m.stateMu.Lock()
+ defer m.stateMu.Unlock()
+ // Verify the state hasn't changed and it's still invalid
+ // before deleting.
+ s, ok := m.state[domain]
+ if !ok {
+ return
+ }
+ if _, err := validCert(domain, s.cert, s.key); err == nil {
+ return
+ }
+ delete(m.state, domain)
+ })
return nil, err
}
state.cert = der
@@ -418,7 +440,6 @@ func (m *Manager) certState(domain string) (*certState, error) {
// authorizedCert starts domain ownership verification process and requests a new cert upon success.
// The key argument is the certificate private key.
func (m *Manager) authorizedCert(ctx context.Context, key crypto.Signer, domain string) (der [][]byte, leaf *x509.Certificate, err error) {
- // TODO: make m.verify retry or retry m.verify calls here
if err := m.verify(ctx, domain); err != nil {
return nil, nil, err
}
@@ -494,7 +515,7 @@ func (m *Manager) verify(ctx context.Context, domain string) error {
if err != nil {
return err
}
- m.putTokenCert(name, &cert)
+ m.putTokenCert(ctx, name, &cert)
defer func() {
// verification has ended at this point
// don't need token cert anymore
@@ -512,14 +533,14 @@ func (m *Manager) verify(ctx context.Context, domain string) error {
// putTokenCert stores the cert under the named key in both m.tokenCert map
// and m.Cache.
-func (m *Manager) putTokenCert(name string, cert *tls.Certificate) {
+func (m *Manager) putTokenCert(ctx context.Context, name string, cert *tls.Certificate) {
m.tokenCertMu.Lock()
defer m.tokenCertMu.Unlock()
if m.tokenCert == nil {
m.tokenCert = make(map[string]*tls.Certificate)
}
m.tokenCert[name] = cert
- m.cachePut(name, cert)
+ m.cachePut(ctx, name, cert)
}
// deleteTokenCert removes the token certificate for the specified domain name
@@ -644,10 +665,10 @@ func (m *Manager) hostPolicy() HostPolicy {
}
func (m *Manager) renewBefore() time.Duration {
- if m.RenewBefore > maxRandRenew {
+ if m.RenewBefore > renewJitter {
return m.RenewBefore
}
- return 7 * 24 * time.Hour // 1 week
+ return 720 * time.Hour // 30 days
}
// certState is ready when its mutex is unlocked for reading.
@@ -789,5 +810,10 @@ func (r *lockedMathRand) int63n(max int64) int64 {
return n
}
-// for easier testing
-var timeNow = time.Now
+// For easier testing.
+var (
+ timeNow = time.Now
+
+ // Called when a state is removed.
+ testDidRemoveState = func(domain string) {}
+)
diff --git a/vendor/golang.org/x/crypto/acme/autocert/autocert_test.go b/vendor/golang.org/x/crypto/acme/autocert/autocert_test.go
index 4bcd6d5..0352e34 100644
--- a/vendor/golang.org/x/crypto/acme/autocert/autocert_test.go
+++ b/vendor/golang.org/x/crypto/acme/autocert/autocert_test.go
@@ -5,6 +5,7 @@
package autocert
import (
+ "context"
"crypto"
"crypto/ecdsa"
"crypto/elliptic"
@@ -22,11 +23,11 @@ import (
"net/http"
"net/http/httptest"
"reflect"
+ "sync"
"testing"
"time"
"golang.org/x/crypto/acme"
- "golang.org/x/net/context"
)
var discoTmpl = template.Must(template.New("disco").Parse(`{
@@ -51,26 +52,44 @@ var authzTmpl = template.Must(template.New("authz").Parse(`{
]
}`))
-type memCache map[string][]byte
+type memCache struct {
+ mu sync.Mutex
+ keyData map[string][]byte
+}
-func (m memCache) Get(ctx context.Context, key string) ([]byte, error) {
- v, ok := m[key]
+func (m *memCache) Get(ctx context.Context, key string) ([]byte, error) {
+ m.mu.Lock()
+ defer m.mu.Unlock()
+
+ v, ok := m.keyData[key]
if !ok {
return nil, ErrCacheMiss
}
return v, nil
}
-func (m memCache) Put(ctx context.Context, key string, data []byte) error {
- m[key] = data
+func (m *memCache) Put(ctx context.Context, key string, data []byte) error {
+ m.mu.Lock()
+ defer m.mu.Unlock()
+
+ m.keyData[key] = data
return nil
}
-func (m memCache) Delete(ctx context.Context, key string) error {
- delete(m, key)
+func (m *memCache) Delete(ctx context.Context, key string) error {
+ m.mu.Lock()
+ defer m.mu.Unlock()
+
+ delete(m.keyData, key)
return nil
}
+func newMemCache() *memCache {
+ return &memCache{
+ keyData: make(map[string][]byte),
+ }
+}
+
func dummyCert(pub interface{}, san ...string) ([]byte, error) {
return dateDummyCert(pub, time.Now(), time.Now().Add(90*24*time.Hour), san...)
}
@@ -124,14 +143,14 @@ func TestGetCertificate_trailingDot(t *testing.T) {
func TestGetCertificate_ForceRSA(t *testing.T) {
man := &Manager{
Prompt: AcceptTOS,
- Cache: make(memCache),
+ Cache: newMemCache(),
ForceRSA: true,
}
defer man.stopRenew()
hello := &tls.ClientHelloInfo{ServerName: "example.org"}
testGetCertificate(t, man, "example.org", hello)
- cert, err := man.cacheGet("example.org")
+ cert, err := man.cacheGet(context.Background(), "example.org")
if err != nil {
t.Fatalf("man.cacheGet: %v", err)
}
@@ -140,9 +159,110 @@ func TestGetCertificate_ForceRSA(t *testing.T) {
}
}
-// tests man.GetCertificate flow using the provided hello argument.
+func TestGetCertificate_nilPrompt(t *testing.T) {
+ man := &Manager{}
+ defer man.stopRenew()
+ url, finish := startACMEServerStub(t, man, "example.org")
+ defer finish()
+ key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
+ if err != nil {
+ t.Fatal(err)
+ }
+ man.Client = &acme.Client{
+ Key: key,
+ DirectoryURL: url,
+ }
+ hello := &tls.ClientHelloInfo{ServerName: "example.org"}
+ if _, err := man.GetCertificate(hello); err == nil {
+ t.Error("got certificate for example.org; wanted error")
+ }
+}
+
+func TestGetCertificate_expiredCache(t *testing.T) {
+ // Make an expired cert and cache it.
+ pk, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
+ if err != nil {
+ t.Fatal(err)
+ }
+ tmpl := &x509.Certificate{
+ SerialNumber: big.NewInt(1),
+ Subject: pkix.Name{CommonName: "example.org"},
+ NotAfter: time.Now(),
+ }
+ pub, err := x509.CreateCertificate(rand.Reader, tmpl, tmpl, &pk.PublicKey, pk)
+ if err != nil {
+ t.Fatal(err)
+ }
+ tlscert := &tls.Certificate{
+ Certificate: [][]byte{pub},
+ PrivateKey: pk,
+ }
+
+ man := &Manager{Prompt: AcceptTOS, Cache: newMemCache()}
+ defer man.stopRenew()
+ if err := man.cachePut(context.Background(), "example.org", tlscert); err != nil {
+ t.Fatalf("man.cachePut: %v", err)
+ }
+
+ // The expired cached cert should trigger a new cert issuance
+ // and return without an error.
+ hello := &tls.ClientHelloInfo{ServerName: "example.org"}
+ testGetCertificate(t, man, "example.org", hello)
+}
+
+func TestGetCertificate_failedAttempt(t *testing.T) {
+ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.WriteHeader(http.StatusBadRequest)
+ }))
+ defer ts.Close()
+
+ const example = "example.org"
+ d := createCertRetryAfter
+ f := testDidRemoveState
+ defer func() {
+ createCertRetryAfter = d
+ testDidRemoveState = f
+ }()
+ createCertRetryAfter = 0
+ done := make(chan struct{})
+ testDidRemoveState = func(domain string) {
+ if domain != example {
+ t.Errorf("testDidRemoveState: domain = %q; want %q", domain, example)
+ }
+ close(done)
+ }
+
+ key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
+ if err != nil {
+ t.Fatal(err)
+ }
+ man := &Manager{
+ Prompt: AcceptTOS,
+ Client: &acme.Client{
+ Key: key,
+ DirectoryURL: ts.URL,
+ },
+ }
+ defer man.stopRenew()
+ hello := &tls.ClientHelloInfo{ServerName: example}
+ if _, err := man.GetCertificate(hello); err == nil {
+ t.Error("GetCertificate: err is nil")
+ }
+ select {
+ case <-time.After(5 * time.Second):
+ t.Errorf("took too long to remove the %q state", example)
+ case <-done:
+ man.stateMu.Lock()
+ defer man.stateMu.Unlock()
+ if v, exist := man.state[example]; exist {
+ t.Errorf("state exists for %q: %+v", example, v)
+ }
+ }
+}
+
+// startACMEServerStub runs an ACME server
// The domain argument is the expected domain name of a certificate request.
-func testGetCertificate(t *testing.T, man *Manager, domain string, hello *tls.ClientHelloInfo) {
+func startACMEServerStub(t *testing.T, man *Manager, domain string) (url string, finish func()) {
// echo token-02 | shasum -a 256
// then divide result in 2 parts separated by dot
tokenCertName := "4e8eb87631187e9ff2153b56b13a4dec.13a35d002e485d60ff37354b32f665d9.token.acme.invalid"
@@ -168,7 +288,7 @@ func testGetCertificate(t *testing.T, man *Manager, domain string, hello *tls.Cl
// discovery
case "/":
if err := discoTmpl.Execute(w, ca.URL); err != nil {
- t.Fatalf("discoTmpl: %v", err)
+ t.Errorf("discoTmpl: %v", err)
}
// client key registration
case "/new-reg":
@@ -178,7 +298,7 @@ func testGetCertificate(t *testing.T, man *Manager, domain string, hello *tls.Cl
w.Header().Set("location", ca.URL+"/authz/1")
w.WriteHeader(http.StatusCreated)
if err := authzTmpl.Execute(w, ca.URL); err != nil {
- t.Fatalf("authzTmpl: %v", err)
+ t.Errorf("authzTmpl: %v", err)
}
// accept tls-sni-02 challenge
case "/challenge/2":
@@ -196,14 +316,14 @@ func testGetCertificate(t *testing.T, man *Manager, domain string, hello *tls.Cl
b, _ := base64.RawURLEncoding.DecodeString(req.CSR)
csr, err := x509.ParseCertificateRequest(b)
if err != nil {
- t.Fatalf("new-cert: CSR: %v", err)
+ t.Errorf("new-cert: CSR: %v", err)
}
if csr.Subject.CommonName != domain {
t.Errorf("CommonName in CSR = %q; want %q", csr.Subject.CommonName, domain)
}
der, err := dummyCert(csr.PublicKey, domain)
if err != nil {
- t.Fatalf("new-cert: dummyCert: %v", err)
+ t.Errorf("new-cert: dummyCert: %v", err)
}
chainUp := fmt.Sprintf("<%s/ca-cert>; rel=up", ca.URL)
w.Header().Set("link", chainUp)
@@ -213,14 +333,51 @@ func testGetCertificate(t *testing.T, man *Manager, domain string, hello *tls.Cl
case "/ca-cert":
der, err := dummyCert(nil, "ca")
if err != nil {
- t.Fatalf("ca-cert: dummyCert: %v", err)
+ t.Errorf("ca-cert: dummyCert: %v", err)
}
w.Write(der)
default:
t.Errorf("unrecognized r.URL.Path: %s", r.URL.Path)
}
}))
- defer ca.Close()
+ finish = func() {
+ ca.Close()
+
+ // make sure token cert was removed
+ cancel := make(chan struct{})
+ done := make(chan struct{})
+ go func() {
+ defer close(done)
+ tick := time.NewTicker(100 * time.Millisecond)
+ defer tick.Stop()
+ for {
+ hello := &tls.ClientHelloInfo{ServerName: tokenCertName}
+ if _, err := man.GetCertificate(hello); err != nil {
+ return
+ }
+ select {
+ case <-tick.C:
+ case <-cancel:
+ return
+ }
+ }
+ }()
+ select {
+ case <-done:
+ case <-time.After(5 * time.Second):
+ close(cancel)
+ t.Error("token cert was not removed")
+ <-done
+ }
+ }
+ return ca.URL, finish
+}
+
+// tests man.GetCertificate flow using the provided hello argument.
+// The domain argument is the expected domain name of a certificate request.
+func testGetCertificate(t *testing.T, man *Manager, domain string, hello *tls.ClientHelloInfo) {
+ url, finish := startACMEServerStub(t, man, domain)
+ defer finish()
// use EC key to run faster on 386
key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
@@ -229,7 +386,7 @@ func testGetCertificate(t *testing.T, man *Manager, domain string, hello *tls.Cl
}
man.Client = &acme.Client{
Key: key,
- DirectoryURL: ca.URL,
+ DirectoryURL: url,
}
// simulate tls.Config.GetCertificate
@@ -260,28 +417,10 @@ func testGetCertificate(t *testing.T, man *Manager, domain string, hello *tls.Cl
t.Errorf("cert.DNSNames = %v; want %q", cert.DNSNames, domain)
}
- // make sure token cert was removed
- done = make(chan struct{})
- go func() {
- for {
- hello := &tls.ClientHelloInfo{ServerName: tokenCertName}
- if _, err := man.GetCertificate(hello); err != nil {
- break
- }
- time.Sleep(100 * time.Millisecond)
- }
- close(done)
- }()
- select {
- case <-time.After(5 * time.Second):
- t.Error("token cert was not removed")
- case <-done:
- }
}
func TestAccountKeyCache(t *testing.T) {
- cache := make(memCache)
- m := Manager{Cache: cache}
+ m := Manager{Cache: newMemCache()}
ctx := context.Background()
k1, err := m.accountKey(ctx)
if err != nil {
@@ -315,13 +454,13 @@ func TestCache(t *testing.T) {
PrivateKey: privKey,
}
- cache := make(memCache)
- man := &Manager{Cache: cache}
+ man := &Manager{Cache: newMemCache()}
defer man.stopRenew()
- if err := man.cachePut("example.org", tlscert); err != nil {
+ ctx := context.Background()
+ if err := man.cachePut(ctx, "example.org", tlscert); err != nil {
t.Fatalf("man.cachePut: %v", err)
}
- res, err := man.cacheGet("example.org")
+ res, err := man.cacheGet(ctx, "example.org")
if err != nil {
t.Fatalf("man.cacheGet: %v", err)
}
@@ -421,3 +560,47 @@ func TestValidCert(t *testing.T) {
}
}
}
+
+type cacheGetFunc func(ctx context.Context, key string) ([]byte, error)
+
+func (f cacheGetFunc) Get(ctx context.Context, key string) ([]byte, error) {
+ return f(ctx, key)
+}
+
+func (f cacheGetFunc) Put(ctx context.Context, key string, data []byte) error {
+ return fmt.Errorf("unsupported Put of %q = %q", key, data)
+}
+
+func (f cacheGetFunc) Delete(ctx context.Context, key string) error {
+ return fmt.Errorf("unsupported Delete of %q", key)
+}
+
+func TestManagerGetCertificateBogusSNI(t *testing.T) {
+ m := Manager{
+ Prompt: AcceptTOS,
+ Cache: cacheGetFunc(func(ctx context.Context, key string) ([]byte, error) {
+ return nil, fmt.Errorf("cache.Get of %s", key)
+ }),
+ }
+ tests := []struct {
+ name string
+ wantErr string
+ }{
+ {"foo.com", "cache.Get of foo.com"},
+ {"foo.com.", "cache.Get of foo.com"},
+ {`a\b.com`, "acme/autocert: server name contains invalid character"},
+ {`a/b.com`, "acme/autocert: server name contains invalid character"},
+ {"", "acme/autocert: missing server name"},
+ {"foo", "acme/autocert: server name component count invalid"},
+ {".foo", "acme/autocert: server name component count invalid"},
+ {"foo.", "acme/autocert: server name component count invalid"},
+ {"fo.o", "cache.Get of fo.o"},
+ }
+ for _, tt := range tests {
+ _, err := m.GetCertificate(&tls.ClientHelloInfo{ServerName: tt.name})
+ got := fmt.Sprint(err)
+ if got != tt.wantErr {
+ t.Errorf("GetCertificate(SNI = %q) = %q; want %q", tt.name, got, tt.wantErr)
+ }
+ }
+}
diff --git a/vendor/golang.org/x/crypto/acme/autocert/cache.go b/vendor/golang.org/x/crypto/acme/autocert/cache.go
index 9b184aa..61a5fd2 100644
--- a/vendor/golang.org/x/crypto/acme/autocert/cache.go
+++ b/vendor/golang.org/x/crypto/acme/autocert/cache.go
@@ -5,12 +5,11 @@
package autocert
import (
+ "context"
"errors"
"io/ioutil"
"os"
"path/filepath"
-
- "golang.org/x/net/context"
)
// ErrCacheMiss is returned when a certificate is not found in cache.
@@ -78,12 +77,13 @@ func (d DirCache) Put(ctx context.Context, name string, data []byte) error {
if tmp, err = d.writeTempFile(name, data); err != nil {
return
}
- // prevent overwriting the file if the context was cancelled
- if ctx.Err() != nil {
- return // no need to set err
+ select {
+ case <-ctx.Done():
+ // Don't overwrite the file if the context was canceled.
+ default:
+ newName := filepath.Join(string(d), name)
+ err = os.Rename(tmp, newName)
}
- name = filepath.Join(string(d), name)
- err = os.Rename(tmp, name)
}()
select {
case <-ctx.Done():
diff --git a/vendor/golang.org/x/crypto/acme/autocert/cache_test.go b/vendor/golang.org/x/crypto/acme/autocert/cache_test.go
index ad6d4a4..6e1b88d 100644
--- a/vendor/golang.org/x/crypto/acme/autocert/cache_test.go
+++ b/vendor/golang.org/x/crypto/acme/autocert/cache_test.go
@@ -5,13 +5,12 @@
package autocert
import (
+ "context"
"io/ioutil"
"os"
"path/filepath"
"reflect"
"testing"
-
- "golang.org/x/net/context"
)
// make sure DirCache satisfies Cache interface
diff --git a/vendor/golang.org/x/crypto/acme/autocert/example_test.go b/vendor/golang.org/x/crypto/acme/autocert/example_test.go
new file mode 100644
index 0000000..c6267b8
--- /dev/null
+++ b/vendor/golang.org/x/crypto/acme/autocert/example_test.go
@@ -0,0 +1,34 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package autocert_test
+
+import (
+ "crypto/tls"
+ "fmt"
+ "log"
+ "net/http"
+
+ "golang.org/x/crypto/acme/autocert"
+)
+
+func ExampleNewListener() {
+ mux := http.NewServeMux()
+ mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
+ fmt.Fprintf(w, "Hello, TLS user! Your config: %+v", r.TLS)
+ })
+ log.Fatal(http.Serve(autocert.NewListener("example.com"), mux))
+}
+
+func ExampleManager() {
+ m := autocert.Manager{
+ Prompt: autocert.AcceptTOS,
+ HostPolicy: autocert.HostWhitelist("example.org"),
+ }
+ s := &http.Server{
+ Addr: ":https",
+ TLSConfig: &tls.Config{GetCertificate: m.GetCertificate},
+ }
+ s.ListenAndServeTLS("", "")
+}
diff --git a/vendor/golang.org/x/crypto/acme/autocert/listener.go b/vendor/golang.org/x/crypto/acme/autocert/listener.go
new file mode 100644
index 0000000..d744df0
--- /dev/null
+++ b/vendor/golang.org/x/crypto/acme/autocert/listener.go
@@ -0,0 +1,160 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package autocert
+
+import (
+ "crypto/tls"
+ "log"
+ "net"
+ "os"
+ "path/filepath"
+ "runtime"
+ "time"
+)
+
+// NewListener returns a net.Listener that listens on the standard TLS
+// port (443) on all interfaces and returns *tls.Conn connections with
+// LetsEncrypt certificates for the provided domain or domains.
+//
+// It enables one-line HTTPS servers:
+//
+// log.Fatal(http.Serve(autocert.NewListener("example.com"), handler))
+//
+// NewListener is a convenience function for a common configuration.
+// More complex or custom configurations can use the autocert.Manager
+// type instead.
+//
+// Use of this function implies acceptance of the LetsEncrypt Terms of
+// Service. If domains is not empty, the provided domains are passed
+// to HostWhitelist. If domains is empty, the listener will do
+// LetsEncrypt challenges for any requested domain, which is not
+// recommended.
+//
+// Certificates are cached in a "golang-autocert" directory under an
+// operating system-specific cache or temp directory. This may not
+// be suitable for servers spanning multiple machines.
+//
+// The returned listener uses a *tls.Config that enables HTTP/2, and
+// should only be used with servers that support HTTP/2.
+//
+// The returned Listener also enables TCP keep-alives on the accepted
+// connections. The returned *tls.Conn are returned before their TLS
+// handshake has completed.
+func NewListener(domains ...string) net.Listener {
+ m := &Manager{
+ Prompt: AcceptTOS,
+ }
+ if len(domains) > 0 {
+ m.HostPolicy = HostWhitelist(domains...)
+ }
+ dir := cacheDir()
+ if err := os.MkdirAll(dir, 0700); err != nil {
+ log.Printf("warning: autocert.NewListener not using a cache: %v", err)
+ } else {
+ m.Cache = DirCache(dir)
+ }
+ return m.Listener()
+}
+
+// Listener listens on the standard TLS port (443) on all interfaces
+// and returns a net.Listener returning *tls.Conn connections.
+//
+// The returned listener uses a *tls.Config that enables HTTP/2, and
+// should only be used with servers that support HTTP/2.
+//
+// The returned Listener also enables TCP keep-alives on the accepted
+// connections. The returned *tls.Conn are returned before their TLS
+// handshake has completed.
+//
+// Unlike NewListener, it is the caller's responsibility to initialize
+// the Manager m's Prompt, Cache, HostPolicy, and other desired options.
+func (m *Manager) Listener() net.Listener {
+ ln := &listener{
+ m: m,
+ conf: &tls.Config{
+ GetCertificate: m.GetCertificate, // bonus: panic on nil m
+ NextProtos: []string{"h2", "http/1.1"}, // Enable HTTP/2
+ },
+ }
+ ln.tcpListener, ln.tcpListenErr = net.Listen("tcp", ":443")
+ return ln
+}
+
+type listener struct {
+ m *Manager
+ conf *tls.Config
+
+ tcpListener net.Listener
+ tcpListenErr error
+}
+
+func (ln *listener) Accept() (net.Conn, error) {
+ if ln.tcpListenErr != nil {
+ return nil, ln.tcpListenErr
+ }
+ conn, err := ln.tcpListener.Accept()
+ if err != nil {
+ return nil, err
+ }
+ tcpConn := conn.(*net.TCPConn)
+
+ // Because Listener is a convenience function, help out with
+ // this too. This is not possible for the caller to set once
+ // we return a *tcp.Conn wrapping an inaccessible net.Conn.
+ // If callers don't want this, they can do things the manual
+ // way and tweak as needed. But this is what net/http does
+ // itself, so copy that. If net/http changes, we can change
+ // here too.
+ tcpConn.SetKeepAlive(true)
+ tcpConn.SetKeepAlivePeriod(3 * time.Minute)
+
+ return tls.Server(tcpConn, ln.conf), nil
+}
+
+func (ln *listener) Addr() net.Addr {
+ if ln.tcpListener != nil {
+ return ln.tcpListener.Addr()
+ }
+ // net.Listen failed. Return something non-nil in case callers
+ // call Addr before Accept:
+ return &net.TCPAddr{IP: net.IP{0, 0, 0, 0}, Port: 443}
+}
+
+func (ln *listener) Close() error {
+ if ln.tcpListenErr != nil {
+ return ln.tcpListenErr
+ }
+ return ln.tcpListener.Close()
+}
+
+func homeDir() string {
+ if runtime.GOOS == "windows" {
+ return os.Getenv("HOMEDRIVE") + os.Getenv("HOMEPATH")
+ }
+ if h := os.Getenv("HOME"); h != "" {
+ return h
+ }
+ return "/"
+}
+
+func cacheDir() string {
+ const base = "golang-autocert"
+ switch runtime.GOOS {
+ case "darwin":
+ return filepath.Join(homeDir(), "Library", "Caches", base)
+ case "windows":
+ for _, ev := range []string{"APPDATA", "CSIDL_APPDATA", "TEMP", "TMP"} {
+ if v := os.Getenv(ev); v != "" {
+ return filepath.Join(v, base)
+ }
+ }
+ // Worst case:
+ return filepath.Join(homeDir(), base)
+ }
+ if xdg := os.Getenv("XDG_CACHE_HOME"); xdg != "" {
+ return filepath.Join(xdg, base)
+ }
+ return filepath.Join(homeDir(), ".cache", base)
+}
diff --git a/vendor/golang.org/x/crypto/acme/autocert/renewal.go b/vendor/golang.org/x/crypto/acme/autocert/renewal.go
index 1a5018c..6c5da2b 100644
--- a/vendor/golang.org/x/crypto/acme/autocert/renewal.go
+++ b/vendor/golang.org/x/crypto/acme/autocert/renewal.go
@@ -5,15 +5,14 @@
package autocert
import (
+ "context"
"crypto"
"sync"
"time"
-
- "golang.org/x/net/context"
)
-// maxRandRenew is a maximum deviation from Manager.RenewBefore.
-const maxRandRenew = time.Hour
+// renewJitter is the maximum deviation from Manager.RenewBefore.
+const renewJitter = time.Hour
// domainRenewal tracks the state used by the periodic timers
// renewing a single domain's cert.
@@ -65,7 +64,7 @@ func (dr *domainRenewal) renew() {
// TODO: rotate dr.key at some point?
next, err := dr.do(ctx)
if err != nil {
- next = maxRandRenew / 2
+ next = renewJitter / 2
next += time.Duration(pseudoRand.int63n(int64(next)))
}
dr.timer = time.AfterFunc(next, dr.renew)
@@ -83,9 +82,9 @@ func (dr *domainRenewal) renew() {
func (dr *domainRenewal) do(ctx context.Context) (time.Duration, error) {
// a race is likely unavoidable in a distributed environment
// but we try nonetheless
- if tlscert, err := dr.m.cacheGet(dr.domain); err == nil {
+ if tlscert, err := dr.m.cacheGet(ctx, dr.domain); err == nil {
next := dr.next(tlscert.Leaf.NotAfter)
- if next > dr.m.renewBefore()+maxRandRenew {
+ if next > dr.m.renewBefore()+renewJitter {
return next, nil
}
}
@@ -103,7 +102,7 @@ func (dr *domainRenewal) do(ctx context.Context) (time.Duration, error) {
if err != nil {
return 0, err
}
- dr.m.cachePut(dr.domain, tlscert)
+ dr.m.cachePut(ctx, dr.domain, tlscert)
dr.m.stateMu.Lock()
defer dr.m.stateMu.Unlock()
// m.state is guaranteed to be non-nil at this point
@@ -114,7 +113,7 @@ func (dr *domainRenewal) do(ctx context.Context) (time.Duration, error) {
func (dr *domainRenewal) next(expiry time.Time) time.Duration {
d := expiry.Sub(timeNow()) - dr.m.renewBefore()
// add a bit of randomness to renew deadline
- n := pseudoRand.int63n(int64(maxRandRenew))
+ n := pseudoRand.int63n(int64(renewJitter))
d -= time.Duration(n)
if d < 0 {
return 0
diff --git a/vendor/golang.org/x/crypto/acme/autocert/renewal_test.go b/vendor/golang.org/x/crypto/acme/autocert/renewal_test.go
index d1ec52f..f232619 100644
--- a/vendor/golang.org/x/crypto/acme/autocert/renewal_test.go
+++ b/vendor/golang.org/x/crypto/acme/autocert/renewal_test.go
@@ -5,6 +5,7 @@
package autocert
import (
+ "context"
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
@@ -31,7 +32,7 @@ func TestRenewalNext(t *testing.T) {
expiry time.Time
min, max time.Duration
}{
- {now.Add(90 * 24 * time.Hour), 83*24*time.Hour - maxRandRenew, 83 * 24 * time.Hour},
+ {now.Add(90 * 24 * time.Hour), 83*24*time.Hour - renewJitter, 83 * 24 * time.Hour},
{now.Add(time.Hour), 0, 1},
{now, 0, 1},
{now.Add(-time.Hour), 0, 1},
@@ -111,7 +112,7 @@ func TestRenewFromCache(t *testing.T) {
}
man := &Manager{
Prompt: AcceptTOS,
- Cache: make(memCache),
+ Cache: newMemCache(),
RenewBefore: 24 * time.Hour,
Client: &acme.Client{
Key: key,
@@ -127,7 +128,7 @@ func TestRenewFromCache(t *testing.T) {
t.Fatal(err)
}
tlscert := &tls.Certificate{PrivateKey: key, Certificate: [][]byte{cert}}
- if err := man.cachePut(domain, tlscert); err != nil {
+ if err := man.cachePut(context.Background(), domain, tlscert); err != nil {
t.Fatal(err)
}
@@ -151,7 +152,7 @@ func TestRenewFromCache(t *testing.T) {
// ensure the new cert is cached
after := time.Now().Add(future)
- tlscert, err := man.cacheGet(domain)
+ tlscert, err := man.cacheGet(context.Background(), domain)
if err != nil {
t.Fatalf("man.cacheGet: %v", err)
}
diff --git a/vendor/golang.org/x/crypto/acme/jws.go b/vendor/golang.org/x/crypto/acme/jws.go
index 49ba313..6cbca25 100644
--- a/vendor/golang.org/x/crypto/acme/jws.go
+++ b/vendor/golang.org/x/crypto/acme/jws.go
@@ -134,7 +134,7 @@ func jwsHasher(key crypto.Signer) (string, crypto.Hash) {
return "ES256", crypto.SHA256
case "P-384":
return "ES384", crypto.SHA384
- case "P-512":
+ case "P-521":
return "ES512", crypto.SHA512
}
}
diff --git a/vendor/golang.org/x/crypto/acme/jws_test.go b/vendor/golang.org/x/crypto/acme/jws_test.go
index 1def873..0ff0fb5 100644
--- a/vendor/golang.org/x/crypto/acme/jws_test.go
+++ b/vendor/golang.org/x/crypto/acme/jws_test.go
@@ -12,11 +12,13 @@ import (
"encoding/base64"
"encoding/json"
"encoding/pem"
+ "fmt"
"math/big"
"testing"
)
-const testKeyPEM = `
+const (
+ testKeyPEM = `
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEA4xgZ3eRPkwoRvy7qeRUbmMDe0V+xH9eWLdu0iheeLlrmD2mq
WXfP9IeSKApbn34g8TuAS9g5zhq8ELQ3kmjr+KV86GAMgI6VAcGlq3QrzpTCf/30
@@ -46,10 +48,9 @@ EQeIP6dZtv8IMgtGIb91QX9pXvP0aznzQKwYIA8nZgoENCPfiMTPiEDT9e/0lObO
-----END RSA PRIVATE KEY-----
`
-// This thumbprint is for the testKey defined above.
-const testKeyThumbprint = "6nicxzh6WETQlrvdchkz-U3e3DOQZ4heJKU63rfqMqQ"
+ // This thumbprint is for the testKey defined above.
+ testKeyThumbprint = "6nicxzh6WETQlrvdchkz-U3e3DOQZ4heJKU63rfqMqQ"
-const (
// openssl ecparam -name secp256k1 -genkey -noout
testKeyECPEM = `
-----BEGIN EC PRIVATE KEY-----
@@ -58,39 +59,78 @@ AwEHoUQDQgAE5lhEug5xK4xBDZ2nAbaxLtaLiv85bxJ7ePd1dkO23HThqIrvawF5
QAaS/RNouybCiRhRjI3EaxLkQwgrCw0gqQ==
-----END EC PRIVATE KEY-----
`
- // 1. opnessl ec -in key.pem -noout -text
+ // openssl ecparam -name secp384r1 -genkey -noout
+ testKeyEC384PEM = `
+-----BEGIN EC PRIVATE KEY-----
+MIGkAgEBBDAQ4lNtXRORWr1bgKR1CGysr9AJ9SyEk4jiVnlUWWUChmSNL+i9SLSD
+Oe/naPqXJ6CgBwYFK4EEACKhZANiAAQzKtj+Ms0vHoTX5dzv3/L5YMXOWuI5UKRj
+JigpahYCqXD2BA1j0E/2xt5vlPf+gm0PL+UHSQsCokGnIGuaHCsJAp3ry0gHQEke
+WYXapUUFdvaK1R2/2hn5O+eiQM8YzCg=
+-----END EC PRIVATE KEY-----
+`
+ // openssl ecparam -name secp521r1 -genkey -noout
+ testKeyEC512PEM = `
+-----BEGIN EC PRIVATE KEY-----
+MIHcAgEBBEIBSNZKFcWzXzB/aJClAb305ibalKgtDA7+70eEkdPt28/3LZMM935Z
+KqYHh/COcxuu3Kt8azRAUz3gyr4zZKhlKUSgBwYFK4EEACOhgYkDgYYABAHUNKbx
+7JwC7H6pa2sV0tERWhHhB3JmW+OP6SUgMWryvIKajlx73eS24dy4QPGrWO9/ABsD
+FqcRSkNVTXnIv6+0mAF25knqIBIg5Q8M9BnOu9GGAchcwt3O7RDHmqewnJJDrbjd
+GGnm6rb+NnWR9DIopM0nKNkToWoF/hzopxu4Ae/GsQ==
+-----END EC PRIVATE KEY-----
+`
+ // 1. openssl ec -in key.pem -noout -text
// 2. remove first byte, 04 (the header); the rest is X and Y
- // 3. covert each with: echo | xxd -r -p | base64 | tr -d '=' | tr '/+' '_-'
- testKeyECPubX = "5lhEug5xK4xBDZ2nAbaxLtaLiv85bxJ7ePd1dkO23HQ"
- testKeyECPubY = "4aiK72sBeUAGkv0TaLsmwokYUYyNxGsS5EMIKwsNIKk"
+ // 3. convert each with: echo | xxd -r -p | base64 -w 100 | tr -d '=' | tr '/+' '_-'
+ testKeyECPubX = "5lhEug5xK4xBDZ2nAbaxLtaLiv85bxJ7ePd1dkO23HQ"
+ testKeyECPubY = "4aiK72sBeUAGkv0TaLsmwokYUYyNxGsS5EMIKwsNIKk"
+ testKeyEC384PubX = "MyrY_jLNLx6E1-Xc79_y-WDFzlriOVCkYyYoKWoWAqlw9gQNY9BP9sbeb5T3_oJt"
+ testKeyEC384PubY = "Dy_lB0kLAqJBpyBrmhwrCQKd68tIB0BJHlmF2qVFBXb2itUdv9oZ-TvnokDPGMwo"
+ testKeyEC512PubX = "AdQ0pvHsnALsfqlraxXS0RFaEeEHcmZb44_pJSAxavK8gpqOXHvd5Lbh3LhA8atY738AGwMWpxFKQ1VNeci_r7SY"
+ testKeyEC512PubY = "AXbmSeogEiDlDwz0Gc670YYByFzC3c7tEMeap7CckkOtuN0Yaebqtv42dZH0MiikzSco2ROhagX-HOinG7gB78ax"
+
// echo -n '{"crv":"P-256","kty":"EC","x":"","y":""}' | \
// openssl dgst -binary -sha256 | base64 | tr -d '=' | tr '/+' '_-'
testKeyECThumbprint = "zedj-Bd1Zshp8KLePv2MB-lJ_Hagp7wAwdkA0NUTniU"
)
var (
- testKey *rsa.PrivateKey
- testKeyEC *ecdsa.PrivateKey
+ testKey *rsa.PrivateKey
+ testKeyEC *ecdsa.PrivateKey
+ testKeyEC384 *ecdsa.PrivateKey
+ testKeyEC512 *ecdsa.PrivateKey
)
func init() {
- d, _ := pem.Decode([]byte(testKeyPEM))
- if d == nil {
- panic("no block found in testKeyPEM")
- }
- var err error
- testKey, err = x509.ParsePKCS1PrivateKey(d.Bytes)
- if err != nil {
- panic(err.Error())
- }
+ testKey = parseRSA(testKeyPEM, "testKeyPEM")
+ testKeyEC = parseEC(testKeyECPEM, "testKeyECPEM")
+ testKeyEC384 = parseEC(testKeyEC384PEM, "testKeyEC384PEM")
+ testKeyEC512 = parseEC(testKeyEC512PEM, "testKeyEC512PEM")
+}
- if d, _ = pem.Decode([]byte(testKeyECPEM)); d == nil {
- panic("no block found in testKeyECPEM")
+func decodePEM(s, name string) []byte {
+ d, _ := pem.Decode([]byte(s))
+ if d == nil {
+ panic("no block found in " + name)
}
- testKeyEC, err = x509.ParseECPrivateKey(d.Bytes)
+ return d.Bytes
+}
+
+func parseRSA(s, name string) *rsa.PrivateKey {
+ b := decodePEM(s, name)
+ k, err := x509.ParsePKCS1PrivateKey(b)
if err != nil {
- panic(err.Error())
+ panic(fmt.Sprintf("%s: %v", name, err))
}
+ return k
+}
+
+func parseEC(s, name string) *ecdsa.PrivateKey {
+ b := decodePEM(s, name)
+ k, err := x509.ParseECPrivateKey(b)
+ if err != nil {
+ panic(fmt.Sprintf("%s: %v", name, err))
+ }
+ return k
}
func TestJWSEncodeJSON(t *testing.T) {
@@ -141,50 +181,63 @@ func TestJWSEncodeJSON(t *testing.T) {
}
func TestJWSEncodeJSONEC(t *testing.T) {
- claims := struct{ Msg string }{"Hello JWS"}
+ tt := []struct {
+ key *ecdsa.PrivateKey
+ x, y string
+ alg, crv string
+ }{
+ {testKeyEC, testKeyECPubX, testKeyECPubY, "ES256", "P-256"},
+ {testKeyEC384, testKeyEC384PubX, testKeyEC384PubY, "ES384", "P-384"},
+ {testKeyEC512, testKeyEC512PubX, testKeyEC512PubY, "ES512", "P-521"},
+ }
+ for i, test := range tt {
+ claims := struct{ Msg string }{"Hello JWS"}
+ b, err := jwsEncodeJSON(claims, test.key, "nonce")
+ if err != nil {
+ t.Errorf("%d: %v", i, err)
+ continue
+ }
+ var jws struct{ Protected, Payload, Signature string }
+ if err := json.Unmarshal(b, &jws); err != nil {
+ t.Errorf("%d: %v", i, err)
+ continue
+ }
- b, err := jwsEncodeJSON(claims, testKeyEC, "nonce")
- if err != nil {
- t.Fatal(err)
- }
- var jws struct{ Protected, Payload, Signature string }
- if err := json.Unmarshal(b, &jws); err != nil {
- t.Fatal(err)
- }
-
- if b, err = base64.RawURLEncoding.DecodeString(jws.Protected); err != nil {
- t.Fatalf("jws.Protected: %v", err)
- }
- var head struct {
- Alg string
- Nonce string
- JWK struct {
- Crv string
- Kty string
- X string
- Y string
- } `json:"jwk"`
- }
- if err := json.Unmarshal(b, &head); err != nil {
- t.Fatalf("jws.Protected: %v", err)
- }
- if head.Alg != "ES256" {
- t.Errorf("head.Alg = %q; want ES256", head.Alg)
- }
- if head.Nonce != "nonce" {
- t.Errorf("head.Nonce = %q; want nonce", head.Nonce)
- }
- if head.JWK.Crv != "P-256" {
- t.Errorf("head.JWK.Crv = %q; want P-256", head.JWK.Crv)
- }
- if head.JWK.Kty != "EC" {
- t.Errorf("head.JWK.Kty = %q; want EC", head.JWK.Kty)
- }
- if head.JWK.X != testKeyECPubX {
- t.Errorf("head.JWK.X = %q; want %q", head.JWK.X, testKeyECPubX)
- }
- if head.JWK.Y != testKeyECPubY {
- t.Errorf("head.JWK.Y = %q; want %q", head.JWK.Y, testKeyECPubY)
+ b, err = base64.RawURLEncoding.DecodeString(jws.Protected)
+ if err != nil {
+ t.Errorf("%d: jws.Protected: %v", i, err)
+ }
+ var head struct {
+ Alg string
+ Nonce string
+ JWK struct {
+ Crv string
+ Kty string
+ X string
+ Y string
+ } `json:"jwk"`
+ }
+ if err := json.Unmarshal(b, &head); err != nil {
+ t.Errorf("%d: jws.Protected: %v", i, err)
+ }
+ if head.Alg != test.alg {
+ t.Errorf("%d: head.Alg = %q; want %q", i, head.Alg, test.alg)
+ }
+ if head.Nonce != "nonce" {
+ t.Errorf("%d: head.Nonce = %q; want nonce", i, head.Nonce)
+ }
+ if head.JWK.Crv != test.crv {
+ t.Errorf("%d: head.JWK.Crv = %q; want %q", i, head.JWK.Crv, test.crv)
+ }
+ if head.JWK.Kty != "EC" {
+ t.Errorf("%d: head.JWK.Kty = %q; want EC", i, head.JWK.Kty)
+ }
+ if head.JWK.X != test.x {
+ t.Errorf("%d: head.JWK.X = %q; want %q", i, head.JWK.X, test.x)
+ }
+ if head.JWK.Y != test.y {
+ t.Errorf("%d: head.JWK.Y = %q; want %q", i, head.JWK.Y, test.y)
+ }
}
}
diff --git a/vendor/golang.org/x/crypto/acme/types.go b/vendor/golang.org/x/crypto/acme/types.go
index 0513b2e..ab4de0b 100644
--- a/vendor/golang.org/x/crypto/acme/types.go
+++ b/vendor/golang.org/x/crypto/acme/types.go
@@ -1,9 +1,15 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
package acme
import (
"errors"
"fmt"
"net/http"
+ "strings"
+ "time"
)
// ACME server response statuses used to describe Authorization and Challenge states.
@@ -33,14 +39,8 @@ const (
CRLReasonAACompromise CRLReasonCode = 10
)
-var (
- // ErrAuthorizationFailed indicates that an authorization for an identifier
- // did not succeed.
- ErrAuthorizationFailed = errors.New("acme: identifier authorization failed")
-
- // ErrUnsupportedKey is returned when an unsupported key type is encountered.
- ErrUnsupportedKey = errors.New("acme: unknown key type; only RSA and ECDSA are supported")
-)
+// ErrUnsupportedKey is returned when an unsupported key type is encountered.
+var ErrUnsupportedKey = errors.New("acme: unknown key type; only RSA and ECDSA are supported")
// Error is an ACME error, defined in Problem Details for HTTP APIs doc
// http://tools.ietf.org/html/draft-ietf-appsawg-http-problem.
@@ -53,6 +53,7 @@ type Error struct {
// Detail is a human-readable explanation specific to this occurrence of the problem.
Detail string
// Header is the original server error response headers.
+ // It may be nil.
Header http.Header
}
@@ -60,6 +61,50 @@ func (e *Error) Error() string {
return fmt.Sprintf("%d %s: %s", e.StatusCode, e.ProblemType, e.Detail)
}
+// AuthorizationError indicates that an authorization for an identifier
+// did not succeed.
+// It contains all errors from Challenge items of the failed Authorization.
+type AuthorizationError struct {
+ // URI uniquely identifies the failed Authorization.
+ URI string
+
+ // Identifier is an AuthzID.Value of the failed Authorization.
+ Identifier string
+
+ // Errors is a collection of non-nil error values of Challenge items
+ // of the failed Authorization.
+ Errors []error
+}
+
+func (a *AuthorizationError) Error() string {
+ e := make([]string, len(a.Errors))
+ for i, err := range a.Errors {
+ e[i] = err.Error()
+ }
+ return fmt.Sprintf("acme: authorization error for %s: %s", a.Identifier, strings.Join(e, "; "))
+}
+
+// RateLimit reports whether err represents a rate limit error and
+// any Retry-After duration returned by the server.
+//
+// See the following for more details on rate limiting:
+// https://tools.ietf.org/html/draft-ietf-acme-acme-05#section-5.6
+func RateLimit(err error) (time.Duration, bool) {
+ e, ok := err.(*Error)
+ if !ok {
+ return 0, false
+ }
+ // Some CA implementations may return incorrect values.
+ // Use case-insensitive comparison.
+ if !strings.HasSuffix(strings.ToLower(e.ProblemType), ":ratelimited") {
+ return 0, false
+ }
+ if e.Header == nil {
+ return 0, true
+ }
+ return retryAfter(e.Header.Get("Retry-After"), 0), true
+}
+
// Account is a user account. It is associated with a private key.
type Account struct {
// URI is the account unique ID, which is also a URL used to retrieve
@@ -118,6 +163,8 @@ type Directory struct {
}
// Challenge encodes a returned CA challenge.
+// Its Error field may be non-nil if the challenge is part of an Authorization
+// with StatusInvalid.
type Challenge struct {
// Type is the challenge type, e.g. "http-01", "tls-sni-02", "dns-01".
Type string
@@ -130,6 +177,11 @@ type Challenge struct {
// Status identifies the status of this challenge.
Status string
+
+ // Error indicates the reason for an authorization failure
+ // when this challenge was used.
+ // The type of a non-nil value is *Error.
+ Error error
}
// Authorization encodes an authorization response.
@@ -187,12 +239,26 @@ func (z *wireAuthz) authorization(uri string) *Authorization {
return a
}
+func (z *wireAuthz) error(uri string) *AuthorizationError {
+ err := &AuthorizationError{
+ URI: uri,
+ Identifier: z.Identifier.Value,
+ }
+ for _, raw := range z.Challenges {
+ if raw.Error != nil {
+ err.Errors = append(err.Errors, raw.Error.error(nil))
+ }
+ }
+ return err
+}
+
// wireChallenge is ACME JSON challenge representation.
type wireChallenge struct {
URI string `json:"uri"`
Type string
Token string
Status string
+ Error *wireError
}
func (c *wireChallenge) challenge() *Challenge {
@@ -205,5 +271,25 @@ func (c *wireChallenge) challenge() *Challenge {
if v.Status == "" {
v.Status = StatusPending
}
+ if c.Error != nil {
+ v.Error = c.Error.error(nil)
+ }
return v
}
+
+// wireError is a subset of fields of the Problem Details object
+// as described in https://tools.ietf.org/html/rfc7807#section-3.1.
+type wireError struct {
+ Status int
+ Type string
+ Detail string
+}
+
+func (e *wireError) error(h http.Header) *Error {
+ return &Error{
+ StatusCode: e.Status,
+ ProblemType: e.Type,
+ Detail: e.Detail,
+ Header: h,
+ }
+}
diff --git a/vendor/golang.org/x/crypto/acme/types_test.go b/vendor/golang.org/x/crypto/acme/types_test.go
new file mode 100644
index 0000000..a7553e6
--- /dev/null
+++ b/vendor/golang.org/x/crypto/acme/types_test.go
@@ -0,0 +1,63 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package acme
+
+import (
+ "errors"
+ "net/http"
+ "testing"
+ "time"
+)
+
+func TestRateLimit(t *testing.T) {
+ now := time.Date(2017, 04, 27, 10, 0, 0, 0, time.UTC)
+ f := timeNow
+ defer func() { timeNow = f }()
+ timeNow = func() time.Time { return now }
+
+ h120, hTime := http.Header{}, http.Header{}
+ h120.Set("Retry-After", "120")
+ hTime.Set("Retry-After", "Tue Apr 27 11:00:00 2017")
+
+ err1 := &Error{
+ ProblemType: "urn:ietf:params:acme:error:nolimit",
+ Header: h120,
+ }
+ err2 := &Error{
+ ProblemType: "urn:ietf:params:acme:error:rateLimited",
+ Header: h120,
+ }
+ err3 := &Error{
+ ProblemType: "urn:ietf:params:acme:error:rateLimited",
+ Header: nil,
+ }
+ err4 := &Error{
+ ProblemType: "urn:ietf:params:acme:error:rateLimited",
+ Header: hTime,
+ }
+
+ tt := []struct {
+ err error
+ res time.Duration
+ ok bool
+ }{
+ {nil, 0, false},
+ {errors.New("dummy"), 0, false},
+ {err1, 0, false},
+ {err2, 2 * time.Minute, true},
+ {err3, 0, true},
+ {err4, time.Hour, true},
+ }
+ for i, test := range tt {
+ res, ok := RateLimit(test.err)
+ if ok != test.ok {
+ t.Errorf("%d: RateLimit(%+v): ok = %v; want %v", i, test.err, ok, test.ok)
+ continue
+ }
+ if res != test.res {
+ t.Errorf("%d: RateLimit(%+v) = %v; want %v", i, test.err, res, test.res)
+ }
+ }
+}
diff --git a/vendor/golang.org/x/crypto/bcrypt/bcrypt.go b/vendor/golang.org/x/crypto/bcrypt/bcrypt.go
index f8b807f..202fa8a 100644
--- a/vendor/golang.org/x/crypto/bcrypt/bcrypt.go
+++ b/vendor/golang.org/x/crypto/bcrypt/bcrypt.go
@@ -12,9 +12,10 @@ import (
"crypto/subtle"
"errors"
"fmt"
- "golang.org/x/crypto/blowfish"
"io"
"strconv"
+
+ "golang.org/x/crypto/blowfish"
)
const (
@@ -205,7 +206,6 @@ func bcrypt(password []byte, cost int, salt []byte) ([]byte, error) {
}
func expensiveBlowfishSetup(key []byte, cost uint32, salt []byte) (*blowfish.Cipher, error) {
-
csalt, err := base64Decode(salt)
if err != nil {
return nil, err
@@ -213,7 +213,8 @@ func expensiveBlowfishSetup(key []byte, cost uint32, salt []byte) (*blowfish.Cip
// Bug compatibility with C bcrypt implementations. They use the trailing
// NULL in the key string during expansion.
- ckey := append(key, 0)
+ // We copy the key to prevent changing the underlying array.
+ ckey := append(key[:len(key):len(key)], 0)
c, err := blowfish.NewSaltedCipher(ckey, csalt)
if err != nil {
diff --git a/vendor/golang.org/x/crypto/bcrypt/bcrypt_test.go b/vendor/golang.org/x/crypto/bcrypt/bcrypt_test.go
index f08a6f5..aecf759 100644
--- a/vendor/golang.org/x/crypto/bcrypt/bcrypt_test.go
+++ b/vendor/golang.org/x/crypto/bcrypt/bcrypt_test.go
@@ -224,3 +224,20 @@ func BenchmarkGeneration(b *testing.B) {
GenerateFromPassword(passwd, 10)
}
}
+
+// See Issue https://github.com/golang/go/issues/20425.
+func TestNoSideEffectsFromCompare(t *testing.T) {
+ source := []byte("passw0rd123456")
+ password := source[:len(source)-6]
+ token := source[len(source)-6:]
+ want := make([]byte, len(source))
+ copy(want, source)
+
+ wantHash := []byte("$2a$10$LK9XRuhNxHHCvjX3tdkRKei1QiCDUKrJRhZv7WWZPuQGRUM92rOUa")
+ _ = CompareHashAndPassword(wantHash, password)
+
+ got := bytes.Join([][]byte{password, token}, []byte(""))
+ if !bytes.Equal(got, want) {
+ t.Errorf("got=%q want=%q", got, want)
+ }
+}
diff --git a/vendor/golang.org/x/crypto/blake2b/blake2b.go b/vendor/golang.org/x/crypto/blake2b/blake2b.go
index fa9e48e..ce62241 100644
--- a/vendor/golang.org/x/crypto/blake2b/blake2b.go
+++ b/vendor/golang.org/x/crypto/blake2b/blake2b.go
@@ -4,7 +4,7 @@
// Package blake2b implements the BLAKE2b hash algorithm as
// defined in RFC 7693.
-package blake2b
+package blake2b // import "golang.org/x/crypto/blake2b"
import (
"encoding/binary"
diff --git a/vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.s b/vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.s
index 96a51d5..784bce6 100644
--- a/vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.s
+++ b/vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.s
@@ -54,68 +54,223 @@ DATA ·AVX_c48<>+0x00(SB)/8, $0x0100070605040302
DATA ·AVX_c48<>+0x08(SB)/8, $0x09080f0e0d0c0b0a
GLOBL ·AVX_c48<>(SB), (NOPTR+RODATA), $16
-// unfortunately the BYTE representation of VPERMQ must be used
-#define ROUND_AVX2(m0, m1, m2, m3, t, c40, c48) \
- VPADDQ m0, Y0, Y0; \
- VPADDQ Y1, Y0, Y0; \
- VPXOR Y0, Y3, Y3; \
- VPSHUFD $-79, Y3, Y3; \
- VPADDQ Y3, Y2, Y2; \
- VPXOR Y2, Y1, Y1; \
- VPSHUFB c40, Y1, Y1; \
- VPADDQ m1, Y0, Y0; \
- VPADDQ Y1, Y0, Y0; \
- VPXOR Y0, Y3, Y3; \
- VPSHUFB c48, Y3, Y3; \
- VPADDQ Y3, Y2, Y2; \
- VPXOR Y2, Y1, Y1; \
- VPADDQ Y1, Y1, t; \
- VPSRLQ $63, Y1, Y1; \
- VPXOR t, Y1, Y1; \
- BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xc9; BYTE $0x39 \ // VPERMQ 0x39, Y1, Y1
- BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xd2; BYTE $0x4e \ // VPERMQ 0x4e, Y2, Y2
- BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xdb; BYTE $0x93 \ // VPERMQ 0x93, Y3, Y3
- VPADDQ m2, Y0, Y0; \
- VPADDQ Y1, Y0, Y0; \
- VPXOR Y0, Y3, Y3; \
- VPSHUFD $-79, Y3, Y3; \
- VPADDQ Y3, Y2, Y2; \
- VPXOR Y2, Y1, Y1; \
- VPSHUFB c40, Y1, Y1; \
- VPADDQ m3, Y0, Y0; \
- VPADDQ Y1, Y0, Y0; \
- VPXOR Y0, Y3, Y3; \
- VPSHUFB c48, Y3, Y3; \
- VPADDQ Y3, Y2, Y2; \
- VPXOR Y2, Y1, Y1; \
- VPADDQ Y1, Y1, t; \
- VPSRLQ $63, Y1, Y1; \
- VPXOR t, Y1, Y1; \
- BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xdb; BYTE $0x39 \ // VPERMQ 0x39, Y3, Y3
- BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xd2; BYTE $0x4e \ // VPERMQ 0x4e, Y2, Y2
- BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xc9; BYTE $0x93 \ // VPERMQ 0x93, Y1, Y1
+#define VPERMQ_0x39_Y1_Y1 BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xc9; BYTE $0x39
+#define VPERMQ_0x93_Y1_Y1 BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xc9; BYTE $0x93
+#define VPERMQ_0x4E_Y2_Y2 BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xd2; BYTE $0x4e
+#define VPERMQ_0x93_Y3_Y3 BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xdb; BYTE $0x93
+#define VPERMQ_0x39_Y3_Y3 BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xdb; BYTE $0x39
-// load msg into Y12, Y13, Y14, Y15
-#define LOAD_MSG_AVX2(src, i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12, i13, i14, i15) \
- MOVQ i0*8(src), X12; \
- PINSRQ $1, i1*8(src), X12; \
- MOVQ i2*8(src), X11; \
- PINSRQ $1, i3*8(src), X11; \
- VINSERTI128 $1, X11, Y12, Y12; \
- MOVQ i4*8(src), X13; \
- PINSRQ $1, i5*8(src), X13; \
- MOVQ i6*8(src), X11; \
- PINSRQ $1, i7*8(src), X11; \
- VINSERTI128 $1, X11, Y13, Y13; \
- MOVQ i8*8(src), X14; \
- PINSRQ $1, i9*8(src), X14; \
- MOVQ i10*8(src), X11; \
- PINSRQ $1, i11*8(src), X11; \
+#define ROUND_AVX2(m0, m1, m2, m3, t, c40, c48) \
+ VPADDQ m0, Y0, Y0; \
+ VPADDQ Y1, Y0, Y0; \
+ VPXOR Y0, Y3, Y3; \
+ VPSHUFD $-79, Y3, Y3; \
+ VPADDQ Y3, Y2, Y2; \
+ VPXOR Y2, Y1, Y1; \
+ VPSHUFB c40, Y1, Y1; \
+ VPADDQ m1, Y0, Y0; \
+ VPADDQ Y1, Y0, Y0; \
+ VPXOR Y0, Y3, Y3; \
+ VPSHUFB c48, Y3, Y3; \
+ VPADDQ Y3, Y2, Y2; \
+ VPXOR Y2, Y1, Y1; \
+ VPADDQ Y1, Y1, t; \
+ VPSRLQ $63, Y1, Y1; \
+ VPXOR t, Y1, Y1; \
+ VPERMQ_0x39_Y1_Y1; \
+ VPERMQ_0x4E_Y2_Y2; \
+ VPERMQ_0x93_Y3_Y3; \
+ VPADDQ m2, Y0, Y0; \
+ VPADDQ Y1, Y0, Y0; \
+ VPXOR Y0, Y3, Y3; \
+ VPSHUFD $-79, Y3, Y3; \
+ VPADDQ Y3, Y2, Y2; \
+ VPXOR Y2, Y1, Y1; \
+ VPSHUFB c40, Y1, Y1; \
+ VPADDQ m3, Y0, Y0; \
+ VPADDQ Y1, Y0, Y0; \
+ VPXOR Y0, Y3, Y3; \
+ VPSHUFB c48, Y3, Y3; \
+ VPADDQ Y3, Y2, Y2; \
+ VPXOR Y2, Y1, Y1; \
+ VPADDQ Y1, Y1, t; \
+ VPSRLQ $63, Y1, Y1; \
+ VPXOR t, Y1, Y1; \
+ VPERMQ_0x39_Y3_Y3; \
+ VPERMQ_0x4E_Y2_Y2; \
+ VPERMQ_0x93_Y1_Y1
+
+#define VMOVQ_SI_X11_0 BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x1E
+#define VMOVQ_SI_X12_0 BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x26
+#define VMOVQ_SI_X13_0 BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x2E
+#define VMOVQ_SI_X14_0 BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x36
+#define VMOVQ_SI_X15_0 BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x3E
+
+#define VMOVQ_SI_X11(n) BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x5E; BYTE $n
+#define VMOVQ_SI_X12(n) BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x66; BYTE $n
+#define VMOVQ_SI_X13(n) BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x6E; BYTE $n
+#define VMOVQ_SI_X14(n) BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x76; BYTE $n
+#define VMOVQ_SI_X15(n) BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x7E; BYTE $n
+
+#define VPINSRQ_1_SI_X11_0 BYTE $0xC4; BYTE $0x63; BYTE $0xA1; BYTE $0x22; BYTE $0x1E; BYTE $0x01
+#define VPINSRQ_1_SI_X12_0 BYTE $0xC4; BYTE $0x63; BYTE $0x99; BYTE $0x22; BYTE $0x26; BYTE $0x01
+#define VPINSRQ_1_SI_X13_0 BYTE $0xC4; BYTE $0x63; BYTE $0x91; BYTE $0x22; BYTE $0x2E; BYTE $0x01
+#define VPINSRQ_1_SI_X14_0 BYTE $0xC4; BYTE $0x63; BYTE $0x89; BYTE $0x22; BYTE $0x36; BYTE $0x01
+#define VPINSRQ_1_SI_X15_0 BYTE $0xC4; BYTE $0x63; BYTE $0x81; BYTE $0x22; BYTE $0x3E; BYTE $0x01
+
+#define VPINSRQ_1_SI_X11(n) BYTE $0xC4; BYTE $0x63; BYTE $0xA1; BYTE $0x22; BYTE $0x5E; BYTE $n; BYTE $0x01
+#define VPINSRQ_1_SI_X12(n) BYTE $0xC4; BYTE $0x63; BYTE $0x99; BYTE $0x22; BYTE $0x66; BYTE $n; BYTE $0x01
+#define VPINSRQ_1_SI_X13(n) BYTE $0xC4; BYTE $0x63; BYTE $0x91; BYTE $0x22; BYTE $0x6E; BYTE $n; BYTE $0x01
+#define VPINSRQ_1_SI_X14(n) BYTE $0xC4; BYTE $0x63; BYTE $0x89; BYTE $0x22; BYTE $0x76; BYTE $n; BYTE $0x01
+#define VPINSRQ_1_SI_X15(n) BYTE $0xC4; BYTE $0x63; BYTE $0x81; BYTE $0x22; BYTE $0x7E; BYTE $n; BYTE $0x01
+
+#define VMOVQ_R8_X15 BYTE $0xC4; BYTE $0x41; BYTE $0xF9; BYTE $0x6E; BYTE $0xF8
+#define VPINSRQ_1_R9_X15 BYTE $0xC4; BYTE $0x43; BYTE $0x81; BYTE $0x22; BYTE $0xF9; BYTE $0x01
+
+// load msg: Y12 = (i0, i1, i2, i3)
+// i0, i1, i2, i3 must not be 0
+#define LOAD_MSG_AVX2_Y12(i0, i1, i2, i3) \
+ VMOVQ_SI_X12(i0*8); \
+ VMOVQ_SI_X11(i2*8); \
+ VPINSRQ_1_SI_X12(i1*8); \
+ VPINSRQ_1_SI_X11(i3*8); \
+ VINSERTI128 $1, X11, Y12, Y12
+
+// load msg: Y13 = (i0, i1, i2, i3)
+// i0, i1, i2, i3 must not be 0
+#define LOAD_MSG_AVX2_Y13(i0, i1, i2, i3) \
+ VMOVQ_SI_X13(i0*8); \
+ VMOVQ_SI_X11(i2*8); \
+ VPINSRQ_1_SI_X13(i1*8); \
+ VPINSRQ_1_SI_X11(i3*8); \
+ VINSERTI128 $1, X11, Y13, Y13
+
+// load msg: Y14 = (i0, i1, i2, i3)
+// i0, i1, i2, i3 must not be 0
+#define LOAD_MSG_AVX2_Y14(i0, i1, i2, i3) \
+ VMOVQ_SI_X14(i0*8); \
+ VMOVQ_SI_X11(i2*8); \
+ VPINSRQ_1_SI_X14(i1*8); \
+ VPINSRQ_1_SI_X11(i3*8); \
+ VINSERTI128 $1, X11, Y14, Y14
+
+// load msg: Y15 = (i0, i1, i2, i3)
+// i0, i1, i2, i3 must not be 0
+#define LOAD_MSG_AVX2_Y15(i0, i1, i2, i3) \
+ VMOVQ_SI_X15(i0*8); \
+ VMOVQ_SI_X11(i2*8); \
+ VPINSRQ_1_SI_X15(i1*8); \
+ VPINSRQ_1_SI_X11(i3*8); \
+ VINSERTI128 $1, X11, Y15, Y15
+
+#define LOAD_MSG_AVX2_0_2_4_6_1_3_5_7_8_10_12_14_9_11_13_15() \
+ VMOVQ_SI_X12_0; \
+ VMOVQ_SI_X11(4*8); \
+ VPINSRQ_1_SI_X12(2*8); \
+ VPINSRQ_1_SI_X11(6*8); \
+ VINSERTI128 $1, X11, Y12, Y12; \
+ LOAD_MSG_AVX2_Y13(1, 3, 5, 7); \
+ LOAD_MSG_AVX2_Y14(8, 10, 12, 14); \
+ LOAD_MSG_AVX2_Y15(9, 11, 13, 15)
+
+#define LOAD_MSG_AVX2_14_4_9_13_10_8_15_6_1_0_11_5_12_2_7_3() \
+ LOAD_MSG_AVX2_Y12(14, 4, 9, 13); \
+ LOAD_MSG_AVX2_Y13(10, 8, 15, 6); \
+ VMOVQ_SI_X11(11*8); \
+ VPSHUFD $0x4E, 0*8(SI), X14; \
+ VPINSRQ_1_SI_X11(5*8); \
VINSERTI128 $1, X11, Y14, Y14; \
- MOVQ i12*8(src), X15; \
- PINSRQ $1, i13*8(src), X15; \
- MOVQ i14*8(src), X11; \
- PINSRQ $1, i15*8(src), X11; \
+ LOAD_MSG_AVX2_Y15(12, 2, 7, 3)
+
+#define LOAD_MSG_AVX2_11_12_5_15_8_0_2_13_10_3_7_9_14_6_1_4() \
+ VMOVQ_SI_X11(5*8); \
+ VMOVDQU 11*8(SI), X12; \
+ VPINSRQ_1_SI_X11(15*8); \
+ VINSERTI128 $1, X11, Y12, Y12; \
+ VMOVQ_SI_X13(8*8); \
+ VMOVQ_SI_X11(2*8); \
+ VPINSRQ_1_SI_X13_0; \
+ VPINSRQ_1_SI_X11(13*8); \
+ VINSERTI128 $1, X11, Y13, Y13; \
+ LOAD_MSG_AVX2_Y14(10, 3, 7, 9); \
+ LOAD_MSG_AVX2_Y15(14, 6, 1, 4)
+
+#define LOAD_MSG_AVX2_7_3_13_11_9_1_12_14_2_5_4_15_6_10_0_8() \
+ LOAD_MSG_AVX2_Y12(7, 3, 13, 11); \
+ LOAD_MSG_AVX2_Y13(9, 1, 12, 14); \
+ LOAD_MSG_AVX2_Y14(2, 5, 4, 15); \
+ VMOVQ_SI_X15(6*8); \
+ VMOVQ_SI_X11_0; \
+ VPINSRQ_1_SI_X15(10*8); \
+ VPINSRQ_1_SI_X11(8*8); \
+ VINSERTI128 $1, X11, Y15, Y15
+
+#define LOAD_MSG_AVX2_9_5_2_10_0_7_4_15_14_11_6_3_1_12_8_13() \
+ LOAD_MSG_AVX2_Y12(9, 5, 2, 10); \
+ VMOVQ_SI_X13_0; \
+ VMOVQ_SI_X11(4*8); \
+ VPINSRQ_1_SI_X13(7*8); \
+ VPINSRQ_1_SI_X11(15*8); \
+ VINSERTI128 $1, X11, Y13, Y13; \
+ LOAD_MSG_AVX2_Y14(14, 11, 6, 3); \
+ LOAD_MSG_AVX2_Y15(1, 12, 8, 13)
+
+#define LOAD_MSG_AVX2_2_6_0_8_12_10_11_3_4_7_15_1_13_5_14_9() \
+ VMOVQ_SI_X12(2*8); \
+ VMOVQ_SI_X11_0; \
+ VPINSRQ_1_SI_X12(6*8); \
+ VPINSRQ_1_SI_X11(8*8); \
+ VINSERTI128 $1, X11, Y12, Y12; \
+ LOAD_MSG_AVX2_Y13(12, 10, 11, 3); \
+ LOAD_MSG_AVX2_Y14(4, 7, 15, 1); \
+ LOAD_MSG_AVX2_Y15(13, 5, 14, 9)
+
+#define LOAD_MSG_AVX2_12_1_14_4_5_15_13_10_0_6_9_8_7_3_2_11() \
+ LOAD_MSG_AVX2_Y12(12, 1, 14, 4); \
+ LOAD_MSG_AVX2_Y13(5, 15, 13, 10); \
+ VMOVQ_SI_X14_0; \
+ VPSHUFD $0x4E, 8*8(SI), X11; \
+ VPINSRQ_1_SI_X14(6*8); \
+ VINSERTI128 $1, X11, Y14, Y14; \
+ LOAD_MSG_AVX2_Y15(7, 3, 2, 11)
+
+#define LOAD_MSG_AVX2_13_7_12_3_11_14_1_9_5_15_8_2_0_4_6_10() \
+ LOAD_MSG_AVX2_Y12(13, 7, 12, 3); \
+ LOAD_MSG_AVX2_Y13(11, 14, 1, 9); \
+ LOAD_MSG_AVX2_Y14(5, 15, 8, 2); \
+ VMOVQ_SI_X15_0; \
+ VMOVQ_SI_X11(6*8); \
+ VPINSRQ_1_SI_X15(4*8); \
+ VPINSRQ_1_SI_X11(10*8); \
+ VINSERTI128 $1, X11, Y15, Y15
+
+#define LOAD_MSG_AVX2_6_14_11_0_15_9_3_8_12_13_1_10_2_7_4_5() \
+ VMOVQ_SI_X12(6*8); \
+ VMOVQ_SI_X11(11*8); \
+ VPINSRQ_1_SI_X12(14*8); \
+ VPINSRQ_1_SI_X11_0; \
+ VINSERTI128 $1, X11, Y12, Y12; \
+ LOAD_MSG_AVX2_Y13(15, 9, 3, 8); \
+ VMOVQ_SI_X11(1*8); \
+ VMOVDQU 12*8(SI), X14; \
+ VPINSRQ_1_SI_X11(10*8); \
+ VINSERTI128 $1, X11, Y14, Y14; \
+ VMOVQ_SI_X15(2*8); \
+ VMOVDQU 4*8(SI), X11; \
+ VPINSRQ_1_SI_X15(7*8); \
+ VINSERTI128 $1, X11, Y15, Y15
+
+#define LOAD_MSG_AVX2_10_8_7_1_2_4_6_5_15_9_3_13_11_14_12_0() \
+ LOAD_MSG_AVX2_Y12(10, 8, 7, 1); \
+ VMOVQ_SI_X13(2*8); \
+ VPSHUFD $0x4E, 5*8(SI), X11; \
+ VPINSRQ_1_SI_X13(4*8); \
+ VINSERTI128 $1, X11, Y13, Y13; \
+ LOAD_MSG_AVX2_Y14(15, 9, 3, 13); \
+ VMOVQ_SI_X15(11*8); \
+ VMOVQ_SI_X11(12*8); \
+ VPINSRQ_1_SI_X15(14*8); \
+ VPINSRQ_1_SI_X11_0; \
VINSERTI128 $1, X11, Y15, Y15
// func hashBlocksAVX2(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte)
@@ -162,34 +317,34 @@ noinc:
VMOVDQA Y6, Y2
VPXOR 0(SP), Y7, Y3
- LOAD_MSG_AVX2(SI, 0, 2, 4, 6, 1, 3, 5, 7, 8, 10, 12, 14, 9, 11, 13, 15)
+ LOAD_MSG_AVX2_0_2_4_6_1_3_5_7_8_10_12_14_9_11_13_15()
VMOVDQA Y12, 32(SP)
VMOVDQA Y13, 64(SP)
VMOVDQA Y14, 96(SP)
VMOVDQA Y15, 128(SP)
ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5)
- LOAD_MSG_AVX2(SI, 14, 4, 9, 13, 10, 8, 15, 6, 1, 0, 11, 5, 12, 2, 7, 3)
+ LOAD_MSG_AVX2_14_4_9_13_10_8_15_6_1_0_11_5_12_2_7_3()
VMOVDQA Y12, 160(SP)
VMOVDQA Y13, 192(SP)
VMOVDQA Y14, 224(SP)
VMOVDQA Y15, 256(SP)
ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5)
- LOAD_MSG_AVX2(SI, 11, 12, 5, 15, 8, 0, 2, 13, 10, 3, 7, 9, 14, 6, 1, 4)
+ LOAD_MSG_AVX2_11_12_5_15_8_0_2_13_10_3_7_9_14_6_1_4()
ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5)
- LOAD_MSG_AVX2(SI, 7, 3, 13, 11, 9, 1, 12, 14, 2, 5, 4, 15, 6, 10, 0, 8)
+ LOAD_MSG_AVX2_7_3_13_11_9_1_12_14_2_5_4_15_6_10_0_8()
ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5)
- LOAD_MSG_AVX2(SI, 9, 5, 2, 10, 0, 7, 4, 15, 14, 11, 6, 3, 1, 12, 8, 13)
+ LOAD_MSG_AVX2_9_5_2_10_0_7_4_15_14_11_6_3_1_12_8_13()
ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5)
- LOAD_MSG_AVX2(SI, 2, 6, 0, 8, 12, 10, 11, 3, 4, 7, 15, 1, 13, 5, 14, 9)
+ LOAD_MSG_AVX2_2_6_0_8_12_10_11_3_4_7_15_1_13_5_14_9()
ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5)
- LOAD_MSG_AVX2(SI, 12, 1, 14, 4, 5, 15, 13, 10, 0, 6, 9, 8, 7, 3, 2, 11)
+ LOAD_MSG_AVX2_12_1_14_4_5_15_13_10_0_6_9_8_7_3_2_11()
ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5)
- LOAD_MSG_AVX2(SI, 13, 7, 12, 3, 11, 14, 1, 9, 5, 15, 8, 2, 0, 4, 6, 10)
+ LOAD_MSG_AVX2_13_7_12_3_11_14_1_9_5_15_8_2_0_4_6_10()
ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5)
- LOAD_MSG_AVX2(SI, 6, 14, 11, 0, 15, 9, 3, 8, 12, 13, 1, 10, 2, 7, 4, 5)
+ LOAD_MSG_AVX2_6_14_11_0_15_9_3_8_12_13_1_10_2_7_4_5()
ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5)
- LOAD_MSG_AVX2(SI, 10, 8, 7, 1, 2, 4, 6, 5, 15, 9, 3, 13, 11, 14, 12, 0)
+ LOAD_MSG_AVX2_10_8_7_1_2_4_6_5_15_9_3_13_11_14_12_0()
ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5)
ROUND_AVX2(32(SP), 64(SP), 96(SP), 128(SP), Y10, Y4, Y5)
@@ -209,56 +364,55 @@ noinc:
VMOVDQU Y8, 0(AX)
VMOVDQU Y9, 32(AX)
+ VZEROUPPER
MOVQ DX, SP
RET
-// unfortunately the BYTE representation of VPUNPCKLQDQ and VPUNPCKHQDQ must be used
-#define VPUNPCKLQDQ_X8_X8_X10 BYTE $0xC4; BYTE $0x41; BYTE $0x39; BYTE $0x6C; BYTE $0xD0
-#define VPUNPCKHQDQ_X7_X10_X6 BYTE $0xC4; BYTE $0xC1; BYTE $0x41; BYTE $0x6D; BYTE $0xF2
-#define VPUNPCKLQDQ_X7_X7_X10 BYTE $0xC5; BYTE $0x41; BYTE $0x6C; BYTE $0xD7
-#define VPUNPCKHQDQ_X8_X10_X7 BYTE $0xC4; BYTE $0xC1; BYTE $0x39; BYTE $0x6D; BYTE $0xFA
-#define VPUNPCKLQDQ_X3_X3_X10 BYTE $0xC5; BYTE $0x61; BYTE $0x6C; BYTE $0xD3
-#define VPUNPCKHQDQ_X2_X10_X2 BYTE $0xC4; BYTE $0xC1; BYTE $0x69; BYTE $0x6D; BYTE $0xD2
-#define VPUNPCKLQDQ_X9_X9_X10 BYTE $0xC4; BYTE $0x41; BYTE $0x31; BYTE $0x6C; BYTE $0xD1
-#define VPUNPCKHQDQ_X3_X10_X3 BYTE $0xC4; BYTE $0xC1; BYTE $0x61; BYTE $0x6D; BYTE $0xDA
-#define VPUNPCKLQDQ_X2_X2_X10 BYTE $0xC5; BYTE $0x69; BYTE $0x6C; BYTE $0xD2
-#define VPUNPCKHQDQ_X3_X10_X2 BYTE $0xC4; BYTE $0xC1; BYTE $0x61; BYTE $0x6D; BYTE $0xD2
-#define VPUNPCKHQDQ_X8_X10_X3 BYTE $0xC4; BYTE $0xC1; BYTE $0x39; BYTE $0x6D; BYTE $0xDA
-#define VPUNPCKHQDQ_X6_X10_X6 BYTE $0xC4; BYTE $0xC1; BYTE $0x49; BYTE $0x6D; BYTE $0xF2
-#define VPUNPCKHQDQ_X7_X10_X7 BYTE $0xC4; BYTE $0xC1; BYTE $0x41; BYTE $0x6D; BYTE $0xFA
+#define VPUNPCKLQDQ_X2_X2_X15 BYTE $0xC5; BYTE $0x69; BYTE $0x6C; BYTE $0xFA
+#define VPUNPCKLQDQ_X3_X3_X15 BYTE $0xC5; BYTE $0x61; BYTE $0x6C; BYTE $0xFB
+#define VPUNPCKLQDQ_X7_X7_X15 BYTE $0xC5; BYTE $0x41; BYTE $0x6C; BYTE $0xFF
+#define VPUNPCKLQDQ_X13_X13_X15 BYTE $0xC4; BYTE $0x41; BYTE $0x11; BYTE $0x6C; BYTE $0xFD
+#define VPUNPCKLQDQ_X14_X14_X15 BYTE $0xC4; BYTE $0x41; BYTE $0x09; BYTE $0x6C; BYTE $0xFE
+
+#define VPUNPCKHQDQ_X15_X2_X2 BYTE $0xC4; BYTE $0xC1; BYTE $0x69; BYTE $0x6D; BYTE $0xD7
+#define VPUNPCKHQDQ_X15_X3_X3 BYTE $0xC4; BYTE $0xC1; BYTE $0x61; BYTE $0x6D; BYTE $0xDF
+#define VPUNPCKHQDQ_X15_X6_X6 BYTE $0xC4; BYTE $0xC1; BYTE $0x49; BYTE $0x6D; BYTE $0xF7
+#define VPUNPCKHQDQ_X15_X7_X7 BYTE $0xC4; BYTE $0xC1; BYTE $0x41; BYTE $0x6D; BYTE $0xFF
+#define VPUNPCKHQDQ_X15_X3_X2 BYTE $0xC4; BYTE $0xC1; BYTE $0x61; BYTE $0x6D; BYTE $0xD7
+#define VPUNPCKHQDQ_X15_X7_X6 BYTE $0xC4; BYTE $0xC1; BYTE $0x41; BYTE $0x6D; BYTE $0xF7
+#define VPUNPCKHQDQ_X15_X13_X3 BYTE $0xC4; BYTE $0xC1; BYTE $0x11; BYTE $0x6D; BYTE $0xDF
+#define VPUNPCKHQDQ_X15_X13_X7 BYTE $0xC4; BYTE $0xC1; BYTE $0x11; BYTE $0x6D; BYTE $0xFF
-// shuffle X2 and X6 using the temp registers X8, X9, X10
#define SHUFFLE_AVX() \
- VMOVDQA X4, X9; \
- VMOVDQA X5, X4; \
- VMOVDQA X9, X5; \
- VMOVDQA X6, X8; \
- VPUNPCKLQDQ_X8_X8_X10; \
- VPUNPCKHQDQ_X7_X10_X6; \
- VPUNPCKLQDQ_X7_X7_X10; \
- VPUNPCKHQDQ_X8_X10_X7; \
- VPUNPCKLQDQ_X3_X3_X10; \
- VMOVDQA X2, X9; \
- VPUNPCKHQDQ_X2_X10_X2; \
- VPUNPCKLQDQ_X9_X9_X10; \
- VPUNPCKHQDQ_X3_X10_X3; \
+ VMOVDQA X6, X13; \
+ VMOVDQA X2, X14; \
+ VMOVDQA X4, X6; \
+ VPUNPCKLQDQ_X13_X13_X15; \
+ VMOVDQA X5, X4; \
+ VMOVDQA X6, X5; \
+ VPUNPCKHQDQ_X15_X7_X6; \
+ VPUNPCKLQDQ_X7_X7_X15; \
+ VPUNPCKHQDQ_X15_X13_X7; \
+ VPUNPCKLQDQ_X3_X3_X15; \
+ VPUNPCKHQDQ_X15_X2_X2; \
+ VPUNPCKLQDQ_X14_X14_X15; \
+ VPUNPCKHQDQ_X15_X3_X3; \
-// inverse shuffle X2 and X6 using the temp registers X8, X9, X10
#define SHUFFLE_AVX_INV() \
- VMOVDQA X4, X9; \
- VMOVDQA X5, X4; \
- VMOVDQA X9, X5; \
- VMOVDQA X2, X8; \
- VPUNPCKLQDQ_X2_X2_X10; \
- VPUNPCKHQDQ_X3_X10_X2; \
- VPUNPCKLQDQ_X3_X3_X10; \
- VPUNPCKHQDQ_X8_X10_X3; \
- VPUNPCKLQDQ_X7_X7_X10; \
- VMOVDQA X6, X9; \
- VPUNPCKHQDQ_X6_X10_X6; \
- VPUNPCKLQDQ_X9_X9_X10; \
- VPUNPCKHQDQ_X7_X10_X7; \
+ VMOVDQA X2, X13; \
+ VMOVDQA X4, X14; \
+ VPUNPCKLQDQ_X2_X2_X15; \
+ VMOVDQA X5, X4; \
+ VPUNPCKHQDQ_X15_X3_X2; \
+ VMOVDQA X14, X5; \
+ VPUNPCKLQDQ_X3_X3_X15; \
+ VMOVDQA X6, X14; \
+ VPUNPCKHQDQ_X15_X13_X3; \
+ VPUNPCKLQDQ_X7_X7_X15; \
+ VPUNPCKHQDQ_X15_X6_X6; \
+ VPUNPCKLQDQ_X14_X14_X15; \
+ VPUNPCKHQDQ_X15_X7_X7; \
#define HALF_ROUND_AVX(v0, v1, v2, v3, v4, v5, v6, v7, m0, m1, m2, m3, t0, c40, c48) \
VPADDQ m0, v0, v0; \
@@ -294,28 +448,133 @@ noinc:
VPSRLQ $63, v3, v3; \
VPXOR t0, v3, v3
-// unfortunately the BYTE representation of VPINSRQ must be used
-#define VPINSRQ_1_R10_X8_X8 BYTE $0xC4; BYTE $0x43; BYTE $0xB9; BYTE $0x22; BYTE $0xC2; BYTE $0x01
-#define VPINSRQ_1_R11_X9_X9 BYTE $0xC4; BYTE $0x43; BYTE $0xB1; BYTE $0x22; BYTE $0xCB; BYTE $0x01
-#define VPINSRQ_1_R12_X10_X10 BYTE $0xC4; BYTE $0x43; BYTE $0xA9; BYTE $0x22; BYTE $0xD4; BYTE $0x01
-#define VPINSRQ_1_R13_X11_X11 BYTE $0xC4; BYTE $0x43; BYTE $0xA1; BYTE $0x22; BYTE $0xDD; BYTE $0x01
+// load msg: X12 = (i0, i1), X13 = (i2, i3), X14 = (i4, i5), X15 = (i6, i7)
+// i0, i1, i2, i3, i4, i5, i6, i7 must not be 0
+#define LOAD_MSG_AVX(i0, i1, i2, i3, i4, i5, i6, i7) \
+ VMOVQ_SI_X12(i0*8); \
+ VMOVQ_SI_X13(i2*8); \
+ VMOVQ_SI_X14(i4*8); \
+ VMOVQ_SI_X15(i6*8); \
+ VPINSRQ_1_SI_X12(i1*8); \
+ VPINSRQ_1_SI_X13(i3*8); \
+ VPINSRQ_1_SI_X14(i5*8); \
+ VPINSRQ_1_SI_X15(i7*8)
-#define VPINSRQ_1_R9_X8_X8 BYTE $0xC4; BYTE $0x43; BYTE $0xB9; BYTE $0x22; BYTE $0xC1; BYTE $0x01
+// load msg: X12 = (0, 2), X13 = (4, 6), X14 = (1, 3), X15 = (5, 7)
+#define LOAD_MSG_AVX_0_2_4_6_1_3_5_7() \
+ VMOVQ_SI_X12_0; \
+ VMOVQ_SI_X13(4*8); \
+ VMOVQ_SI_X14(1*8); \
+ VMOVQ_SI_X15(5*8); \
+ VPINSRQ_1_SI_X12(2*8); \
+ VPINSRQ_1_SI_X13(6*8); \
+ VPINSRQ_1_SI_X14(3*8); \
+ VPINSRQ_1_SI_X15(7*8)
-// load src into X8, X9, X10 and X11 using R10, R11, R12 and R13 for temp registers
-#define LOAD_MSG_AVX(src, i0, i1, i2, i3, i4, i5, i6, i7) \
- MOVQ i0*8(src), X8; \
- MOVQ i1*8(src), R10; \
- MOVQ i2*8(src), X9; \
- MOVQ i3*8(src), R11; \
- MOVQ i4*8(src), X10; \
- MOVQ i5*8(src), R12; \
- MOVQ i6*8(src), X11; \
- MOVQ i7*8(src), R13; \
- VPINSRQ_1_R10_X8_X8; \
- VPINSRQ_1_R11_X9_X9; \
- VPINSRQ_1_R12_X10_X10; \
- VPINSRQ_1_R13_X11_X11
+// load msg: X12 = (1, 0), X13 = (11, 5), X14 = (12, 2), X15 = (7, 3)
+#define LOAD_MSG_AVX_1_0_11_5_12_2_7_3() \
+ VPSHUFD $0x4E, 0*8(SI), X12; \
+ VMOVQ_SI_X13(11*8); \
+ VMOVQ_SI_X14(12*8); \
+ VMOVQ_SI_X15(7*8); \
+ VPINSRQ_1_SI_X13(5*8); \
+ VPINSRQ_1_SI_X14(2*8); \
+ VPINSRQ_1_SI_X15(3*8)
+
+// load msg: X12 = (11, 12), X13 = (5, 15), X14 = (8, 0), X15 = (2, 13)
+#define LOAD_MSG_AVX_11_12_5_15_8_0_2_13() \
+ VMOVDQU 11*8(SI), X12; \
+ VMOVQ_SI_X13(5*8); \
+ VMOVQ_SI_X14(8*8); \
+ VMOVQ_SI_X15(2*8); \
+ VPINSRQ_1_SI_X13(15*8); \
+ VPINSRQ_1_SI_X14_0; \
+ VPINSRQ_1_SI_X15(13*8)
+
+// load msg: X12 = (2, 5), X13 = (4, 15), X14 = (6, 10), X15 = (0, 8)
+#define LOAD_MSG_AVX_2_5_4_15_6_10_0_8() \
+ VMOVQ_SI_X12(2*8); \
+ VMOVQ_SI_X13(4*8); \
+ VMOVQ_SI_X14(6*8); \
+ VMOVQ_SI_X15_0; \
+ VPINSRQ_1_SI_X12(5*8); \
+ VPINSRQ_1_SI_X13(15*8); \
+ VPINSRQ_1_SI_X14(10*8); \
+ VPINSRQ_1_SI_X15(8*8)
+
+// load msg: X12 = (9, 5), X13 = (2, 10), X14 = (0, 7), X15 = (4, 15)
+#define LOAD_MSG_AVX_9_5_2_10_0_7_4_15() \
+ VMOVQ_SI_X12(9*8); \
+ VMOVQ_SI_X13(2*8); \
+ VMOVQ_SI_X14_0; \
+ VMOVQ_SI_X15(4*8); \
+ VPINSRQ_1_SI_X12(5*8); \
+ VPINSRQ_1_SI_X13(10*8); \
+ VPINSRQ_1_SI_X14(7*8); \
+ VPINSRQ_1_SI_X15(15*8)
+
+// load msg: X12 = (2, 6), X13 = (0, 8), X14 = (12, 10), X15 = (11, 3)
+#define LOAD_MSG_AVX_2_6_0_8_12_10_11_3() \
+ VMOVQ_SI_X12(2*8); \
+ VMOVQ_SI_X13_0; \
+ VMOVQ_SI_X14(12*8); \
+ VMOVQ_SI_X15(11*8); \
+ VPINSRQ_1_SI_X12(6*8); \
+ VPINSRQ_1_SI_X13(8*8); \
+ VPINSRQ_1_SI_X14(10*8); \
+ VPINSRQ_1_SI_X15(3*8)
+
+// load msg: X12 = (0, 6), X13 = (9, 8), X14 = (7, 3), X15 = (2, 11)
+#define LOAD_MSG_AVX_0_6_9_8_7_3_2_11() \
+ MOVQ 0*8(SI), X12; \
+ VPSHUFD $0x4E, 8*8(SI), X13; \
+ MOVQ 7*8(SI), X14; \
+ MOVQ 2*8(SI), X15; \
+ VPINSRQ_1_SI_X12(6*8); \
+ VPINSRQ_1_SI_X14(3*8); \
+ VPINSRQ_1_SI_X15(11*8)
+
+// load msg: X12 = (6, 14), X13 = (11, 0), X14 = (15, 9), X15 = (3, 8)
+#define LOAD_MSG_AVX_6_14_11_0_15_9_3_8() \
+ MOVQ 6*8(SI), X12; \
+ MOVQ 11*8(SI), X13; \
+ MOVQ 15*8(SI), X14; \
+ MOVQ 3*8(SI), X15; \
+ VPINSRQ_1_SI_X12(14*8); \
+ VPINSRQ_1_SI_X13_0; \
+ VPINSRQ_1_SI_X14(9*8); \
+ VPINSRQ_1_SI_X15(8*8)
+
+// load msg: X12 = (5, 15), X13 = (8, 2), X14 = (0, 4), X15 = (6, 10)
+#define LOAD_MSG_AVX_5_15_8_2_0_4_6_10() \
+ MOVQ 5*8(SI), X12; \
+ MOVQ 8*8(SI), X13; \
+ MOVQ 0*8(SI), X14; \
+ MOVQ 6*8(SI), X15; \
+ VPINSRQ_1_SI_X12(15*8); \
+ VPINSRQ_1_SI_X13(2*8); \
+ VPINSRQ_1_SI_X14(4*8); \
+ VPINSRQ_1_SI_X15(10*8)
+
+// load msg: X12 = (12, 13), X13 = (1, 10), X14 = (2, 7), X15 = (4, 5)
+#define LOAD_MSG_AVX_12_13_1_10_2_7_4_5() \
+ VMOVDQU 12*8(SI), X12; \
+ MOVQ 1*8(SI), X13; \
+ MOVQ 2*8(SI), X14; \
+ VPINSRQ_1_SI_X13(10*8); \
+ VPINSRQ_1_SI_X14(7*8); \
+ VMOVDQU 4*8(SI), X15
+
+// load msg: X12 = (15, 9), X13 = (3, 13), X14 = (11, 14), X15 = (12, 0)
+#define LOAD_MSG_AVX_15_9_3_13_11_14_12_0() \
+ MOVQ 15*8(SI), X12; \
+ MOVQ 3*8(SI), X13; \
+ MOVQ 11*8(SI), X14; \
+ MOVQ 12*8(SI), X15; \
+ VPINSRQ_1_SI_X12(9*8); \
+ VPINSRQ_1_SI_X13(13*8); \
+ VPINSRQ_1_SI_X14(14*8); \
+ VPINSRQ_1_SI_X15_0
// func hashBlocksAVX(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte)
TEXT ·hashBlocksAVX(SB), 4, $288-48 // frame size = 272 + 16 byte alignment
@@ -331,15 +590,17 @@ TEXT ·hashBlocksAVX(SB), 4, $288-48 // frame size = 272 + 16 byte alignment
ANDQ $~15, R9
MOVQ R9, SP
- MOVOU ·AVX_c40<>(SB), X13
- MOVOU ·AVX_c48<>(SB), X14
+ VMOVDQU ·AVX_c40<>(SB), X0
+ VMOVDQU ·AVX_c48<>(SB), X1
+ VMOVDQA X0, X8
+ VMOVDQA X1, X9
VMOVDQU ·AVX_iv3<>(SB), X0
VMOVDQA X0, 0(SP)
XORQ CX, 0(SP) // 0(SP) = ·AVX_iv3 ^ (CX || 0)
- VMOVDQU 0(AX), X12
- VMOVDQU 16(AX), X15
+ VMOVDQU 0(AX), X10
+ VMOVDQU 16(AX), X11
VMOVDQU 32(AX), X2
VMOVDQU 48(AX), X3
@@ -353,124 +614,124 @@ loop:
INCQ R9
noinc:
- MOVQ R8, X8
- VPINSRQ_1_R9_X8_X8
+ VMOVQ_R8_X15
+ VPINSRQ_1_R9_X15
- VMOVDQA X12, X0
- VMOVDQA X15, X1
+ VMOVDQA X10, X0
+ VMOVDQA X11, X1
VMOVDQU ·AVX_iv0<>(SB), X4
VMOVDQU ·AVX_iv1<>(SB), X5
VMOVDQU ·AVX_iv2<>(SB), X6
- VPXOR X8, X6, X6
+ VPXOR X15, X6, X6
VMOVDQA 0(SP), X7
- LOAD_MSG_AVX(SI, 0, 2, 4, 6, 1, 3, 5, 7)
- VMOVDQA X8, 16(SP)
- VMOVDQA X9, 32(SP)
- VMOVDQA X10, 48(SP)
- VMOVDQA X11, 64(SP)
- HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
+ LOAD_MSG_AVX_0_2_4_6_1_3_5_7()
+ VMOVDQA X12, 16(SP)
+ VMOVDQA X13, 32(SP)
+ VMOVDQA X14, 48(SP)
+ VMOVDQA X15, 64(SP)
+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
SHUFFLE_AVX()
- LOAD_MSG_AVX(SI, 8, 10, 12, 14, 9, 11, 13, 15)
- VMOVDQA X8, 80(SP)
- VMOVDQA X9, 96(SP)
- VMOVDQA X10, 112(SP)
- VMOVDQA X11, 128(SP)
- HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
+ LOAD_MSG_AVX(8, 10, 12, 14, 9, 11, 13, 15)
+ VMOVDQA X12, 80(SP)
+ VMOVDQA X13, 96(SP)
+ VMOVDQA X14, 112(SP)
+ VMOVDQA X15, 128(SP)
+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
SHUFFLE_AVX_INV()
- LOAD_MSG_AVX(SI, 14, 4, 9, 13, 10, 8, 15, 6)
- VMOVDQA X8, 144(SP)
- VMOVDQA X9, 160(SP)
- VMOVDQA X10, 176(SP)
- VMOVDQA X11, 192(SP)
- HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
+ LOAD_MSG_AVX(14, 4, 9, 13, 10, 8, 15, 6)
+ VMOVDQA X12, 144(SP)
+ VMOVDQA X13, 160(SP)
+ VMOVDQA X14, 176(SP)
+ VMOVDQA X15, 192(SP)
+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
SHUFFLE_AVX()
- LOAD_MSG_AVX(SI, 1, 0, 11, 5, 12, 2, 7, 3)
- VMOVDQA X8, 208(SP)
- VMOVDQA X9, 224(SP)
- VMOVDQA X10, 240(SP)
- VMOVDQA X11, 256(SP)
- HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
+ LOAD_MSG_AVX_1_0_11_5_12_2_7_3()
+ VMOVDQA X12, 208(SP)
+ VMOVDQA X13, 224(SP)
+ VMOVDQA X14, 240(SP)
+ VMOVDQA X15, 256(SP)
+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
SHUFFLE_AVX_INV()
- LOAD_MSG_AVX(SI, 11, 12, 5, 15, 8, 0, 2, 13)
- HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
+ LOAD_MSG_AVX_11_12_5_15_8_0_2_13()
+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
SHUFFLE_AVX()
- LOAD_MSG_AVX(SI, 10, 3, 7, 9, 14, 6, 1, 4)
- HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
+ LOAD_MSG_AVX(10, 3, 7, 9, 14, 6, 1, 4)
+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
SHUFFLE_AVX_INV()
- LOAD_MSG_AVX(SI, 7, 3, 13, 11, 9, 1, 12, 14)
- HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
+ LOAD_MSG_AVX(7, 3, 13, 11, 9, 1, 12, 14)
+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
SHUFFLE_AVX()
- LOAD_MSG_AVX(SI, 2, 5, 4, 15, 6, 10, 0, 8)
- HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
+ LOAD_MSG_AVX_2_5_4_15_6_10_0_8()
+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
SHUFFLE_AVX_INV()
- LOAD_MSG_AVX(SI, 9, 5, 2, 10, 0, 7, 4, 15)
- HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
+ LOAD_MSG_AVX_9_5_2_10_0_7_4_15()
+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
SHUFFLE_AVX()
- LOAD_MSG_AVX(SI, 14, 11, 6, 3, 1, 12, 8, 13)
- HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
+ LOAD_MSG_AVX(14, 11, 6, 3, 1, 12, 8, 13)
+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
SHUFFLE_AVX_INV()
- LOAD_MSG_AVX(SI, 2, 6, 0, 8, 12, 10, 11, 3)
- HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
+ LOAD_MSG_AVX_2_6_0_8_12_10_11_3()
+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
SHUFFLE_AVX()
- LOAD_MSG_AVX(SI, 4, 7, 15, 1, 13, 5, 14, 9)
- HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
+ LOAD_MSG_AVX(4, 7, 15, 1, 13, 5, 14, 9)
+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
SHUFFLE_AVX_INV()
- LOAD_MSG_AVX(SI, 12, 1, 14, 4, 5, 15, 13, 10)
- HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
+ LOAD_MSG_AVX(12, 1, 14, 4, 5, 15, 13, 10)
+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
SHUFFLE_AVX()
- LOAD_MSG_AVX(SI, 0, 6, 9, 8, 7, 3, 2, 11)
- HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
+ LOAD_MSG_AVX_0_6_9_8_7_3_2_11()
+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
SHUFFLE_AVX_INV()
- LOAD_MSG_AVX(SI, 13, 7, 12, 3, 11, 14, 1, 9)
- HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
+ LOAD_MSG_AVX(13, 7, 12, 3, 11, 14, 1, 9)
+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
SHUFFLE_AVX()
- LOAD_MSG_AVX(SI, 5, 15, 8, 2, 0, 4, 6, 10)
- HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
+ LOAD_MSG_AVX_5_15_8_2_0_4_6_10()
+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
SHUFFLE_AVX_INV()
- LOAD_MSG_AVX(SI, 6, 14, 11, 0, 15, 9, 3, 8)
- HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
+ LOAD_MSG_AVX_6_14_11_0_15_9_3_8()
+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
SHUFFLE_AVX()
- LOAD_MSG_AVX(SI, 12, 13, 1, 10, 2, 7, 4, 5)
- HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
+ LOAD_MSG_AVX_12_13_1_10_2_7_4_5()
+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
SHUFFLE_AVX_INV()
- LOAD_MSG_AVX(SI, 10, 8, 7, 1, 2, 4, 6, 5)
- HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
+ LOAD_MSG_AVX(10, 8, 7, 1, 2, 4, 6, 5)
+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
SHUFFLE_AVX()
- LOAD_MSG_AVX(SI, 15, 9, 3, 13, 11, 14, 12, 0)
- HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
+ LOAD_MSG_AVX_15_9_3_13_11_14_12_0()
+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
SHUFFLE_AVX_INV()
- HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, 16(SP), 32(SP), 48(SP), 64(SP), X11, X13, X14)
+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, 16(SP), 32(SP), 48(SP), 64(SP), X15, X8, X9)
SHUFFLE_AVX()
- HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, 80(SP), 96(SP), 112(SP), 128(SP), X11, X13, X14)
+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, 80(SP), 96(SP), 112(SP), 128(SP), X15, X8, X9)
SHUFFLE_AVX_INV()
- HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, 144(SP), 160(SP), 176(SP), 192(SP), X11, X13, X14)
+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, 144(SP), 160(SP), 176(SP), 192(SP), X15, X8, X9)
SHUFFLE_AVX()
- HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, 208(SP), 224(SP), 240(SP), 256(SP), X11, X13, X14)
+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, 208(SP), 224(SP), 240(SP), 256(SP), X15, X8, X9)
SHUFFLE_AVX_INV()
- VMOVDQU 32(AX), X10
- VMOVDQU 48(AX), X11
- VPXOR X0, X12, X12
- VPXOR X1, X15, X15
- VPXOR X2, X10, X10
- VPXOR X3, X11, X11
- VPXOR X4, X12, X12
- VPXOR X5, X15, X15
- VPXOR X6, X10, X2
- VPXOR X7, X11, X3
+ VMOVDQU 32(AX), X14
+ VMOVDQU 48(AX), X15
+ VPXOR X0, X10, X10
+ VPXOR X1, X11, X11
+ VPXOR X2, X14, X14
+ VPXOR X3, X15, X15
+ VPXOR X4, X10, X10
+ VPXOR X5, X11, X11
+ VPXOR X6, X14, X2
+ VPXOR X7, X15, X3
VMOVDQU X2, 32(AX)
VMOVDQU X3, 48(AX)
@@ -478,12 +739,11 @@ noinc:
SUBQ $128, DI
JNE loop
- VMOVDQU X12, 0(AX)
- VMOVDQU X15, 16(AX)
+ VMOVDQU X10, 0(AX)
+ VMOVDQU X11, 16(AX)
MOVQ R8, 0(BX)
MOVQ R9, 8(BX)
-
VZEROUPPER
MOVQ BP, SP
diff --git a/vendor/golang.org/x/crypto/blake2b/blake2b_test.go b/vendor/golang.org/x/crypto/blake2b/blake2b_test.go
index a38fceb..7954346 100644
--- a/vendor/golang.org/x/crypto/blake2b/blake2b_test.go
+++ b/vendor/golang.org/x/crypto/blake2b/blake2b_test.go
@@ -22,7 +22,7 @@ func fromHex(s string) []byte {
func TestHashes(t *testing.T) {
defer func(sse4, avx, avx2 bool) {
- useSSE4, useAVX, useAVX2 = sse4, useAVX, avx2
+ useSSE4, useAVX, useAVX2 = sse4, avx, avx2
}(useSSE4, useAVX, useAVX2)
if useAVX2 {
diff --git a/vendor/golang.org/x/crypto/blake2b/register.go b/vendor/golang.org/x/crypto/blake2b/register.go
new file mode 100644
index 0000000..efd689a
--- /dev/null
+++ b/vendor/golang.org/x/crypto/blake2b/register.go
@@ -0,0 +1,32 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build go1.9
+
+package blake2b
+
+import (
+ "crypto"
+ "hash"
+)
+
+func init() {
+ newHash256 := func() hash.Hash {
+ h, _ := New256(nil)
+ return h
+ }
+ newHash384 := func() hash.Hash {
+ h, _ := New384(nil)
+ return h
+ }
+
+ newHash512 := func() hash.Hash {
+ h, _ := New512(nil)
+ return h
+ }
+
+ crypto.RegisterHash(crypto.BLAKE2b_256, newHash256)
+ crypto.RegisterHash(crypto.BLAKE2b_384, newHash384)
+ crypto.RegisterHash(crypto.BLAKE2b_512, newHash512)
+}
diff --git a/vendor/golang.org/x/crypto/blake2s/blake2s.go b/vendor/golang.org/x/crypto/blake2s/blake2s.go
index 394c121..f2d8221 100644
--- a/vendor/golang.org/x/crypto/blake2s/blake2s.go
+++ b/vendor/golang.org/x/crypto/blake2s/blake2s.go
@@ -4,7 +4,7 @@
// Package blake2s implements the BLAKE2s hash algorithm as
// defined in RFC 7693.
-package blake2s
+package blake2s // import "golang.org/x/crypto/blake2s"
import (
"encoding/binary"
@@ -15,8 +15,12 @@ import (
const (
// The blocksize of BLAKE2s in bytes.
BlockSize = 64
+
// The hash size of BLAKE2s-256 in bytes.
Size = 32
+
+ // The hash size of BLAKE2s-128 in bytes.
+ Size128 = 16
)
var errKeySize = errors.New("blake2s: invalid key size")
@@ -37,6 +41,17 @@ func Sum256(data []byte) [Size]byte {
// key turns the hash into a MAC. The key must between zero and 32 bytes long.
func New256(key []byte) (hash.Hash, error) { return newDigest(Size, key) }
+// New128 returns a new hash.Hash computing the BLAKE2s-128 checksum given a
+// non-empty key. Note that a 128-bit digest is too small to be secure as a
+// cryptographic hash and should only be used as a MAC, thus the key argument
+// is not optional.
+func New128(key []byte) (hash.Hash, error) {
+ if len(key) == 0 {
+ return nil, errors.New("blake2s: a key is required for a 128-bit hash")
+ }
+ return newDigest(Size128, key)
+}
+
func newDigest(hashSize int, key []byte) (*digest, error) {
if len(key) > Size {
return nil, errKeySize
diff --git a/vendor/golang.org/x/crypto/blake2s/blake2s_test.go b/vendor/golang.org/x/crypto/blake2s/blake2s_test.go
index e6f2eeb..ff41670 100644
--- a/vendor/golang.org/x/crypto/blake2s/blake2s_test.go
+++ b/vendor/golang.org/x/crypto/blake2s/blake2s_test.go
@@ -18,21 +18,25 @@ func TestHashes(t *testing.T) {
if useSSE4 {
t.Log("SSE4 version")
testHashes(t)
+ testHashes128(t)
useSSE4 = false
}
if useSSSE3 {
t.Log("SSSE3 version")
testHashes(t)
+ testHashes128(t)
useSSSE3 = false
}
if useSSE2 {
t.Log("SSE2 version")
testHashes(t)
+ testHashes128(t)
useSSE2 = false
}
if useGeneric {
t.Log("generic version")
testHashes(t)
+ testHashes128(t)
}
}
@@ -69,6 +73,39 @@ func testHashes(t *testing.T) {
}
}
+func testHashes128(t *testing.T) {
+ key, _ := hex.DecodeString("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f")
+
+ input := make([]byte, 255)
+ for i := range input {
+ input[i] = byte(i)
+ }
+
+ for i, expectedHex := range hashes128 {
+ h, err := New128(key)
+ if err != nil {
+ t.Fatalf("#%d: error from New128: %v", i, err)
+ }
+
+ h.Write(input[:i])
+ sum := h.Sum(nil)
+
+ if gotHex := fmt.Sprintf("%x", sum); gotHex != expectedHex {
+ t.Fatalf("#%d (single write): got %s, wanted %s", i, gotHex, expectedHex)
+ }
+
+ h.Reset()
+ for j := 0; j < i; j++ {
+ h.Write(input[j : j+1])
+ }
+
+ sum = h.Sum(sum[:0])
+ if gotHex := fmt.Sprintf("%x", sum); gotHex != expectedHex {
+ t.Fatalf("#%d (byte-by-byte): got %s, wanted %s", i, gotHex, expectedHex)
+ }
+ }
+}
+
// Benchmarks
func benchmarkSum(b *testing.B, size int) {
@@ -355,3 +392,262 @@ var hashes = []string{
"db444c15597b5f1a03d1f9edd16e4a9f43a667cc275175dfa2b704e3bb1a9b83",
"3fb735061abc519dfe979e54c1ee5bfad0a9d858b3315bad34bde999efd724dd",
}
+
+var hashes128 = []string{
+ "9536f9b267655743dee97b8a670f9f53",
+ "13bacfb85b48a1223c595f8c1e7e82cb",
+ "d47a9b1645e2feae501cd5fe44ce6333",
+ "1e2a79436a7796a3e9826bfedf07659f",
+ "7640360ed3c4f3054dba79a21dda66b7",
+ "d1207ac2bf5ac84fc9ef016da5a46a86",
+ "3123987871e59305ece3125abfc0099a",
+ "cf9e072ad522f2cda2d825218086731c",
+ "95d22870392efe2846b12b6e8e84efbb",
+ "7d63c30e2d51333f245601b038c0b93b",
+ "ed608b98e13976bdf4bedc63fa35e443",
+ "ed704b5cd1abf8e0dd67a6ac667a3fa5",
+ "77dc70109827dc74c70fd26cba379ae5",
+ "d2bf34508b07825ee934f33958f4560e",
+ "a340baa7b8a93a6e658adef42e78eeb7",
+ "b85c5ceaecbe9a251eac76f6932ba395",
+ "246519722001f6e8e97a2183f5985e53",
+ "5bce5aa0b7c6cac2ecf6406183cd779a",
+ "13408f1647c02f6efd0047ad8344f695",
+ "a63970f196760aa36cb965ab62f0e0fa",
+ "bc26f48421dd99fd45e15e736d3e7dac",
+ "4c6f70f9e3237cde918afb52d26f1823",
+ "45ed610cfbc37db80c4bf0eef14ae8d6",
+ "87c4c150705ea5078209ec008200539c",
+ "54de21f5e0e6f2afe04daeb822b6931e",
+ "9732a04e505064e19de3d542e7e71631",
+ "d2bd27e95531d6957eef511c4ba64ad4",
+ "7a36c9f70dcc7c3063b547101a5f6c35",
+ "322007d1a44c4257bc7903b183305529",
+ "dbcc9a09f412290ca2e0d53dfd142ddb",
+ "df12ed43b8e53a56db20e0f83764002c",
+ "d114cc11e7d5b33a360c45f18d4c7c6e",
+ "c43b5e836af88620a8a71b1652cb8640",
+ "9491c653e8867ed73c1b4ac6b5a9bb4d",
+ "06d0e988df94ada6c6f9f36f588ab7c5",
+ "561efad2480e93262c8eeaa3677615c4",
+ "ba8ffc702e5adc93503045eca8702312",
+ "5782be6ccdc78c8425285e85de8ccdc6",
+ "aa1c4393e4c07b53ea6e2b5b1e970771",
+ "42a229dc50e52271c51e8666023ebc1e",
+ "53706110e919f84de7f8d6c7f0e7b831",
+ "fc5ac8ee39cc1dd1424391323e2901bd",
+ "bed27b62ff66cac2fbb68193c727106a",
+ "cd5e689b96d0b9ea7e08dac36f7b211e",
+ "0b4c7f604eba058d18e322c6e1baf173",
+ "eb838227fdfad09a27f0f8413120675d",
+ "3149cf9d19a7fd529e6154a8b4c3b3ad",
+ "ca1e20126df930fd5fb7afe4422191e5",
+ "b23398f910599f3c09b6549fa81bcb46",
+ "27fb17c11b34fa5d8b5afe5ee3321ead",
+ "0f665f5f04cf2d46b7fead1a1f328158",
+ "8f068be73b3681f99f3b282e3c02bba5",
+ "ba189bbd13808dcf4e002a4dd21660d5",
+ "2732dcd1b16668ae6ab6a61595d0d62a",
+ "d410ccdd059f0e02b472ec9ec54bdd3c",
+ "b2eaa07b055b3a03a399971327f7e8c2",
+ "2e8a225655e9f99b69c60dc8b4d8e566",
+ "4eb55416c853f2152e67f8a224133cec",
+ "49552403790d8de0505a8e317a443687",
+ "7f2747cd41f56942752e868212c7d5ac",
+ "02a28f10e193b430df7112d2d98cf759",
+ "d4213404a9f1cf759017747cf5958270",
+ "faa34884344f9c65e944882db8476d34",
+ "ece382a8bd5018f1de5da44b72cea75b",
+ "f1efa90d2547036841ecd3627fafbc36",
+ "811ff8686d23a435ecbd0bdafcd27b1b",
+ "b21beea9c7385f657a76558530438721",
+ "9cb969da4f1b4fc5b13bf78fe366f0c4",
+ "8850d16d7b614d3268ccfa009d33c7fc",
+ "aa98a2b6176ea86415b9aff3268c6f6d",
+ "ec3e1efa5ed195eff667e16b1af1e39e",
+ "e40787dca57411d2630db2de699beb08",
+ "554835890735babd06318de23d31e78a",
+ "493957feecddc302ee2bb2086b6ebfd3",
+ "f6069709ad5b0139163717e9ce1114ab",
+ "ba5ed386098da284484b211555505a01",
+ "9244c8dfad8cbb68c118fa51465b3ae4",
+ "51e309a5008eb1f5185e5cc007cfb36f",
+ "6ce9ff712121b4f6087955f4911eafd4",
+ "59b51d8dcda031218ccdd7c760828155",
+ "0012878767a3d4f1c8194458cf1f8832",
+ "82900708afd5b6582dc16f008c655edd",
+ "21302c7e39b5a4cdf1d6f86b4f00c9b4",
+ "e894c7431591eab8d1ce0fe2aa1f01df",
+ "b67e1c40ee9d988226d605621854d955",
+ "6237bdafa34137cbbec6be43ea9bd22c",
+ "4172a8e19b0dcb09b978bb9eff7af52b",
+ "5714abb55bd4448a5a6ad09fbd872fdf",
+ "7ce1700bef423e1f958a94a77a94d44a",
+ "3742ec50cded528527775833453e0b26",
+ "5d41b135724c7c9c689495324b162f18",
+ "85c523333c6442c202e9e6e0f1185f93",
+ "5c71f5222d40ff5d90e7570e71ab2d30",
+ "6e18912e83d012efb4c66250ced6f0d9",
+ "4add4448c2e35e0b138a0bac7b4b1775",
+ "c0376c6bc5e7b8b9d2108ec25d2aab53",
+ "f72261d5ed156765c977751c8a13fcc1",
+ "cff4156c48614b6ceed3dd6b9058f17e",
+ "36bfb513f76c15f514bcb593419835aa",
+ "166bf48c6bffaf8291e6fdf63854bef4",
+ "0b67d33f8b859c3157fbabd9e6e47ed0",
+ "e4da659ca76c88e73a9f9f10f3d51789",
+ "33c1ae2a86b3f51c0642e6ed5b5aa1f1",
+ "27469b56aca2334449c1cf4970dcd969",
+ "b7117b2e363378aa0901b0d6a9f6ddc0",
+ "a9578233b09e5cd5231943fdb12cd90d",
+ "486d7d75253598b716a068243c1c3e89",
+ "66f6b02d682b78ffdc85e9ec86852489",
+ "38a07b9a4b228fbcc305476e4d2e05d2",
+ "aedb61c7970e7d05bf9002dae3c6858c",
+ "c03ef441f7dd30fdb61ad2d4d8e4c7da",
+ "7f45cc1eea9a00cb6aeb2dd748361190",
+ "a59538b358459132e55160899e47bd65",
+ "137010fef72364411820c3fbed15c8df",
+ "d8362b93fc504500dbd33ac74e1b4d70",
+ "a7e49f12c8f47e3b29cf8c0889b0a9c8",
+ "072e94ffbfc684bd8ab2a1b9dade2fd5",
+ "5ab438584bd2229e452052e002631a5f",
+ "f233d14221097baef57d3ec205c9e086",
+ "3a95db000c4a8ff98dc5c89631a7f162",
+ "0544f18c2994ab4ddf1728f66041ff16",
+ "0bc02116c60a3cc331928d6c9d3ba37e",
+ "b189dca6cb5b813c74200834fba97f29",
+ "ac8aaab075b4a5bc24419da239212650",
+ "1e9f19323dc71c29ae99c479dc7e8df9",
+ "12d944c3fa7caa1b3d62adfc492274dd",
+ "b4c68f1fffe8f0030e9b18aad8c9dc96",
+ "25887fab1422700d7fa3edc0b20206e2",
+ "8c09f698d03eaf88abf69f8147865ef6",
+ "5c363ae42a5bec26fbc5e996428d9bd7",
+ "7fdfc2e854fbb3928150d5e3abcf56d6",
+ "f0c944023f714df115f9e4f25bcdb89b",
+ "6d19534b4c332741c8ddd79a9644de2d",
+ "32595eb23764fbfc2ee7822649f74a12",
+ "5a51391aab33c8d575019b6e76ae052a",
+ "98b861ce2c620f10f913af5d704a5afd",
+ "b7fe2fc8b77fb1ce434f8465c7ddf793",
+ "0e8406e0cf8e9cc840668ece2a0fc64e",
+ "b89922db99c58f6a128ccffe19b6ce60",
+ "e1be9af665f0932b77d7f5631a511db7",
+ "74b96f20f58de8dc9ff5e31f91828523",
+ "36a4cfef5a2a7d8548db6710e50b3009",
+ "007e95e8d3b91948a1dedb91f75de76b",
+ "a87a702ce08f5745edf765bfcd5fbe0d",
+ "847e69a388a749a9c507354d0dddfe09",
+ "07176eefbc107a78f058f3d424ca6a54",
+ "ad7e80682333b68296f6cb2b4a8e446d",
+ "53c4aba43896ae422e5de5b9edbd46bf",
+ "33bd6c20ca2a7ab916d6e98003c6c5f8",
+ "060d088ea94aa093f9981a79df1dfcc8",
+ "5617b214b9df08d4f11e58f5e76d9a56",
+ "ca3a60ee85bd971e1daf9f7db059d909",
+ "cd2b7754505d8c884eddf736f1ec613e",
+ "f496163b252f1439e7e113ba2ecabd8e",
+ "5719c7dcf9d9f756d6213354acb7d5cf",
+ "6f7dd40b245c54411e7a9be83ae5701c",
+ "c8994dd9fdeb077a45ea04a30358b637",
+ "4b1184f1e35458c1c747817d527a252f",
+ "fc7df674afeac7a3fd994183f4c67a74",
+ "4f68e05ce4dcc533acf9c7c01d95711e",
+ "d4ebc59e918400720035dfc88e0c486a",
+ "d3105dd6fa123e543b0b3a6e0eeaea9e",
+ "874196128ed443f5bdb2800ca048fcad",
+ "01645f134978dc8f9cf0abc93b53780e",
+ "5b8b64caa257873a0ffd47c981ef6c3f",
+ "4ee208fc50ba0a6e65c5b58cec44c923",
+ "53f409a52427b3b7ffabb057ca088428",
+ "c1d6cd616f5341a93d921e356e5887a9",
+ "e85c20fea67fa7320dc23379181183c8",
+ "7912b6409489df001b7372bc94aebde7",
+ "e559f761ec866a87f1f331767fafc60f",
+ "20a6f5a36bc37043d977ed7708465ef8",
+ "6a72f526965ab120826640dd784c6cc4",
+ "bf486d92ad68e87c613689dd370d001b",
+ "d339fd0eb35edf3abd6419c8d857acaf",
+ "9521cd7f32306d969ddabc4e6a617f52",
+ "a1cd9f3e81520842f3cf6cc301cb0021",
+ "18e879b6f154492d593edd3f4554e237",
+ "66e2329c1f5137589e051592587e521e",
+ "e899566dd6c3e82cbc83958e69feb590",
+ "8a4b41d7c47e4e80659d77b4e4bfc9ae",
+ "f1944f6fcfc17803405a1101998c57dd",
+ "f6bcec07567b4f72851b307139656b18",
+ "22e7bb256918fe9924dce9093e2d8a27",
+ "dd25b925815fe7b50b7079f5f65a3970",
+ "0457f10f299acf0c230dd4007612e58f",
+ "ecb420c19efd93814fae2964d69b54af",
+ "14eb47b06dff685d88751c6e32789db4",
+ "e8f072dbb50d1ab6654aa162604a892d",
+ "69cff9c62092332f03a166c7b0034469",
+ "d3619f98970b798ca32c6c14cd25af91",
+ "2246d423774ee9d51a551e89c0539d9e",
+ "75e5d1a1e374a04a699247dad827b6cf",
+ "6d087dd1d4cd15bf47db07c7a96b1db8",
+ "967e4c055ac51b4b2a3e506cebd5826f",
+ "7417aa79247e473401bfa92a25b62e2a",
+ "24f3f4956da34b5c533d9a551ccd7b16",
+ "0c40382de693a5304e2331eb951cc962",
+ "9436f949d51b347db5c8e6258dafaaac",
+ "d2084297fe84c4ba6e04e4fb73d734fe",
+ "42a6f8ff590af21b512e9e088257aa34",
+ "c484ad06b1cdb3a54f3f6464a7a2a6fd",
+ "1b8ac860f5ceb4365400a201ed2917aa",
+ "c43eadabbe7b7473f3f837fc52650f54",
+ "0e5d3205406126b1f838875deb150d6a",
+ "6bf4946f8ec8a9c417f50cd1e67565be",
+ "42f09a2522314799c95b3fc121a0e3e8",
+ "06b8f1487f691a3f7c3f74e133d55870",
+ "1a70a65fb4f314dcf6a31451a9d2704f",
+ "7d4acdd0823279fd28a1e48b49a04669",
+ "09545cc8822a5dfc93bbab708fd69174",
+ "efc063db625013a83c9a426d39a9bddb",
+ "213bbf89b3f5be0ffdb14854bbcb2588",
+ "b69624d89fe2774df9a6f43695d755d4",
+ "c0f9ff9ded82bd73c512e365a894774d",
+ "d1b68507ed89c17ead6f69012982db71",
+ "14cf16db04648978e35c44850855d1b0",
+ "9f254d4eccab74cd91d694df863650a8",
+ "8f8946e2967baa4a814d36ff01d20813",
+ "6b9dc4d24ecba166cb2915d7a6cba43b",
+ "eb35a80418a0042b850e294db7898d4d",
+ "f55f925d280c637d54055c9df088ef5f",
+ "f48427a04f67e33f3ba0a17f7c9704a7",
+ "4a9f5bfcc0321aea2eced896cee65894",
+ "8723a67d1a1df90f1cef96e6fe81e702",
+ "c166c343ee25998f80bad4067960d3fd",
+ "dab67288d16702e676a040fd42344d73",
+ "c8e9e0d80841eb2c116dd14c180e006c",
+ "92294f546bacf0dea9042c93ecba8b34",
+ "013705b1502b37369ad22fe8237d444e",
+ "9b97f8837d5f2ebab0768fc9a6446b93",
+ "7e7e5236b05ec35f89edf8bf655498e7",
+ "7be8f2362c174c776fb9432fe93bf259",
+ "2422e80420276d2df5702c6470879b01",
+ "df645795db778bcce23bbe819a76ba48",
+ "3f97a4ac87dfc58761cda1782d749074",
+ "50e3f45df21ebfa1b706b9c0a1c245a8",
+ "7879541c7ff612c7ddf17cb8f7260183",
+ "67f6542b903b7ba1945eba1a85ee6b1c",
+ "b34b73d36ab6234b8d3f5494d251138e",
+ "0aea139641fdba59ab1103479a96e05f",
+ "02776815a87b8ba878453666d42afe3c",
+ "5929ab0a90459ebac5a16e2fb37c847e",
+ "c244def5b20ce0468f2b5012d04ac7fd",
+ "12116add6fefce36ed8a0aeccce9b6d3",
+ "3cd743841e9d8b878f34d91b793b4fad",
+ "45e87510cf5705262185f46905fae35f",
+ "276047016b0bfb501b2d4fc748165793",
+ "ddd245df5a799417d350bd7f4e0b0b7e",
+ "d34d917a54a2983f3fdbc4b14caae382",
+ "7730fbc09d0c1fb1939a8fc436f6b995",
+ "eb4899ef257a1711cc9270a19702e5b5",
+ "8a30932014bce35bba620895d374df7a",
+ "1924aabf9c50aa00bee5e1f95b5d9e12",
+ "1758d6f8b982aec9fbe50f20e3082b46",
+ "cd075928ab7e6883e697fe7fd3ac43ee",
+}
diff --git a/vendor/golang.org/x/crypto/blake2s/register.go b/vendor/golang.org/x/crypto/blake2s/register.go
new file mode 100644
index 0000000..d277459
--- /dev/null
+++ b/vendor/golang.org/x/crypto/blake2s/register.go
@@ -0,0 +1,21 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build go1.9
+
+package blake2s
+
+import (
+ "crypto"
+ "hash"
+)
+
+func init() {
+ newHash256 := func() hash.Hash {
+ h, _ := New256(nil)
+ return h
+ }
+
+ crypto.RegisterHash(crypto.BLAKE2s_256, newHash256)
+}
diff --git a/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305.go b/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305.go
index eb6739a..3f0dcb9 100644
--- a/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305.go
+++ b/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305.go
@@ -3,7 +3,7 @@
// license that can be found in the LICENSE file.
// Package chacha20poly1305 implements the ChaCha20-Poly1305 AEAD as specified in RFC 7539.
-package chacha20poly1305
+package chacha20poly1305 // import "golang.org/x/crypto/chacha20poly1305"
import (
"crypto/cipher"
diff --git a/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.go b/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.go
index 4755033..7cd7ad8 100644
--- a/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.go
+++ b/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.go
@@ -14,13 +14,60 @@ func chacha20Poly1305Open(dst []byte, key []uint32, src, ad []byte) bool
//go:noescape
func chacha20Poly1305Seal(dst []byte, key []uint32, src, ad []byte)
-//go:noescape
-func haveSSSE3() bool
+// cpuid is implemented in chacha20poly1305_amd64.s.
+func cpuid(eaxArg, ecxArg uint32) (eax, ebx, ecx, edx uint32)
-var canUseASM bool
+// xgetbv with ecx = 0 is implemented in chacha20poly1305_amd64.s.
+func xgetbv() (eax, edx uint32)
+
+var (
+ useASM bool
+ useAVX2 bool
+)
func init() {
- canUseASM = haveSSSE3()
+ detectCPUFeatures()
+}
+
+// detectCPUFeatures is used to detect if cpu instructions
+// used by the functions implemented in assembler in
+// chacha20poly1305_amd64.s are supported.
+func detectCPUFeatures() {
+ maxID, _, _, _ := cpuid(0, 0)
+ if maxID < 1 {
+ return
+ }
+
+ _, _, ecx1, _ := cpuid(1, 0)
+
+ haveSSSE3 := isSet(9, ecx1)
+ useASM = haveSSSE3
+
+ haveOSXSAVE := isSet(27, ecx1)
+
+ osSupportsAVX := false
+ // For XGETBV, OSXSAVE bit is required and sufficient.
+ if haveOSXSAVE {
+ eax, _ := xgetbv()
+ // Check if XMM and YMM registers have OS support.
+ osSupportsAVX = isSet(1, eax) && isSet(2, eax)
+ }
+ haveAVX := isSet(28, ecx1) && osSupportsAVX
+
+ if maxID < 7 {
+ return
+ }
+
+ _, ebx7, _, _ := cpuid(7, 0)
+ haveAVX2 := isSet(5, ebx7) && haveAVX
+ haveBMI2 := isSet(8, ebx7)
+
+ useAVX2 = haveAVX2 && haveBMI2
+}
+
+// isSet checks if bit at bitpos is set in value.
+func isSet(bitpos uint, value uint32) bool {
+ return value&(1<= 0x80 || i < -0x80; i >>= 8 {
+ length++
+ }
+
+ for ; length > 0; length-- {
+ i := v >> uint((length-1)*8) & 0xff
+ c.AddUint8(uint8(i))
+ }
+ })
+}
+
+// AddASN1Uint64 appends a DER-encoded ASN.1 INTEGER.
+func (b *Builder) AddASN1Uint64(v uint64) {
+ b.AddASN1(asn1.TagInteger, func(c *Builder) {
+ length := 1
+ for i := v; i >= 0x80; i >>= 8 {
+ length++
+ }
+
+ for ; length > 0; length-- {
+ i := v >> uint((length-1)*8) & 0xff
+ c.AddUint8(uint8(i))
+ }
+ })
+}
+
+// AddASN1BigInt appends a DER-encoded ASN.1 INTEGER.
+func (b *Builder) AddASN1BigInt(n *big.Int) {
+ if b.err != nil {
+ return
+ }
+
+ b.AddASN1(asn1.TagInteger, func(c *Builder) {
+ if n.Sign() < 0 {
+ // A negative number has to be converted to two's-complement form. So we
+ // invert and subtract 1. If the most-significant-bit isn't set then
+ // we'll need to pad the beginning with 0xff in order to keep the number
+ // negative.
+ nMinus1 := new(big.Int).Neg(n)
+ nMinus1.Sub(nMinus1, bigOne)
+ bytes := nMinus1.Bytes()
+ for i := range bytes {
+ bytes[i] ^= 0xff
+ }
+ if bytes[0]&0x80 == 0 {
+ c.add(0xff)
+ }
+ c.add(bytes...)
+ } else if n.Sign() == 0 {
+ c.add(0)
+ } else {
+ bytes := n.Bytes()
+ if bytes[0]&0x80 != 0 {
+ c.add(0)
+ }
+ c.add(bytes...)
+ }
+ })
+}
+
+// AddASN1OctetString appends a DER-encoded ASN.1 OCTET STRING.
+func (b *Builder) AddASN1OctetString(bytes []byte) {
+ b.AddASN1(asn1.TagOctetString, func(c *Builder) {
+ c.AddBytes(bytes)
+ })
+}
+
+const generalizedTimeFormatStr = "20060102150405Z0700"
+
+// AddASN1GeneralizedTime appends a DER-encoded ASN.1 GENERALIZEDTIME.
+func (b *Builder) AddASN1GeneralizedTime(t time.Time) {
+ if t.Year() < 0 || t.Year() > 9999 {
+ b.err = fmt.Errorf("cryptobyte: cannot represent %v as a GeneralizedTime", t)
+ return
+ }
+ b.AddASN1(asn1.TagGeneralizedTime, func(c *Builder) {
+ c.AddBytes([]byte(t.Format(generalizedTimeFormatStr)))
+ })
+}
+
+// AddASN1BitString appends a DER-encoded ASN.1 BIT STRING.
+func (b *Builder) AddASN1BitString(s asn1.BitString) {
+ // TODO(martinkr): Implement.
+ b.MarshalASN1(s)
+}
+
+// MarshalASN1 calls asn1.Marshal on its input and appends the result if
+// successful or records an error if one occurred.
+func (b *Builder) MarshalASN1(v interface{}) {
+ // NOTE(martinkr): This is somewhat of a hack to allow propagation of
+ // asn1.Marshal errors into Builder.err. N.B. if you call MarshalASN1 with a
+ // value embedded into a struct, its tag information is lost.
+ if b.err != nil {
+ return
+ }
+ bytes, err := asn1.Marshal(v)
+ if err != nil {
+ b.err = err
+ return
+ }
+ b.AddBytes(bytes)
+}
+
+// AddASN1 appends an ASN.1 object. The object is prefixed with the given tag.
+// Tags greater than 30 are not supported and result in an error (i.e.
+// low-tag-number form only). The child builder passed to the
+// BuilderContinuation can be used to build the content of the ASN.1 object.
+func (b *Builder) AddASN1(tag Tag, f BuilderContinuation) {
+ if b.err != nil {
+ return
+ }
+ // Identifiers with the low five bits set indicate high-tag-number format
+ // (two or more octets), which we don't support.
+ if tag&0x1f == 0x1f {
+ b.err = fmt.Errorf("cryptobyte: high-tag number identifier octects not supported: 0x%x", tag)
+ return
+ }
+ b.AddUint8(uint8(tag))
+ b.addLengthPrefixed(1, true, f)
+}
+
+// String
+
+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.
+func (s *String) ReadASN1Integer(out interface{}) bool {
+ if reflect.TypeOf(out).Kind() != reflect.Ptr {
+ panic("out is not a pointer")
+ }
+ switch reflect.ValueOf(out).Elem().Kind() {
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ var i int64
+ if !s.readASN1Int64(&i) || reflect.ValueOf(out).Elem().OverflowInt(i) {
+ return false
+ }
+ reflect.ValueOf(out).Elem().SetInt(i)
+ return true
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
+ var u uint64
+ if !s.readASN1Uint64(&u) || reflect.ValueOf(out).Elem().OverflowUint(u) {
+ return false
+ }
+ reflect.ValueOf(out).Elem().SetUint(u)
+ return true
+ case reflect.Struct:
+ if reflect.TypeOf(out).Elem() == bigIntType {
+ return s.readASN1BigInt(out.(*big.Int))
+ }
+ }
+ panic("out does not point to an integer type")
+}
+
+func checkASN1Integer(bytes []byte) bool {
+ if len(bytes) == 0 {
+ // An INTEGER is encoded with at least one octet.
+ return false
+ }
+ if len(bytes) == 1 {
+ return true
+ }
+ if bytes[0] == 0 && bytes[1]&0x80 == 0 || bytes[0] == 0xff && bytes[1]&0x80 == 0x80 {
+ // Value is not minimally encoded.
+ return false
+ }
+ return true
+}
+
+var bigOne = big.NewInt(1)
+
+func (s *String) readASN1BigInt(out *big.Int) bool {
+ var bytes String
+ if !s.ReadASN1(&bytes, asn1.TagInteger) || !checkASN1Integer(bytes) {
+ return false
+ }
+ if bytes[0]&0x80 == 0x80 {
+ // Negative number.
+ neg := make([]byte, len(bytes))
+ for i, b := range bytes {
+ neg[i] = ^b
+ }
+ out.SetBytes(neg)
+ out.Add(out, bigOne)
+ out.Neg(out)
+ } else {
+ out.SetBytes(bytes)
+ }
+ return true
+}
+
+func (s *String) readASN1Int64(out *int64) bool {
+ var bytes String
+ if !s.ReadASN1(&bytes, asn1.TagInteger) || !checkASN1Integer(bytes) || !asn1Signed(out, bytes) {
+ return false
+ }
+ return true
+}
+
+func asn1Signed(out *int64, n []byte) bool {
+ length := len(n)
+ if length > 8 {
+ return false
+ }
+ for i := 0; i < length; i++ {
+ *out <<= 8
+ *out |= int64(n[i])
+ }
+ // Shift up and down in order to sign extend the result.
+ *out <<= 64 - uint8(length)*8
+ *out >>= 64 - uint8(length)*8
+ return true
+}
+
+func (s *String) readASN1Uint64(out *uint64) bool {
+ var bytes String
+ if !s.ReadASN1(&bytes, asn1.TagInteger) || !checkASN1Integer(bytes) || !asn1Unsigned(out, bytes) {
+ return false
+ }
+ return true
+}
+
+func asn1Unsigned(out *uint64, n []byte) bool {
+ length := len(n)
+ if length > 9 || length == 9 && n[0] != 0 {
+ // Too large for uint64.
+ return false
+ }
+ if n[0]&0x80 != 0 {
+ // Negative number.
+ return false
+ }
+ for i := 0; i < length; i++ {
+ *out <<= 8
+ *out |= uint64(n[i])
+ }
+ return true
+}
+
+// ReadASN1Enum decodes an ASN.1 ENUMERATION into out and advances. It returns
+// true on success and false on error.
+func (s *String) ReadASN1Enum(out *int) bool {
+ var bytes String
+ var i int64
+ if !s.ReadASN1(&bytes, asn1.TagEnum) || !checkASN1Integer(bytes) || !asn1Signed(&i, bytes) {
+ return false
+ }
+ if int64(int(i)) != i {
+ return false
+ }
+ *out = int(i)
+ return true
+}
+
+func (s *String) readBase128Int(out *int) bool {
+ ret := 0
+ for i := 0; len(*s) > 0; i++ {
+ if i == 4 {
+ return false
+ }
+ ret <<= 7
+ b := s.read(1)[0]
+ ret |= int(b & 0x7f)
+ if b&0x80 == 0 {
+ *out = ret
+ return true
+ }
+ }
+ return false // truncated
+}
+
+// ReadASN1ObjectIdentifier decodes an ASN.1 OBJECT IDENTIFIER into out and
+// advances. It returns true on success and false on error.
+func (s *String) ReadASN1ObjectIdentifier(out *asn1.ObjectIdentifier) bool {
+ var bytes String
+ if !s.ReadASN1(&bytes, asn1.TagOID) || len(bytes) == 0 {
+ return false
+ }
+
+ // In the worst case, we get two elements from the first byte (which is
+ // encoded differently) and then every varint is a single byte long.
+ components := make([]int, len(bytes)+1)
+
+ // The first varint is 40*value1 + value2:
+ // According to this packing, value1 can take the values 0, 1 and 2 only.
+ // When value1 = 0 or value1 = 1, then value2 is <= 39. When value1 = 2,
+ // then there are no restrictions on value2.
+ var v int
+ if !bytes.readBase128Int(&v) {
+ return false
+ }
+ if v < 80 {
+ components[0] = v / 40
+ components[1] = v % 40
+ } else {
+ components[0] = 2
+ components[1] = v - 80
+ }
+
+ i := 2
+ for ; len(bytes) > 0; i++ {
+ if !bytes.readBase128Int(&v) {
+ return false
+ }
+ components[i] = v
+ }
+ *out = components[:i]
+ return true
+}
+
+// ReadASN1GeneralizedTime decodes an ASN.1 GENERALIZEDTIME into out and
+// advances. It returns true on success and false on error.
+func (s *String) ReadASN1GeneralizedTime(out *time.Time) bool {
+ var bytes String
+ if !s.ReadASN1(&bytes, asn1.TagGeneralizedTime) {
+ return false
+ }
+ t := string(bytes)
+ res, err := time.Parse(generalizedTimeFormatStr, t)
+ if err != nil {
+ return false
+ }
+ if serialized := res.Format(generalizedTimeFormatStr); serialized != t {
+ return false
+ }
+ *out = res
+ return true
+}
+
+// ReadASN1BitString decodes an ASN.1 BIT STRING into out and advances. It
+// returns true on success and false on error.
+func (s *String) ReadASN1BitString(out *asn1.BitString) bool {
+ var bytes String
+ if !s.ReadASN1(&bytes, asn1.TagBitString) || len(bytes) == 0 {
+ return false
+ }
+
+ paddingBits := uint8(bytes[0])
+ bytes = bytes[1:]
+ if paddingBits > 7 ||
+ len(bytes) == 0 && paddingBits != 0 ||
+ len(bytes) > 0 && bytes[len(bytes)-1]&(1< 4 || len(*s) < int(2+lenLen) {
+ return false
+ }
+
+ lenBytes := String((*s)[2 : 2+lenLen])
+ if !lenBytes.readUnsigned(&len32, int(lenLen)) {
+ return false
+ }
+
+ // ITU-T X.690 section 10.1 (DER length forms) requires encoding the length
+ // with the minimum number of octets.
+ if len32 < 128 {
+ // Length should have used short-form encoding.
+ return false
+ }
+ if len32>>((lenLen-1)*8) == 0 {
+ // Leading octet is 0. Length should have been at least one byte shorter.
+ return false
+ }
+
+ headerLen = 2 + uint32(lenLen)
+ if headerLen+len32 < len32 {
+ // Overflow.
+ return false
+ }
+ length = headerLen + len32
+ }
+
+ if uint32(int(length)) != length || !s.ReadBytes((*[]byte)(out), int(length)) {
+ return false
+ }
+ if skipHeader && !out.Skip(int(headerLen)) {
+ panic("cryptobyte: internal error")
+ }
+
+ return true
+}
diff --git a/vendor/golang.org/x/crypto/cryptobyte/asn1_test.go b/vendor/golang.org/x/crypto/cryptobyte/asn1_test.go
new file mode 100644
index 0000000..c8c1870
--- /dev/null
+++ b/vendor/golang.org/x/crypto/cryptobyte/asn1_test.go
@@ -0,0 +1,285 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package cryptobyte
+
+import (
+ "bytes"
+ "encoding/asn1"
+ "math/big"
+ "reflect"
+ "testing"
+ "time"
+)
+
+type readASN1Test struct {
+ name string
+ in []byte
+ tag Tag
+ ok bool
+ out interface{}
+}
+
+var readASN1TestData = []readASN1Test{
+ {"valid", []byte{0x30, 2, 1, 2}, 0x30, true, []byte{1, 2}},
+ {"truncated", []byte{0x30, 3, 1, 2}, 0x30, false, nil},
+ {"zero length of length", []byte{0x30, 0x80}, 0x30, false, nil},
+ {"invalid long form length", []byte{0x30, 0x81, 1, 1}, 0x30, false, nil},
+ {"non-minimal length", append([]byte{0x30, 0x82, 0, 0x80}, make([]byte, 0x80)...), 0x30, false, nil},
+ {"invalid tag", []byte{0xa1, 3, 0x4, 1, 1}, 31, false, nil},
+ {"high tag", []byte{0x1f, 0x81, 0x80, 0x01, 2, 1, 2}, 0xff /* actually 0x4001, but tag is uint8 */, false, nil},
+}
+
+func TestReadASN1(t *testing.T) {
+ for _, test := range readASN1TestData {
+ t.Run(test.name, func(t *testing.T) {
+ var in, out String = test.in, nil
+ ok := in.ReadASN1(&out, test.tag)
+ if ok != test.ok || ok && !bytes.Equal(out, test.out.([]byte)) {
+ t.Errorf("in.ReadASN1() = %v, want %v; out = %v, want %v", ok, test.ok, out, test.out)
+ }
+ })
+ }
+}
+
+func TestReadASN1Optional(t *testing.T) {
+ var empty String
+ var present bool
+ ok := empty.ReadOptionalASN1(nil, &present, 0xa0)
+ if !ok || present {
+ t.Errorf("empty.ReadOptionalASN1() = %v, want true; present = %v want false", ok, present)
+ }
+
+ var in, out String = []byte{0xa1, 3, 0x4, 1, 1}, nil
+ ok = in.ReadOptionalASN1(&out, &present, 0xa0)
+ if !ok || present {
+ t.Errorf("in.ReadOptionalASN1() = %v, want true, present = %v, want false", ok, present)
+ }
+ ok = in.ReadOptionalASN1(&out, &present, 0xa1)
+ wantBytes := []byte{4, 1, 1}
+ if !ok || !present || !bytes.Equal(out, wantBytes) {
+ t.Errorf("in.ReadOptionalASN1() = %v, want true; present = %v, want true; out = %v, want = %v", ok, present, out, wantBytes)
+ }
+}
+
+var optionalOctetStringTestData = []struct {
+ readASN1Test
+ present bool
+}{
+ {readASN1Test{"empty", []byte{}, 0xa0, true, []byte{}}, false},
+ {readASN1Test{"invalid", []byte{0xa1, 3, 0x4, 2, 1}, 0xa1, false, []byte{}}, true},
+ {readASN1Test{"missing", []byte{0xa1, 3, 0x4, 1, 1}, 0xa0, true, []byte{}}, false},
+ {readASN1Test{"present", []byte{0xa1, 3, 0x4, 1, 1}, 0xa1, true, []byte{1}}, true},
+}
+
+func TestReadASN1OptionalOctetString(t *testing.T) {
+ for _, test := range optionalOctetStringTestData {
+ t.Run(test.name, func(t *testing.T) {
+ in := String(test.in)
+ var out []byte
+ var present bool
+ ok := in.ReadOptionalASN1OctetString(&out, &present, test.tag)
+ if ok != test.ok || present != test.present || !bytes.Equal(out, test.out.([]byte)) {
+ t.Errorf("in.ReadOptionalASN1OctetString() = %v, want %v; present = %v want %v; out = %v, want %v", ok, test.ok, present, test.present, out, test.out)
+ }
+ })
+ }
+}
+
+const defaultInt = -1
+
+var optionalIntTestData = []readASN1Test{
+ {"empty", []byte{}, 0xa0, true, defaultInt},
+ {"invalid", []byte{0xa1, 3, 0x2, 2, 127}, 0xa1, false, 0},
+ {"missing", []byte{0xa1, 3, 0x2, 1, 127}, 0xa0, true, defaultInt},
+ {"present", []byte{0xa1, 3, 0x2, 1, 42}, 0xa1, true, 42},
+}
+
+func TestReadASN1OptionalInteger(t *testing.T) {
+ for _, test := range optionalIntTestData {
+ t.Run(test.name, func(t *testing.T) {
+ in := String(test.in)
+ var out int
+ ok := in.ReadOptionalASN1Integer(&out, test.tag, defaultInt)
+ if ok != test.ok || ok && out != test.out.(int) {
+ t.Errorf("in.ReadOptionalASN1Integer() = %v, want %v; out = %v, want %v", ok, test.ok, out, test.out)
+ }
+ })
+ }
+}
+
+func TestReadASN1IntegerSigned(t *testing.T) {
+ testData64 := []struct {
+ in []byte
+ out int64
+ }{
+ {[]byte{2, 3, 128, 0, 0}, -0x800000},
+ {[]byte{2, 2, 255, 0}, -256},
+ {[]byte{2, 2, 255, 127}, -129},
+ {[]byte{2, 1, 128}, -128},
+ {[]byte{2, 1, 255}, -1},
+ {[]byte{2, 1, 0}, 0},
+ {[]byte{2, 1, 1}, 1},
+ {[]byte{2, 1, 2}, 2},
+ {[]byte{2, 1, 127}, 127},
+ {[]byte{2, 2, 0, 128}, 128},
+ {[]byte{2, 2, 1, 0}, 256},
+ {[]byte{2, 4, 0, 128, 0, 0}, 0x800000},
+ }
+ for i, test := range testData64 {
+ in := String(test.in)
+ var out int64
+ ok := in.ReadASN1Integer(&out)
+ if !ok || out != test.out {
+ t.Errorf("#%d: in.ReadASN1Integer() = %v, want true; out = %d, want %d", i, ok, out, test.out)
+ }
+ }
+
+ // Repeat the same cases, reading into a big.Int.
+ t.Run("big.Int", func(t *testing.T) {
+ for i, test := range testData64 {
+ in := String(test.in)
+ var out big.Int
+ ok := in.ReadASN1Integer(&out)
+ if !ok || out.Int64() != test.out {
+ t.Errorf("#%d: in.ReadASN1Integer() = %v, want true; out = %d, want %d", i, ok, out.Int64(), test.out)
+ }
+ }
+ })
+}
+
+func TestReadASN1IntegerUnsigned(t *testing.T) {
+ testData := []struct {
+ in []byte
+ out uint64
+ }{
+ {[]byte{2, 1, 0}, 0},
+ {[]byte{2, 1, 1}, 1},
+ {[]byte{2, 1, 2}, 2},
+ {[]byte{2, 1, 127}, 127},
+ {[]byte{2, 2, 0, 128}, 128},
+ {[]byte{2, 2, 1, 0}, 256},
+ {[]byte{2, 4, 0, 128, 0, 0}, 0x800000},
+ {[]byte{2, 8, 127, 255, 255, 255, 255, 255, 255, 255}, 0x7fffffffffffffff},
+ {[]byte{2, 9, 0, 128, 0, 0, 0, 0, 0, 0, 0}, 0x8000000000000000},
+ {[]byte{2, 9, 0, 255, 255, 255, 255, 255, 255, 255, 255}, 0xffffffffffffffff},
+ }
+ for i, test := range testData {
+ in := String(test.in)
+ var out uint64
+ ok := in.ReadASN1Integer(&out)
+ if !ok || out != test.out {
+ t.Errorf("#%d: in.ReadASN1Integer() = %v, want true; out = %d, want %d", i, ok, out, test.out)
+ }
+ }
+}
+
+func TestReadASN1IntegerInvalid(t *testing.T) {
+ testData := []String{
+ []byte{3, 1, 0}, // invalid tag
+ // truncated
+ []byte{2, 1},
+ []byte{2, 2, 0},
+ // not minimally encoded
+ []byte{2, 2, 0, 1},
+ []byte{2, 2, 0xff, 0xff},
+ }
+
+ for i, test := range testData {
+ var out int64
+ if test.ReadASN1Integer(&out) {
+ t.Errorf("#%d: in.ReadASN1Integer() = true, want false (out = %d)", i, out)
+ }
+ }
+}
+
+func TestReadASN1ObjectIdentifier(t *testing.T) {
+ testData := []struct {
+ in []byte
+ ok bool
+ out []int
+ }{
+ {[]byte{}, false, []int{}},
+ {[]byte{6, 0}, false, []int{}},
+ {[]byte{5, 1, 85}, false, []int{2, 5}},
+ {[]byte{6, 1, 85}, true, []int{2, 5}},
+ {[]byte{6, 2, 85, 0x02}, true, []int{2, 5, 2}},
+ {[]byte{6, 4, 85, 0x02, 0xc0, 0x00}, true, []int{2, 5, 2, 0x2000}},
+ {[]byte{6, 3, 0x81, 0x34, 0x03}, true, []int{2, 100, 3}},
+ {[]byte{6, 7, 85, 0x02, 0xc0, 0x80, 0x80, 0x80, 0x80}, false, []int{}},
+ }
+
+ for i, test := range testData {
+ in := String(test.in)
+ var out asn1.ObjectIdentifier
+ ok := in.ReadASN1ObjectIdentifier(&out)
+ if ok != test.ok || ok && !out.Equal(test.out) {
+ t.Errorf("#%d: in.ReadASN1ObjectIdentifier() = %v, want %v; out = %v, want %v", i, ok, test.ok, out, test.out)
+ }
+ }
+}
+
+func TestReadASN1GeneralizedTime(t *testing.T) {
+ testData := []struct {
+ in string
+ ok bool
+ out time.Time
+ }{
+ {"20100102030405Z", true, time.Date(2010, 01, 02, 03, 04, 05, 0, time.UTC)},
+ {"20100102030405", false, time.Time{}},
+ {"20100102030405+0607", true, time.Date(2010, 01, 02, 03, 04, 05, 0, time.FixedZone("", 6*60*60+7*60))},
+ {"20100102030405-0607", true, time.Date(2010, 01, 02, 03, 04, 05, 0, time.FixedZone("", -6*60*60-7*60))},
+ /* These are invalid times. However, the time package normalises times
+ * and they were accepted in some versions. See #11134. */
+ {"00000100000000Z", false, time.Time{}},
+ {"20101302030405Z", false, time.Time{}},
+ {"20100002030405Z", false, time.Time{}},
+ {"20100100030405Z", false, time.Time{}},
+ {"20100132030405Z", false, time.Time{}},
+ {"20100231030405Z", false, time.Time{}},
+ {"20100102240405Z", false, time.Time{}},
+ {"20100102036005Z", false, time.Time{}},
+ {"20100102030460Z", false, time.Time{}},
+ {"-20100102030410Z", false, time.Time{}},
+ {"2010-0102030410Z", false, time.Time{}},
+ {"2010-0002030410Z", false, time.Time{}},
+ {"201001-02030410Z", false, time.Time{}},
+ {"20100102-030410Z", false, time.Time{}},
+ {"2010010203-0410Z", false, time.Time{}},
+ {"201001020304-10Z", false, time.Time{}},
+ }
+ for i, test := range testData {
+ in := String(append([]byte{asn1.TagGeneralizedTime, byte(len(test.in))}, test.in...))
+ var out time.Time
+ ok := in.ReadASN1GeneralizedTime(&out)
+ if ok != test.ok || ok && !reflect.DeepEqual(out, test.out) {
+ t.Errorf("#%d: in.ReadASN1GeneralizedTime() = %v, want %v; out = %q, want %q", i, ok, test.ok, out, test.out)
+ }
+ }
+}
+
+func TestReadASN1BitString(t *testing.T) {
+ testData := []struct {
+ in []byte
+ ok bool
+ out asn1.BitString
+ }{
+ {[]byte{}, false, asn1.BitString{}},
+ {[]byte{0x00}, true, asn1.BitString{}},
+ {[]byte{0x07, 0x00}, true, asn1.BitString{Bytes: []byte{0}, BitLength: 1}},
+ {[]byte{0x07, 0x01}, false, asn1.BitString{}},
+ {[]byte{0x07, 0x40}, false, asn1.BitString{}},
+ {[]byte{0x08, 0x00}, false, asn1.BitString{}},
+ {[]byte{0xff}, false, asn1.BitString{}},
+ {[]byte{0xfe, 0x00}, false, asn1.BitString{}},
+ }
+ for i, test := range testData {
+ in := String(append([]byte{3, byte(len(test.in))}, test.in...))
+ var out asn1.BitString
+ ok := in.ReadASN1BitString(&out)
+ if ok != test.ok || ok && (!bytes.Equal(out.Bytes, test.out.Bytes) || out.BitLength != test.out.BitLength) {
+ t.Errorf("#%d: in.ReadASN1BitString() = %v, want %v; out = %v, want %v", i, ok, test.ok, out, test.out)
+ }
+ }
+}
diff --git a/vendor/golang.org/x/crypto/cryptobyte/builder.go b/vendor/golang.org/x/crypto/cryptobyte/builder.go
new file mode 100644
index 0000000..9883fb3
--- /dev/null
+++ b/vendor/golang.org/x/crypto/cryptobyte/builder.go
@@ -0,0 +1,255 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package cryptobyte
+
+import (
+ "errors"
+ "fmt"
+)
+
+// A Builder builds byte strings from fixed-length and length-prefixed values.
+// The zero value is a usable Builder that allocates space as needed.
+type Builder struct {
+ err error
+ result []byte
+ fixedSize bool
+ child *Builder
+ offset int
+ pendingLenLen int
+ pendingIsASN1 bool
+}
+
+// NewBuilder creates a Builder that appends its output to the given buffer.
+// Like append(), the slice will be reallocated if its capacity is exceeded.
+// Use Bytes to get the final buffer.
+func NewBuilder(buffer []byte) *Builder {
+ return &Builder{
+ result: buffer,
+ }
+}
+
+// NewFixedBuilder creates a Builder that appends its output into the given
+// buffer. This builder does not reallocate the output buffer. Writes that
+// would exceed the buffer's capacity are treated as an error.
+func NewFixedBuilder(buffer []byte) *Builder {
+ return &Builder{
+ result: buffer,
+ fixedSize: true,
+ }
+}
+
+// Bytes returns the bytes written by the builder or an error if one has
+// occurred during during building.
+func (b *Builder) Bytes() ([]byte, error) {
+ if b.err != nil {
+ return nil, b.err
+ }
+ return b.result[b.offset:], nil
+}
+
+// BytesOrPanic returns the bytes written by the builder or panics if an error
+// has occurred during building.
+func (b *Builder) BytesOrPanic() []byte {
+ if b.err != nil {
+ panic(b.err)
+ }
+ return b.result[b.offset:]
+}
+
+// AddUint8 appends an 8-bit value to the byte string.
+func (b *Builder) AddUint8(v uint8) {
+ b.add(byte(v))
+}
+
+// AddUint16 appends a big-endian, 16-bit value to the byte string.
+func (b *Builder) AddUint16(v uint16) {
+ b.add(byte(v>>8), byte(v))
+}
+
+// AddUint24 appends a big-endian, 24-bit value to the byte string. The highest
+// byte of the 32-bit input value is silently truncated.
+func (b *Builder) AddUint24(v uint32) {
+ b.add(byte(v>>16), byte(v>>8), byte(v))
+}
+
+// AddUint32 appends a big-endian, 32-bit value to the byte string.
+func (b *Builder) AddUint32(v uint32) {
+ b.add(byte(v>>24), byte(v>>16), byte(v>>8), byte(v))
+}
+
+// AddBytes appends a sequence of bytes to the byte string.
+func (b *Builder) AddBytes(v []byte) {
+ b.add(v...)
+}
+
+// BuilderContinuation is continuation-passing interface for building
+// length-prefixed byte sequences. Builder methods for length-prefixed
+// sequences (AddUint8LengthPrefixed etc.) will invoke the BuilderContinuation
+// supplied to them. The child builder passed to the continuation can be used
+// to build the content of the length-prefixed sequence. Example:
+//
+// parent := cryptobyte.NewBuilder()
+// parent.AddUint8LengthPrefixed(func (child *Builder) {
+// child.AddUint8(42)
+// child.AddUint8LengthPrefixed(func (grandchild *Builder) {
+// grandchild.AddUint8(5)
+// })
+// })
+//
+// It is an error to write more bytes to the child than allowed by the reserved
+// length prefix. After the continuation returns, the child must be considered
+// invalid, i.e. users must not store any copies or references of the child
+// that outlive the continuation.
+type BuilderContinuation func(child *Builder)
+
+// AddUint8LengthPrefixed adds a 8-bit length-prefixed byte sequence.
+func (b *Builder) AddUint8LengthPrefixed(f BuilderContinuation) {
+ b.addLengthPrefixed(1, false, f)
+}
+
+// AddUint16LengthPrefixed adds a big-endian, 16-bit length-prefixed byte sequence.
+func (b *Builder) AddUint16LengthPrefixed(f BuilderContinuation) {
+ b.addLengthPrefixed(2, false, f)
+}
+
+// AddUint24LengthPrefixed adds a big-endian, 24-bit length-prefixed byte sequence.
+func (b *Builder) AddUint24LengthPrefixed(f BuilderContinuation) {
+ b.addLengthPrefixed(3, false, f)
+}
+
+func (b *Builder) addLengthPrefixed(lenLen int, isASN1 bool, f BuilderContinuation) {
+ // Subsequent writes can be ignored if the builder has encountered an error.
+ if b.err != nil {
+ return
+ }
+
+ offset := len(b.result)
+ b.add(make([]byte, lenLen)...)
+
+ b.child = &Builder{
+ result: b.result,
+ fixedSize: b.fixedSize,
+ offset: offset,
+ pendingLenLen: lenLen,
+ pendingIsASN1: isASN1,
+ }
+
+ f(b.child)
+ b.flushChild()
+ if b.child != nil {
+ panic("cryptobyte: internal error")
+ }
+}
+
+func (b *Builder) flushChild() {
+ if b.child == nil {
+ return
+ }
+ b.child.flushChild()
+ child := b.child
+ b.child = nil
+
+ if child.err != nil {
+ b.err = child.err
+ return
+ }
+
+ length := len(child.result) - child.pendingLenLen - child.offset
+
+ if length < 0 {
+ panic("cryptobyte: internal error") // result unexpectedly shrunk
+ }
+
+ if child.pendingIsASN1 {
+ // For ASN.1, we reserved a single byte for the length. If that turned out
+ // to be incorrect, we have to move the contents along in order to make
+ // space.
+ if child.pendingLenLen != 1 {
+ panic("cryptobyte: internal error")
+ }
+ var lenLen, lenByte uint8
+ if int64(length) > 0xfffffffe {
+ b.err = errors.New("pending ASN.1 child too long")
+ return
+ } else if length > 0xffffff {
+ lenLen = 5
+ lenByte = 0x80 | 4
+ } else if length > 0xffff {
+ lenLen = 4
+ lenByte = 0x80 | 3
+ } else if length > 0xff {
+ lenLen = 3
+ lenByte = 0x80 | 2
+ } else if length > 0x7f {
+ lenLen = 2
+ lenByte = 0x80 | 1
+ } else {
+ lenLen = 1
+ lenByte = uint8(length)
+ length = 0
+ }
+
+ // Insert the initial length byte, make space for successive length bytes,
+ // and adjust the offset.
+ child.result[child.offset] = lenByte
+ extraBytes := int(lenLen - 1)
+ if extraBytes != 0 {
+ child.add(make([]byte, extraBytes)...)
+ childStart := child.offset + child.pendingLenLen
+ copy(child.result[childStart+extraBytes:], child.result[childStart:])
+ }
+ child.offset++
+ child.pendingLenLen = extraBytes
+ }
+
+ l := length
+ for i := child.pendingLenLen - 1; i >= 0; i-- {
+ child.result[child.offset+i] = uint8(l)
+ l >>= 8
+ }
+ if l != 0 {
+ b.err = fmt.Errorf("cryptobyte: pending child length %d exceeds %d-byte length prefix", length, child.pendingLenLen)
+ return
+ }
+
+ if !b.fixedSize {
+ b.result = child.result // In case child reallocated result.
+ }
+}
+
+func (b *Builder) add(bytes ...byte) {
+ if b.err != nil {
+ return
+ }
+ if b.child != nil {
+ panic("attempted write while child is pending")
+ }
+ if len(b.result)+len(bytes) < len(bytes) {
+ b.err = errors.New("cryptobyte: length overflow")
+ }
+ if b.fixedSize && len(b.result)+len(bytes) > cap(b.result) {
+ b.err = errors.New("cryptobyte: Builder is exceeding its fixed-size buffer")
+ return
+ }
+ b.result = append(b.result, bytes...)
+}
+
+// A MarshalingValue marshals itself into a Builder.
+type MarshalingValue interface {
+ // Marshal is called by Builder.AddValue. It receives a pointer to a builder
+ // to marshal itself into. It may return an error that occurred during
+ // marshaling, such as unset or invalid values.
+ Marshal(b *Builder) error
+}
+
+// AddValue calls Marshal on v, passing a pointer to the builder to append to.
+// If Marshal returns an error, it is set on the Builder so that subsequent
+// appends don't have an effect.
+func (b *Builder) AddValue(v MarshalingValue) {
+ err := v.Marshal(b)
+ if err != nil {
+ b.err = err
+ }
+}
diff --git a/vendor/golang.org/x/crypto/cryptobyte/cryptobyte_test.go b/vendor/golang.org/x/crypto/cryptobyte/cryptobyte_test.go
new file mode 100644
index 0000000..49c61dc
--- /dev/null
+++ b/vendor/golang.org/x/crypto/cryptobyte/cryptobyte_test.go
@@ -0,0 +1,379 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package cryptobyte
+
+import (
+ "bytes"
+ "fmt"
+ "testing"
+)
+
+func builderBytesEq(b *Builder, want ...byte) error {
+ got := b.BytesOrPanic()
+ if !bytes.Equal(got, want) {
+ return fmt.Errorf("Bytes() = %v, want %v", got, want)
+ }
+ return nil
+}
+
+func TestBytes(t *testing.T) {
+ var b Builder
+ v := []byte("foobarbaz")
+ b.AddBytes(v[0:3])
+ b.AddBytes(v[3:4])
+ b.AddBytes(v[4:9])
+ if err := builderBytesEq(&b, v...); err != nil {
+ t.Error(err)
+ }
+ s := String(b.BytesOrPanic())
+ for _, w := range []string{"foo", "bar", "baz"} {
+ var got []byte
+ if !s.ReadBytes(&got, 3) {
+ t.Errorf("ReadBytes() = false, want true (w = %v)", w)
+ }
+ want := []byte(w)
+ if !bytes.Equal(got, want) {
+ t.Errorf("ReadBytes(): got = %v, want %v", got, want)
+ }
+ }
+ if len(s) != 0 {
+ t.Errorf("len(s) = %d, want 0", len(s))
+ }
+}
+
+func TestUint8(t *testing.T) {
+ var b Builder
+ b.AddUint8(42)
+ if err := builderBytesEq(&b, 42); err != nil {
+ t.Error(err)
+ }
+
+ var s String = b.BytesOrPanic()
+ var v uint8
+ if !s.ReadUint8(&v) {
+ t.Error("ReadUint8() = false, want true")
+ }
+ if v != 42 {
+ t.Errorf("v = %d, want 42", v)
+ }
+ if len(s) != 0 {
+ t.Errorf("len(s) = %d, want 0", len(s))
+ }
+}
+
+func TestUint16(t *testing.T) {
+ var b Builder
+ b.AddUint16(65534)
+ if err := builderBytesEq(&b, 255, 254); err != nil {
+ t.Error(err)
+ }
+ var s String = b.BytesOrPanic()
+ var v uint16
+ if !s.ReadUint16(&v) {
+ t.Error("ReadUint16() == false, want true")
+ }
+ if v != 65534 {
+ t.Errorf("v = %d, want 65534", v)
+ }
+ if len(s) != 0 {
+ t.Errorf("len(s) = %d, want 0", len(s))
+ }
+}
+
+func TestUint24(t *testing.T) {
+ var b Builder
+ b.AddUint24(0xfffefd)
+ if err := builderBytesEq(&b, 255, 254, 253); err != nil {
+ t.Error(err)
+ }
+
+ var s String = b.BytesOrPanic()
+ var v uint32
+ if !s.ReadUint24(&v) {
+ t.Error("ReadUint8() = false, want true")
+ }
+ if v != 0xfffefd {
+ t.Errorf("v = %d, want fffefd", v)
+ }
+ if len(s) != 0 {
+ t.Errorf("len(s) = %d, want 0", len(s))
+ }
+}
+
+func TestUint24Truncation(t *testing.T) {
+ var b Builder
+ b.AddUint24(0x10111213)
+ if err := builderBytesEq(&b, 0x11, 0x12, 0x13); err != nil {
+ t.Error(err)
+ }
+}
+
+func TestUint32(t *testing.T) {
+ var b Builder
+ b.AddUint32(0xfffefdfc)
+ if err := builderBytesEq(&b, 255, 254, 253, 252); err != nil {
+ t.Error(err)
+ }
+
+ var s String = b.BytesOrPanic()
+ var v uint32
+ if !s.ReadUint32(&v) {
+ t.Error("ReadUint8() = false, want true")
+ }
+ if v != 0xfffefdfc {
+ t.Errorf("v = %x, want fffefdfc", v)
+ }
+ if len(s) != 0 {
+ t.Errorf("len(s) = %d, want 0", len(s))
+ }
+}
+
+func TestUMultiple(t *testing.T) {
+ var b Builder
+ b.AddUint8(23)
+ b.AddUint32(0xfffefdfc)
+ b.AddUint16(42)
+ if err := builderBytesEq(&b, 23, 255, 254, 253, 252, 0, 42); err != nil {
+ t.Error(err)
+ }
+
+ var s String = b.BytesOrPanic()
+ var (
+ x uint8
+ y uint32
+ z uint16
+ )
+ if !s.ReadUint8(&x) || !s.ReadUint32(&y) || !s.ReadUint16(&z) {
+ t.Error("ReadUint8() = false, want true")
+ }
+ if x != 23 || y != 0xfffefdfc || z != 42 {
+ t.Errorf("x, y, z = %d, %d, %d; want 23, 4294901244, 5", x, y, z)
+ }
+ if len(s) != 0 {
+ t.Errorf("len(s) = %d, want 0", len(s))
+ }
+}
+
+func TestUint8LengthPrefixedSimple(t *testing.T) {
+ var b Builder
+ b.AddUint8LengthPrefixed(func(c *Builder) {
+ c.AddUint8(23)
+ c.AddUint8(42)
+ })
+ if err := builderBytesEq(&b, 2, 23, 42); err != nil {
+ t.Error(err)
+ }
+
+ var base, child String = b.BytesOrPanic(), nil
+ var x, y uint8
+ if !base.ReadUint8LengthPrefixed(&child) || !child.ReadUint8(&x) ||
+ !child.ReadUint8(&y) {
+ t.Error("parsing failed")
+ }
+ if x != 23 || y != 42 {
+ t.Errorf("want x, y == 23, 42; got %d, %d", x, y)
+ }
+ if len(base) != 0 {
+ t.Errorf("len(base) = %d, want 0", len(base))
+ }
+ if len(child) != 0 {
+ t.Errorf("len(child) = %d, want 0", len(child))
+ }
+}
+
+func TestUint8LengthPrefixedMulti(t *testing.T) {
+ var b Builder
+ b.AddUint8LengthPrefixed(func(c *Builder) {
+ c.AddUint8(23)
+ c.AddUint8(42)
+ })
+ b.AddUint8(5)
+ b.AddUint8LengthPrefixed(func(c *Builder) {
+ c.AddUint8(123)
+ c.AddUint8(234)
+ })
+ if err := builderBytesEq(&b, 2, 23, 42, 5, 2, 123, 234); err != nil {
+ t.Error(err)
+ }
+
+ var s, child String = b.BytesOrPanic(), nil
+ var u, v, w, x, y uint8
+ if !s.ReadUint8LengthPrefixed(&child) || !child.ReadUint8(&u) || !child.ReadUint8(&v) ||
+ !s.ReadUint8(&w) || !s.ReadUint8LengthPrefixed(&child) || !child.ReadUint8(&x) || !child.ReadUint8(&y) {
+ t.Error("parsing failed")
+ }
+ if u != 23 || v != 42 || w != 5 || x != 123 || y != 234 {
+ t.Errorf("u, v, w, x, y = %d, %d, %d, %d, %d; want 23, 42, 5, 123, 234",
+ u, v, w, x, y)
+ }
+ if len(s) != 0 {
+ t.Errorf("len(s) = %d, want 0", len(s))
+ }
+ if len(child) != 0 {
+ t.Errorf("len(child) = %d, want 0", len(child))
+ }
+}
+
+func TestUint8LengthPrefixedNested(t *testing.T) {
+ var b Builder
+ b.AddUint8LengthPrefixed(func(c *Builder) {
+ c.AddUint8(5)
+ c.AddUint8LengthPrefixed(func(d *Builder) {
+ d.AddUint8(23)
+ d.AddUint8(42)
+ })
+ c.AddUint8(123)
+ })
+ if err := builderBytesEq(&b, 5, 5, 2, 23, 42, 123); err != nil {
+ t.Error(err)
+ }
+
+ var base, child1, child2 String = b.BytesOrPanic(), nil, nil
+ var u, v, w, x uint8
+ if !base.ReadUint8LengthPrefixed(&child1) {
+ t.Error("parsing base failed")
+ }
+ if !child1.ReadUint8(&u) || !child1.ReadUint8LengthPrefixed(&child2) || !child1.ReadUint8(&x) {
+ t.Error("parsing child1 failed")
+ }
+ if !child2.ReadUint8(&v) || !child2.ReadUint8(&w) {
+ t.Error("parsing child2 failed")
+ }
+ if u != 5 || v != 23 || w != 42 || x != 123 {
+ t.Errorf("u, v, w, x = %d, %d, %d, %d, want 5, 23, 42, 123",
+ u, v, w, x)
+ }
+ if len(base) != 0 {
+ t.Errorf("len(base) = %d, want 0", len(base))
+ }
+ if len(child1) != 0 {
+ t.Errorf("len(child1) = %d, want 0", len(child1))
+ }
+ if len(base) != 0 {
+ t.Errorf("len(child2) = %d, want 0", len(child2))
+ }
+}
+
+func TestPreallocatedBuffer(t *testing.T) {
+ var buf [5]byte
+ b := NewBuilder(buf[0:0])
+ b.AddUint8(1)
+ b.AddUint8LengthPrefixed(func(c *Builder) {
+ c.AddUint8(3)
+ c.AddUint8(4)
+ })
+ b.AddUint16(1286) // Outgrow buf by one byte.
+ want := []byte{1, 2, 3, 4, 0}
+ if !bytes.Equal(buf[:], want) {
+ t.Errorf("buf = %v want %v", buf, want)
+ }
+ if err := builderBytesEq(b, 1, 2, 3, 4, 5, 6); err != nil {
+ t.Error(err)
+ }
+}
+
+func TestWriteWithPendingChild(t *testing.T) {
+ var b Builder
+ b.AddUint8LengthPrefixed(func(c *Builder) {
+ c.AddUint8LengthPrefixed(func(d *Builder) {
+ defer func() {
+ if recover() == nil {
+ t.Errorf("recover() = nil, want error; c.AddUint8() did not panic")
+ }
+ }()
+ c.AddUint8(2) // panics
+
+ defer func() {
+ if recover() == nil {
+ t.Errorf("recover() = nil, want error; b.AddUint8() did not panic")
+ }
+ }()
+ b.AddUint8(2) // panics
+ })
+
+ defer func() {
+ if recover() == nil {
+ t.Errorf("recover() = nil, want error; b.AddUint8() did not panic")
+ }
+ }()
+ b.AddUint8(2) // panics
+ })
+}
+
+// ASN.1
+
+func TestASN1Int64(t *testing.T) {
+ tests := []struct {
+ in int64
+ want []byte
+ }{
+ {-0x800000, []byte{2, 3, 128, 0, 0}},
+ {-256, []byte{2, 2, 255, 0}},
+ {-129, []byte{2, 2, 255, 127}},
+ {-128, []byte{2, 1, 128}},
+ {-1, []byte{2, 1, 255}},
+ {0, []byte{2, 1, 0}},
+ {1, []byte{2, 1, 1}},
+ {2, []byte{2, 1, 2}},
+ {127, []byte{2, 1, 127}},
+ {128, []byte{2, 2, 0, 128}},
+ {256, []byte{2, 2, 1, 0}},
+ {0x800000, []byte{2, 4, 0, 128, 0, 0}},
+ }
+ for i, tt := range tests {
+ var b Builder
+ b.AddASN1Int64(tt.in)
+ if err := builderBytesEq(&b, tt.want...); err != nil {
+ t.Errorf("%v, (i = %d; in = %v)", err, i, tt.in)
+ }
+
+ var n int64
+ s := String(b.BytesOrPanic())
+ ok := s.ReadASN1Integer(&n)
+ if !ok || n != tt.in {
+ t.Errorf("s.ReadASN1Integer(&n) = %v, n = %d; want true, n = %d (i = %d)",
+ ok, n, tt.in, i)
+ }
+ if len(s) != 0 {
+ t.Errorf("len(s) = %d, want 0", len(s))
+ }
+ }
+}
+
+func TestASN1Uint64(t *testing.T) {
+ tests := []struct {
+ in uint64
+ want []byte
+ }{
+ {0, []byte{2, 1, 0}},
+ {1, []byte{2, 1, 1}},
+ {2, []byte{2, 1, 2}},
+ {127, []byte{2, 1, 127}},
+ {128, []byte{2, 2, 0, 128}},
+ {256, []byte{2, 2, 1, 0}},
+ {0x800000, []byte{2, 4, 0, 128, 0, 0}},
+ {0x7fffffffffffffff, []byte{2, 8, 127, 255, 255, 255, 255, 255, 255, 255}},
+ {0x8000000000000000, []byte{2, 9, 0, 128, 0, 0, 0, 0, 0, 0, 0}},
+ {0xffffffffffffffff, []byte{2, 9, 0, 255, 255, 255, 255, 255, 255, 255, 255}},
+ }
+ for i, tt := range tests {
+ var b Builder
+ b.AddASN1Uint64(tt.in)
+ if err := builderBytesEq(&b, tt.want...); err != nil {
+ t.Errorf("%v, (i = %d; in = %v)", err, i, tt.in)
+ }
+
+ var n uint64
+ s := String(b.BytesOrPanic())
+ ok := s.ReadASN1Integer(&n)
+ if !ok || n != tt.in {
+ t.Errorf("s.ReadASN1Integer(&n) = %v, n = %d; want true, n = %d (i = %d)",
+ ok, n, tt.in, i)
+ }
+ if len(s) != 0 {
+ t.Errorf("len(s) = %d, want 0", len(s))
+ }
+ }
+}
diff --git a/vendor/golang.org/x/crypto/cryptobyte/example_test.go b/vendor/golang.org/x/crypto/cryptobyte/example_test.go
new file mode 100644
index 0000000..7d3c06e
--- /dev/null
+++ b/vendor/golang.org/x/crypto/cryptobyte/example_test.go
@@ -0,0 +1,120 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package cryptobyte_test
+
+import (
+ "encoding/asn1"
+ "fmt"
+ "golang.org/x/crypto/cryptobyte"
+)
+
+func ExampleString_lengthPrefixed() {
+ // This is an example of parsing length-prefixed data (as found in, for
+ // example, TLS). Imagine a 16-bit prefixed series of 8-bit prefixed
+ // strings.
+
+ input := cryptobyte.String([]byte{0, 12, 5, 'h', 'e', 'l', 'l', 'o', 5, 'w', 'o', 'r', 'l', 'd'})
+ var result []string
+
+ var values cryptobyte.String
+ if !input.ReadUint16LengthPrefixed(&values) ||
+ !input.Empty() {
+ panic("bad format")
+ }
+
+ for !values.Empty() {
+ var value cryptobyte.String
+ if !values.ReadUint8LengthPrefixed(&value) {
+ panic("bad format")
+ }
+
+ result = append(result, string(value))
+ }
+
+ // Output: []string{"hello", "world"}
+ fmt.Printf("%#v\n", result)
+}
+
+func ExampleString_asn1() {
+ // This is an example of parsing ASN.1 data that looks like:
+ // Foo ::= SEQUENCE {
+ // version [6] INTEGER DEFAULT 0
+ // data OCTET STRING
+ // }
+
+ input := cryptobyte.String([]byte{0x30, 12, 0xa6, 3, 2, 1, 2, 4, 5, 'h', 'e', 'l', 'l', 'o'})
+
+ var (
+ version int64
+ data, inner, versionBytes cryptobyte.String
+ haveVersion bool
+ )
+ if !input.ReadASN1(&inner, cryptobyte.Tag(asn1.TagSequence).Constructed()) ||
+ !input.Empty() ||
+ !inner.ReadOptionalASN1(&versionBytes, &haveVersion, cryptobyte.Tag(6).Constructed().ContextSpecific()) ||
+ (haveVersion && !versionBytes.ReadASN1Integer(&version)) ||
+ (haveVersion && !versionBytes.Empty()) ||
+ !inner.ReadASN1(&data, asn1.TagOctetString) ||
+ !inner.Empty() {
+ panic("bad format")
+ }
+
+ // Output: haveVersion: true, version: 2, data: hello
+ fmt.Printf("haveVersion: %t, version: %d, data: %s\n", haveVersion, version, string(data))
+}
+
+func ExampleBuilder_asn1() {
+ // This is an example of building ASN.1 data that looks like:
+ // Foo ::= SEQUENCE {
+ // version [6] INTEGER DEFAULT 0
+ // data OCTET STRING
+ // }
+
+ version := int64(2)
+ data := []byte("hello")
+ const defaultVersion = 0
+
+ var b cryptobyte.Builder
+ b.AddASN1(cryptobyte.Tag(asn1.TagSequence).Constructed(), func(b *cryptobyte.Builder) {
+ if version != defaultVersion {
+ b.AddASN1(cryptobyte.Tag(6).Constructed().ContextSpecific(), func(b *cryptobyte.Builder) {
+ b.AddASN1Int64(version)
+ })
+ }
+ b.AddASN1OctetString(data)
+ })
+
+ result, err := b.Bytes()
+ if err != nil {
+ panic(err)
+ }
+
+ // Output: 300ca603020102040568656c6c6f
+ fmt.Printf("%x\n", result)
+}
+
+func ExampleBuilder_lengthPrefixed() {
+ // This is an example of building length-prefixed data (as found in,
+ // for example, TLS). Imagine a 16-bit prefixed series of 8-bit
+ // prefixed strings.
+ input := []string{"hello", "world"}
+
+ var b cryptobyte.Builder
+ b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
+ for _, value := range input {
+ b.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) {
+ b.AddBytes([]byte(value))
+ })
+ }
+ })
+
+ result, err := b.Bytes()
+ if err != nil {
+ panic(err)
+ }
+
+ // Output: 000c0568656c6c6f05776f726c64
+ fmt.Printf("%x\n", result)
+}
diff --git a/vendor/golang.org/x/crypto/cryptobyte/string.go b/vendor/golang.org/x/crypto/cryptobyte/string.go
new file mode 100644
index 0000000..6780336
--- /dev/null
+++ b/vendor/golang.org/x/crypto/cryptobyte/string.go
@@ -0,0 +1,157 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package cryptobyte implements building and parsing of byte strings for
+// DER-encoded ASN.1 and TLS messages. See the examples for the Builder and
+// String types to get started.
+package cryptobyte // import "golang.org/x/crypto/cryptobyte"
+
+// String represents a string of bytes. It provides methods for parsing
+// fixed-length and length-prefixed values from it.
+type String []byte
+
+// read advances a String by n bytes and returns them. If less than n bytes
+// remain, it returns nil.
+func (s *String) read(n int) []byte {
+ if len(*s) < n {
+ return nil
+ }
+ v := (*s)[:n]
+ *s = (*s)[n:]
+ return v
+}
+
+// Skip advances the String by n byte and reports whether it was successful.
+func (s *String) Skip(n int) bool {
+ return s.read(n) != nil
+}
+
+// ReadUint8 decodes an 8-bit value into out and advances over it. It
+// returns true on success and false on error.
+func (s *String) ReadUint8(out *uint8) bool {
+ v := s.read(1)
+ if v == nil {
+ return false
+ }
+ *out = uint8(v[0])
+ return true
+}
+
+// ReadUint16 decodes a big-endian, 16-bit value into out and advances over it.
+// It returns true on success and false on error.
+func (s *String) ReadUint16(out *uint16) bool {
+ v := s.read(2)
+ if v == nil {
+ return false
+ }
+ *out = uint16(v[0])<<8 | uint16(v[1])
+ return true
+}
+
+// ReadUint24 decodes a big-endian, 24-bit value into out and advances over it.
+// It returns true on success and false on error.
+func (s *String) ReadUint24(out *uint32) bool {
+ v := s.read(3)
+ if v == nil {
+ return false
+ }
+ *out = uint32(v[0])<<16 | uint32(v[1])<<8 | uint32(v[2])
+ return true
+}
+
+// ReadUint32 decodes a big-endian, 32-bit value into out and advances over it.
+// It returns true on success and false on error.
+func (s *String) ReadUint32(out *uint32) bool {
+ v := s.read(4)
+ if v == nil {
+ return false
+ }
+ *out = uint32(v[0])<<24 | uint32(v[1])<<16 | uint32(v[2])<<8 | uint32(v[3])
+ return true
+}
+
+func (s *String) readUnsigned(out *uint32, length int) bool {
+ v := s.read(length)
+ if v == nil {
+ return false
+ }
+ var result uint32
+ for i := 0; i < length; i++ {
+ result <<= 8
+ result |= uint32(v[i])
+ }
+ *out = result
+ return true
+}
+
+func (s *String) readLengthPrefixed(lenLen int, outChild *String) bool {
+ lenBytes := s.read(lenLen)
+ if lenBytes == nil {
+ return false
+ }
+ var length uint32
+ for _, b := range lenBytes {
+ length = length << 8
+ length = length | uint32(b)
+ }
+ if int(length) < 0 {
+ // This currently cannot overflow because we read uint24 at most, but check
+ // anyway in case that changes in the future.
+ return false
+ }
+ v := s.read(int(length))
+ if v == nil {
+ return false
+ }
+ *outChild = v
+ return true
+}
+
+// ReadUint8LengthPrefixed reads the content of an 8-bit length-prefixed value
+// into out and advances over it. It returns true on success and false on
+// error.
+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.
+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.
+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.
+func (s *String) ReadBytes(out *[]byte, n int) bool {
+ v := s.read(n)
+ if v == nil {
+ return false
+ }
+ *out = v
+ return true
+}
+
+// CopyBytes copies len(out) bytes into out and advances over them. It returns
+// true on success and false on error.
+func (s *String) CopyBytes(out []byte) bool {
+ n := len(out)
+ v := s.read(n)
+ if v == nil {
+ return false
+ }
+ return copy(out, v) == n
+}
+
+// Empty reports whether the string does not contain any bytes.
+func (s String) Empty() bool {
+ return len(s) == 0
+}
diff --git a/vendor/golang.org/x/crypto/curve25519/const_amd64.h b/vendor/golang.org/x/crypto/curve25519/const_amd64.h
new file mode 100644
index 0000000..80ad222
--- /dev/null
+++ b/vendor/golang.org/x/crypto/curve25519/const_amd64.h
@@ -0,0 +1,8 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This code was translated into a form compatible with 6a from the public
+// domain sources in SUPERCOP: http://bench.cr.yp.to/supercop.html
+
+#define REDMASK51 0x0007FFFFFFFFFFFF
diff --git a/vendor/golang.org/x/crypto/curve25519/const_amd64.s b/vendor/golang.org/x/crypto/curve25519/const_amd64.s
index 797f9b0..0ad5398 100644
--- a/vendor/golang.org/x/crypto/curve25519/const_amd64.s
+++ b/vendor/golang.org/x/crypto/curve25519/const_amd64.s
@@ -7,8 +7,8 @@
// +build amd64,!gccgo,!appengine
-DATA ·REDMASK51(SB)/8, $0x0007FFFFFFFFFFFF
-GLOBL ·REDMASK51(SB), 8, $8
+// These constants cannot be encoded in non-MOVQ immediates.
+// We access them directly from memory instead.
DATA ·_121666_213(SB)/8, $996687872
GLOBL ·_121666_213(SB), 8, $8
diff --git a/vendor/golang.org/x/crypto/curve25519/cswap_amd64.s b/vendor/golang.org/x/crypto/curve25519/cswap_amd64.s
index 45484d1..cd793a5 100644
--- a/vendor/golang.org/x/crypto/curve25519/cswap_amd64.s
+++ b/vendor/golang.org/x/crypto/curve25519/cswap_amd64.s
@@ -2,87 +2,64 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// This code was translated into a form compatible with 6a from the public
-// domain sources in SUPERCOP: http://bench.cr.yp.to/supercop.html
-
// +build amd64,!gccgo,!appengine
-// func cswap(inout *[5]uint64, v uint64)
+// func cswap(inout *[4][5]uint64, v uint64)
TEXT ·cswap(SB),7,$0
MOVQ inout+0(FP),DI
MOVQ v+8(FP),SI
- CMPQ SI,$1
- MOVQ 0(DI),SI
- MOVQ 80(DI),DX
- MOVQ 8(DI),CX
- MOVQ 88(DI),R8
- MOVQ SI,R9
- CMOVQEQ DX,SI
- CMOVQEQ R9,DX
- MOVQ CX,R9
- CMOVQEQ R8,CX
- CMOVQEQ R9,R8
- MOVQ SI,0(DI)
- MOVQ DX,80(DI)
- MOVQ CX,8(DI)
- MOVQ R8,88(DI)
- MOVQ 16(DI),SI
- MOVQ 96(DI),DX
- MOVQ 24(DI),CX
- MOVQ 104(DI),R8
- MOVQ SI,R9
- CMOVQEQ DX,SI
- CMOVQEQ R9,DX
- MOVQ CX,R9
- CMOVQEQ R8,CX
- CMOVQEQ R9,R8
- MOVQ SI,16(DI)
- MOVQ DX,96(DI)
- MOVQ CX,24(DI)
- MOVQ R8,104(DI)
- MOVQ 32(DI),SI
- MOVQ 112(DI),DX
- MOVQ 40(DI),CX
- MOVQ 120(DI),R8
- MOVQ SI,R9
- CMOVQEQ DX,SI
- CMOVQEQ R9,DX
- MOVQ CX,R9
- CMOVQEQ R8,CX
- CMOVQEQ R9,R8
- MOVQ SI,32(DI)
- MOVQ DX,112(DI)
- MOVQ CX,40(DI)
- MOVQ R8,120(DI)
- MOVQ 48(DI),SI
- MOVQ 128(DI),DX
- MOVQ 56(DI),CX
- MOVQ 136(DI),R8
- MOVQ SI,R9
- CMOVQEQ DX,SI
- CMOVQEQ R9,DX
- MOVQ CX,R9
- CMOVQEQ R8,CX
- CMOVQEQ R9,R8
- MOVQ SI,48(DI)
- MOVQ DX,128(DI)
- MOVQ CX,56(DI)
- MOVQ R8,136(DI)
- MOVQ 64(DI),SI
- MOVQ 144(DI),DX
- MOVQ 72(DI),CX
- MOVQ 152(DI),R8
- MOVQ SI,R9
- CMOVQEQ DX,SI
- CMOVQEQ R9,DX
- MOVQ CX,R9
- CMOVQEQ R8,CX
- CMOVQEQ R9,R8
- MOVQ SI,64(DI)
- MOVQ DX,144(DI)
- MOVQ CX,72(DI)
- MOVQ R8,152(DI)
- MOVQ DI,AX
- MOVQ SI,DX
+ SUBQ $1, SI
+ NOTQ SI
+ MOVQ SI, X15
+ PSHUFD $0x44, X15, X15
+
+ MOVOU 0(DI), X0
+ MOVOU 16(DI), X2
+ MOVOU 32(DI), X4
+ MOVOU 48(DI), X6
+ MOVOU 64(DI), X8
+ MOVOU 80(DI), X1
+ MOVOU 96(DI), X3
+ MOVOU 112(DI), X5
+ MOVOU 128(DI), X7
+ MOVOU 144(DI), X9
+
+ MOVO X1, X10
+ MOVO X3, X11
+ MOVO X5, X12
+ MOVO X7, X13
+ MOVO X9, X14
+
+ PXOR X0, X10
+ PXOR X2, X11
+ PXOR X4, X12
+ PXOR X6, X13
+ PXOR X8, X14
+ PAND X15, X10
+ PAND X15, X11
+ PAND X15, X12
+ PAND X15, X13
+ PAND X15, X14
+ PXOR X10, X0
+ PXOR X10, X1
+ PXOR X11, X2
+ PXOR X11, X3
+ PXOR X12, X4
+ PXOR X12, X5
+ PXOR X13, X6
+ PXOR X13, X7
+ PXOR X14, X8
+ PXOR X14, X9
+
+ MOVOU X0, 0(DI)
+ MOVOU X2, 16(DI)
+ MOVOU X4, 32(DI)
+ MOVOU X6, 48(DI)
+ MOVOU X8, 64(DI)
+ MOVOU X1, 80(DI)
+ MOVOU X3, 96(DI)
+ MOVOU X5, 112(DI)
+ MOVOU X7, 128(DI)
+ MOVOU X9, 144(DI)
RET
diff --git a/vendor/golang.org/x/crypto/curve25519/curve25519.go b/vendor/golang.org/x/crypto/curve25519/curve25519.go
index 6918c47..2d14c2a 100644
--- a/vendor/golang.org/x/crypto/curve25519/curve25519.go
+++ b/vendor/golang.org/x/crypto/curve25519/curve25519.go
@@ -8,6 +8,10 @@
package curve25519
+import (
+ "encoding/binary"
+)
+
// This code is a port of the public domain, "ref10" implementation of
// curve25519 from SUPERCOP 20130419 by D. J. Bernstein.
@@ -50,17 +54,11 @@ func feCopy(dst, src *fieldElement) {
//
// Preconditions: b in {0,1}.
func feCSwap(f, g *fieldElement, b int32) {
- var x fieldElement
b = -b
- for i := range x {
- x[i] = b & (f[i] ^ g[i])
- }
-
for i := range f {
- f[i] ^= x[i]
- }
- for i := range g {
- g[i] ^= x[i]
+ t := b & (f[i] ^ g[i])
+ f[i] ^= t
+ g[i] ^= t
}
}
@@ -75,12 +73,7 @@ func load3(in []byte) int64 {
// load4 reads a 32-bit, little-endian value from in.
func load4(in []byte) int64 {
- var r int64
- r = int64(in[0])
- r |= int64(in[1]) << 8
- r |= int64(in[2]) << 16
- r |= int64(in[3]) << 24
- return r
+ return int64(binary.LittleEndian.Uint32(in))
}
func feFromBytes(dst *fieldElement, src *[32]byte) {
diff --git a/vendor/golang.org/x/crypto/curve25519/curve25519_test.go b/vendor/golang.org/x/crypto/curve25519/curve25519_test.go
index 14b0ee8..051a830 100644
--- a/vendor/golang.org/x/crypto/curve25519/curve25519_test.go
+++ b/vendor/golang.org/x/crypto/curve25519/curve25519_test.go
@@ -27,3 +27,13 @@ func TestBaseScalarMult(t *testing.T) {
t.Errorf("incorrect result: got %s, want %s", result, expectedHex)
}
}
+
+func BenchmarkScalarBaseMult(b *testing.B) {
+ var in, out [32]byte
+ in[0] = 1
+
+ b.SetBytes(32)
+ for i := 0; i < b.N; i++ {
+ ScalarBaseMult(&out, &in)
+ }
+}
diff --git a/vendor/golang.org/x/crypto/curve25519/freeze_amd64.s b/vendor/golang.org/x/crypto/curve25519/freeze_amd64.s
index 932800b..536479b 100644
--- a/vendor/golang.org/x/crypto/curve25519/freeze_amd64.s
+++ b/vendor/golang.org/x/crypto/curve25519/freeze_amd64.s
@@ -7,6 +7,8 @@
// +build amd64,!gccgo,!appengine
+#include "const_amd64.h"
+
// func freeze(inout *[5]uint64)
TEXT ·freeze(SB),7,$0-8
MOVQ inout+0(FP), DI
@@ -16,7 +18,7 @@ TEXT ·freeze(SB),7,$0-8
MOVQ 16(DI),CX
MOVQ 24(DI),R8
MOVQ 32(DI),R9
- MOVQ ·REDMASK51(SB),AX
+ MOVQ $REDMASK51,AX
MOVQ AX,R10
SUBQ $18,R10
MOVQ $3,R11
diff --git a/vendor/golang.org/x/crypto/curve25519/ladderstep_amd64.s b/vendor/golang.org/x/crypto/curve25519/ladderstep_amd64.s
index ee7b36c..7074e5c 100644
--- a/vendor/golang.org/x/crypto/curve25519/ladderstep_amd64.s
+++ b/vendor/golang.org/x/crypto/curve25519/ladderstep_amd64.s
@@ -7,6 +7,8 @@
// +build amd64,!gccgo,!appengine
+#include "const_amd64.h"
+
// func ladderstep(inout *[5][5]uint64)
TEXT ·ladderstep(SB),0,$296-8
MOVQ inout+0(FP),DI
@@ -118,7 +120,7 @@ TEXT ·ladderstep(SB),0,$296-8
MULQ 72(SP)
ADDQ AX,R12
ADCQ DX,R13
- MOVQ ·REDMASK51(SB),DX
+ MOVQ $REDMASK51,DX
SHLQ $13,CX:SI
ANDQ DX,SI
SHLQ $13,R9:R8
@@ -233,7 +235,7 @@ TEXT ·ladderstep(SB),0,$296-8
MULQ 32(SP)
ADDQ AX,R12
ADCQ DX,R13
- MOVQ ·REDMASK51(SB),DX
+ MOVQ $REDMASK51,DX
SHLQ $13,CX:SI
ANDQ DX,SI
SHLQ $13,R9:R8
@@ -438,7 +440,7 @@ TEXT ·ladderstep(SB),0,$296-8
MULQ 72(SP)
ADDQ AX,R12
ADCQ DX,R13
- MOVQ ·REDMASK51(SB),DX
+ MOVQ $REDMASK51,DX
SHLQ $13,CX:SI
ANDQ DX,SI
SHLQ $13,R9:R8
@@ -588,7 +590,7 @@ TEXT ·ladderstep(SB),0,$296-8
MULQ 32(SP)
ADDQ AX,R12
ADCQ DX,R13
- MOVQ ·REDMASK51(SB),DX
+ MOVQ $REDMASK51,DX
SHLQ $13,CX:SI
ANDQ DX,SI
SHLQ $13,R9:R8
@@ -728,7 +730,7 @@ TEXT ·ladderstep(SB),0,$296-8
MULQ 152(DI)
ADDQ AX,R12
ADCQ DX,R13
- MOVQ ·REDMASK51(SB),DX
+ MOVQ $REDMASK51,DX
SHLQ $13,CX:SI
ANDQ DX,SI
SHLQ $13,R9:R8
@@ -843,7 +845,7 @@ TEXT ·ladderstep(SB),0,$296-8
MULQ 192(DI)
ADDQ AX,R12
ADCQ DX,R13
- MOVQ ·REDMASK51(SB),DX
+ MOVQ $REDMASK51,DX
SHLQ $13,CX:SI
ANDQ DX,SI
SHLQ $13,R9:R8
@@ -993,7 +995,7 @@ TEXT ·ladderstep(SB),0,$296-8
MULQ 32(DI)
ADDQ AX,R12
ADCQ DX,R13
- MOVQ ·REDMASK51(SB),DX
+ MOVQ $REDMASK51,DX
SHLQ $13,CX:SI
ANDQ DX,SI
SHLQ $13,R9:R8
@@ -1143,7 +1145,7 @@ TEXT ·ladderstep(SB),0,$296-8
MULQ 112(SP)
ADDQ AX,R12
ADCQ DX,R13
- MOVQ ·REDMASK51(SB),DX
+ MOVQ $REDMASK51,DX
SHLQ $13,CX:SI
ANDQ DX,SI
SHLQ $13,R9:R8
@@ -1329,7 +1331,7 @@ TEXT ·ladderstep(SB),0,$296-8
MULQ 192(SP)
ADDQ AX,R12
ADCQ DX,R13
- MOVQ ·REDMASK51(SB),DX
+ MOVQ $REDMASK51,DX
SHLQ $13,CX:SI
ANDQ DX,SI
SHLQ $13,R9:R8
diff --git a/vendor/golang.org/x/crypto/curve25519/mul_amd64.s b/vendor/golang.org/x/crypto/curve25519/mul_amd64.s
index 33ce57d..b162e65 100644
--- a/vendor/golang.org/x/crypto/curve25519/mul_amd64.s
+++ b/vendor/golang.org/x/crypto/curve25519/mul_amd64.s
@@ -7,6 +7,8 @@
// +build amd64,!gccgo,!appengine
+#include "const_amd64.h"
+
// func mul(dest, a, b *[5]uint64)
TEXT ·mul(SB),0,$16-24
MOVQ dest+0(FP), DI
@@ -121,7 +123,7 @@ TEXT ·mul(SB),0,$16-24
MULQ 32(CX)
ADDQ AX,R14
ADCQ DX,R15
- MOVQ ·REDMASK51(SB),SI
+ MOVQ $REDMASK51,SI
SHLQ $13,R9:R8
ANDQ SI,R8
SHLQ $13,R11:R10
diff --git a/vendor/golang.org/x/crypto/curve25519/square_amd64.s b/vendor/golang.org/x/crypto/curve25519/square_amd64.s
index 3a92804..4e864a8 100644
--- a/vendor/golang.org/x/crypto/curve25519/square_amd64.s
+++ b/vendor/golang.org/x/crypto/curve25519/square_amd64.s
@@ -7,6 +7,8 @@
// +build amd64,!gccgo,!appengine
+#include "const_amd64.h"
+
// func square(out, in *[5]uint64)
TEXT ·square(SB),7,$0-16
MOVQ out+0(FP), DI
@@ -84,7 +86,7 @@ TEXT ·square(SB),7,$0-16
MULQ 32(SI)
ADDQ AX,R13
ADCQ DX,R14
- MOVQ ·REDMASK51(SB),SI
+ MOVQ $REDMASK51,SI
SHLQ $13,R8:CX
ANDQ SI,CX
SHLQ $13,R10:R9
diff --git a/vendor/golang.org/x/crypto/nacl/box/example_test.go b/vendor/golang.org/x/crypto/nacl/box/example_test.go
new file mode 100644
index 0000000..25e42d2
--- /dev/null
+++ b/vendor/golang.org/x/crypto/nacl/box/example_test.go
@@ -0,0 +1,95 @@
+package box_test
+
+import (
+ crypto_rand "crypto/rand" // Custom so it's clear which rand we're using.
+ "fmt"
+ "io"
+
+ "golang.org/x/crypto/nacl/box"
+)
+
+func Example() {
+ senderPublicKey, senderPrivateKey, err := box.GenerateKey(crypto_rand.Reader)
+ if err != nil {
+ panic(err)
+ }
+
+ recipientPublicKey, recipientPrivateKey, err := box.GenerateKey(crypto_rand.Reader)
+ if err != nil {
+ panic(err)
+ }
+
+ // You must use a different nonce for each message you encrypt with the
+ // same key. Since the nonce here is 192 bits long, a random value
+ // provides a sufficiently small probability of repeats.
+ var nonce [24]byte
+ if _, err := io.ReadFull(crypto_rand.Reader, nonce[:]); err != nil {
+ panic(err)
+ }
+
+ msg := []byte("Alas, poor Yorick! I knew him, Horatio")
+ // This encrypts msg and appends the result to the nonce.
+ encrypted := box.Seal(nonce[:], msg, &nonce, recipientPublicKey, senderPrivateKey)
+
+ // The recipient can decrypt the message using their private key and the
+ // sender's public key. When you decrypt, you must use the same nonce you
+ // used to encrypt the message. One way to achieve this is to store the
+ // nonce alongside the encrypted message. Above, we stored the nonce in the
+ // first 24 bytes of the encrypted text.
+ var decryptNonce [24]byte
+ copy(decryptNonce[:], encrypted[:24])
+ decrypted, ok := box.Open(nil, encrypted[24:], &decryptNonce, senderPublicKey, recipientPrivateKey)
+ if !ok {
+ panic("decryption error")
+ }
+ fmt.Println(string(decrypted))
+ // Output: Alas, poor Yorick! I knew him, Horatio
+}
+
+func Example_precompute() {
+ senderPublicKey, senderPrivateKey, err := box.GenerateKey(crypto_rand.Reader)
+ if err != nil {
+ panic(err)
+ }
+
+ recipientPublicKey, recipientPrivateKey, err := box.GenerateKey(crypto_rand.Reader)
+ if err != nil {
+ panic(err)
+ }
+
+ // The shared key can be used to speed up processing when using the same
+ // pair of keys repeatedly.
+ sharedEncryptKey := new([32]byte)
+ box.Precompute(sharedEncryptKey, recipientPublicKey, senderPrivateKey)
+
+ // You must use a different nonce for each message you encrypt with the
+ // same key. Since the nonce here is 192 bits long, a random value
+ // provides a sufficiently small probability of repeats.
+ var nonce [24]byte
+ if _, err := io.ReadFull(crypto_rand.Reader, nonce[:]); err != nil {
+ panic(err)
+ }
+
+ msg := []byte("A fellow of infinite jest, of most excellent fancy")
+ // This encrypts msg and appends the result to the nonce.
+ encrypted := box.SealAfterPrecomputation(nonce[:], msg, &nonce, sharedEncryptKey)
+
+ // The shared key can be used to speed up processing when using the same
+ // pair of keys repeatedly.
+ var sharedDecryptKey [32]byte
+ box.Precompute(&sharedDecryptKey, senderPublicKey, recipientPrivateKey)
+
+ // The recipient can decrypt the message using the shared key. When you
+ // decrypt, you must use the same nonce you used to encrypt the message.
+ // One way to achieve this is to store the nonce alongside the encrypted
+ // message. Above, we stored the nonce in the first 24 bytes of the
+ // encrypted text.
+ var decryptNonce [24]byte
+ copy(decryptNonce[:], encrypted[:24])
+ decrypted, ok := box.OpenAfterPrecomputation(nil, encrypted[24:], &decryptNonce, &sharedDecryptKey)
+ if !ok {
+ panic("decryption error")
+ }
+ fmt.Println(string(decrypted))
+ // Output: A fellow of infinite jest, of most excellent fancy
+}
diff --git a/vendor/golang.org/x/crypto/nacl/secretbox/example_test.go b/vendor/golang.org/x/crypto/nacl/secretbox/example_test.go
index b25e663..789f4ff 100644
--- a/vendor/golang.org/x/crypto/nacl/secretbox/example_test.go
+++ b/vendor/golang.org/x/crypto/nacl/secretbox/example_test.go
@@ -43,7 +43,7 @@ func Example() {
// 24 bytes of the encrypted text.
var decryptNonce [24]byte
copy(decryptNonce[:], encrypted[:24])
- decrypted, ok := secretbox.Open([]byte{}, encrypted[24:], &decryptNonce, &secretKey)
+ decrypted, ok := secretbox.Open(nil, encrypted[24:], &decryptNonce, &secretKey)
if !ok {
panic("decryption error")
}
diff --git a/vendor/golang.org/x/crypto/nacl/secretbox/secretbox_test.go b/vendor/golang.org/x/crypto/nacl/secretbox/secretbox_test.go
index 664dc15..3c70b0f 100644
--- a/vendor/golang.org/x/crypto/nacl/secretbox/secretbox_test.go
+++ b/vendor/golang.org/x/crypto/nacl/secretbox/secretbox_test.go
@@ -89,3 +89,66 @@ func TestAppend(t *testing.T) {
t.Fatalf("Seal didn't correctly append with sufficient capacity.")
}
}
+
+func benchmarkSealSize(b *testing.B, size int) {
+ message := make([]byte, size)
+ out := make([]byte, size+Overhead)
+ var nonce [24]byte
+ var key [32]byte
+
+ b.SetBytes(int64(size))
+ b.ResetTimer()
+
+ for i := 0; i < b.N; i++ {
+ out = Seal(out[:0], message, &nonce, &key)
+ }
+}
+
+func BenchmarkSeal8Bytes(b *testing.B) {
+ benchmarkSealSize(b, 8)
+}
+
+func BenchmarkSeal100Bytes(b *testing.B) {
+ benchmarkSealSize(b, 100)
+}
+
+func BenchmarkSeal1K(b *testing.B) {
+ benchmarkSealSize(b, 1024)
+}
+
+func BenchmarkSeal8K(b *testing.B) {
+ benchmarkSealSize(b, 8192)
+}
+
+func benchmarkOpenSize(b *testing.B, size int) {
+ msg := make([]byte, size)
+ result := make([]byte, size)
+ var nonce [24]byte
+ var key [32]byte
+ box := Seal(nil, msg, &nonce, &key)
+
+ b.SetBytes(int64(size))
+ b.ResetTimer()
+
+ for i := 0; i < b.N; i++ {
+ if _, ok := Open(result[:0], box, &nonce, &key); !ok {
+ panic("Open failed")
+ }
+ }
+}
+
+func BenchmarkOpen8Bytes(b *testing.B) {
+ benchmarkOpenSize(b, 8)
+}
+
+func BenchmarkOpen100Bytes(b *testing.B) {
+ benchmarkOpenSize(b, 100)
+}
+
+func BenchmarkOpen1K(b *testing.B) {
+ benchmarkOpenSize(b, 1024)
+}
+
+func BenchmarkOpen8K(b *testing.B) {
+ benchmarkOpenSize(b, 8192)
+}
diff --git a/vendor/golang.org/x/crypto/ocsp/ocsp.go b/vendor/golang.org/x/crypto/ocsp/ocsp.go
index 8ed8796..6bd347e 100644
--- a/vendor/golang.org/x/crypto/ocsp/ocsp.go
+++ b/vendor/golang.org/x/crypto/ocsp/ocsp.go
@@ -450,8 +450,8 @@ func ParseRequest(bytes []byte) (*Request, error) {
// then the signature over the response is checked. If issuer is not nil then
// it will be used to validate the signature or embedded certificate.
//
-// Invalid signatures or parse failures will result in a ParseError. Error
-// responses will result in a ResponseError.
+// Invalid responses and parse failures will result in a ParseError.
+// Error responses will result in a ResponseError.
func ParseResponse(bytes []byte, issuer *x509.Certificate) (*Response, error) {
return ParseResponseForCert(bytes, nil, issuer)
}
@@ -462,8 +462,8 @@ func ParseResponse(bytes []byte, issuer *x509.Certificate) (*Response, error) {
// issuer is not nil then it will be used to validate the signature or embedded
// certificate.
//
-// Invalid signatures or parse failures will result in a ParseError. Error
-// responses will result in a ResponseError.
+// Invalid responses and parse failures will result in a ParseError.
+// Error responses will result in a ResponseError.
func ParseResponseForCert(bytes []byte, cert, issuer *x509.Certificate) (*Response, error) {
var resp responseASN1
rest, err := asn1.Unmarshal(bytes, &resp)
@@ -496,10 +496,32 @@ func ParseResponseForCert(bytes []byte, cert, issuer *x509.Certificate) (*Respon
return nil, ParseError("OCSP response contains bad number of responses")
}
+ var singleResp singleResponse
+ if cert == nil {
+ singleResp = basicResp.TBSResponseData.Responses[0]
+ } else {
+ match := false
+ for _, resp := range basicResp.TBSResponseData.Responses {
+ if cert == nil || cert.SerialNumber.Cmp(resp.CertID.SerialNumber) == 0 {
+ singleResp = resp
+ match = true
+ break
+ }
+ }
+ if !match {
+ return nil, ParseError("no response matching the supplied certificate")
+ }
+ }
+
ret := &Response{
TBSResponseData: basicResp.TBSResponseData.Raw,
Signature: basicResp.Signature.RightAlign(),
SignatureAlgorithm: getSignatureAlgorithmFromOID(basicResp.SignatureAlgorithm.Algorithm),
+ Extensions: singleResp.SingleExtensions,
+ SerialNumber: singleResp.CertID.SerialNumber,
+ ProducedAt: basicResp.TBSResponseData.ProducedAt,
+ ThisUpdate: singleResp.ThisUpdate,
+ NextUpdate: singleResp.NextUpdate,
}
// Handle the ResponderID CHOICE tag. ResponderID can be flattened into
@@ -542,25 +564,14 @@ func ParseResponseForCert(bytes []byte, cert, issuer *x509.Certificate) (*Respon
}
}
- var r singleResponse
- for _, resp := range basicResp.TBSResponseData.Responses {
- if cert == nil || cert.SerialNumber.Cmp(resp.CertID.SerialNumber) == 0 {
- r = resp
- break
- }
- }
-
- for _, ext := range r.SingleExtensions {
+ for _, ext := range singleResp.SingleExtensions {
if ext.Critical {
return nil, ParseError("unsupported critical extension")
}
}
- ret.Extensions = r.SingleExtensions
-
- ret.SerialNumber = r.CertID.SerialNumber
for h, oid := range hashOIDs {
- if r.CertID.HashAlgorithm.Algorithm.Equal(oid) {
+ if singleResp.CertID.HashAlgorithm.Algorithm.Equal(oid) {
ret.IssuerHash = h
break
}
@@ -570,20 +581,16 @@ func ParseResponseForCert(bytes []byte, cert, issuer *x509.Certificate) (*Respon
}
switch {
- case bool(r.Good):
+ case bool(singleResp.Good):
ret.Status = Good
- case bool(r.Unknown):
+ case bool(singleResp.Unknown):
ret.Status = Unknown
default:
ret.Status = Revoked
- ret.RevokedAt = r.Revoked.RevocationTime
- ret.RevocationReason = int(r.Revoked.Reason)
+ ret.RevokedAt = singleResp.Revoked.RevocationTime
+ ret.RevocationReason = int(singleResp.Revoked.Reason)
}
- ret.ProducedAt = basicResp.TBSResponseData.ProducedAt
- ret.ThisUpdate = r.ThisUpdate
- ret.NextUpdate = r.NextUpdate
-
return ret, nil
}
diff --git a/vendor/golang.org/x/crypto/ocsp/ocsp_test.go b/vendor/golang.org/x/crypto/ocsp/ocsp_test.go
index a3c8986..df674b3 100644
--- a/vendor/golang.org/x/crypto/ocsp/ocsp_test.go
+++ b/vendor/golang.org/x/crypto/ocsp/ocsp_test.go
@@ -225,7 +225,6 @@ func TestOCSPResponse(t *testing.T) {
},
}
- producedAt := time.Now().Truncate(time.Minute)
thisUpdate := time.Date(2010, 7, 7, 15, 1, 5, 0, time.UTC)
nextUpdate := time.Date(2010, 7, 7, 18, 35, 17, 0, time.UTC)
template := Response{
@@ -284,8 +283,9 @@ func TestOCSPResponse(t *testing.T) {
t.Errorf("resp.Extensions: got %v, want %v", resp.Extensions, template.ExtraExtensions)
}
- if !resp.ProducedAt.Equal(producedAt) {
- t.Errorf("resp.ProducedAt: got %d, want %d", resp.ProducedAt, producedAt)
+ delay := time.Since(resp.ProducedAt)
+ if delay < -time.Hour || delay > time.Hour {
+ t.Errorf("resp.ProducedAt: got %s, want close to current time (%s)", resp.ProducedAt, time.Now())
}
if resp.Status != template.Status {
@@ -343,6 +343,21 @@ func TestOCSPDecodeMultiResponse(t *testing.T) {
}
}
+func TestOCSPDecodeMultiResponseWithoutMatchingCert(t *testing.T) {
+ wrongCert, _ := hex.DecodeString(startComHex)
+ cert, err := x509.ParseCertificate(wrongCert)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ responseBytes, _ := hex.DecodeString(ocspMultiResponseHex)
+ _, err = ParseResponseForCert(responseBytes, cert, nil)
+ want := ParseError("no response matching the supplied certificate")
+ if err != want {
+ t.Errorf("err: got %q, want %q", err, want)
+ }
+}
+
// This OCSP response was taken from Thawte's public OCSP responder.
// To recreate:
// $ openssl s_client -tls1 -showcerts -servername www.google.com -connect www.google.com:443
diff --git a/vendor/golang.org/x/crypto/pkcs12/pkcs12.go b/vendor/golang.org/x/crypto/pkcs12/pkcs12.go
index ad6341e..eff9ad3 100644
--- a/vendor/golang.org/x/crypto/pkcs12/pkcs12.go
+++ b/vendor/golang.org/x/crypto/pkcs12/pkcs12.go
@@ -109,6 +109,10 @@ func ToPEM(pfxData []byte, password string) ([]*pem.Block, error) {
bags, encodedPassword, err := getSafeContents(pfxData, encodedPassword)
+ if err != nil {
+ return nil, err
+ }
+
blocks := make([]*pem.Block, 0, len(bags))
for _, bag := range bags {
block, err := convertBag(&bag, encodedPassword)
diff --git a/vendor/golang.org/x/crypto/poly1305/poly1305_test.go b/vendor/golang.org/x/crypto/poly1305/poly1305_test.go
index 91b8e2b..017027f 100644
--- a/vendor/golang.org/x/crypto/poly1305/poly1305_test.go
+++ b/vendor/golang.org/x/crypto/poly1305/poly1305_test.go
@@ -6,10 +6,14 @@ package poly1305
import (
"bytes"
+ "encoding/hex"
+ "flag"
"testing"
"unsafe"
)
+var stressFlag = flag.Bool("stress", false, "run slow stress tests")
+
var testData = []struct {
in, k, correct []byte
}{
@@ -39,6 +43,36 @@ var testData = []struct {
[]byte{0x3b, 0x3a, 0x29, 0xe9, 0x3b, 0x21, 0x3a, 0x5c, 0x5c, 0x3b, 0x3b, 0x05, 0x3a, 0x3a, 0x8c, 0x0d},
[]byte{0x6d, 0xc1, 0x8b, 0x8c, 0x34, 0x4c, 0xd7, 0x99, 0x27, 0x11, 0x8b, 0xbe, 0x84, 0xb7, 0xf3, 0x14},
},
+ {
+ // This test generates a result of (2^130-1) % (2^130-5).
+ []byte{
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ },
+ []byte{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ []byte{4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ },
+ {
+ // This test generates a result of (2^130-6) % (2^130-5).
+ []byte{
+ 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ },
+ []byte{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ []byte{0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+ },
+ {
+ // This test generates a result of (2^130-5) % (2^130-5).
+ []byte{
+ 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ },
+ []byte{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ },
}
func testSum(t *testing.T, unaligned bool) {
@@ -58,6 +92,39 @@ func testSum(t *testing.T, unaligned bool) {
}
}
+func TestBurnin(t *testing.T) {
+ // This test can be used to sanity-check significant changes. It can
+ // take about many minutes to run, even on fast machines. It's disabled
+ // by default.
+ if !*stressFlag {
+ t.Skip("skipping without -stress")
+ }
+
+ var key [32]byte
+ var input [25]byte
+ var output [16]byte
+
+ for i := range key {
+ key[i] = 1
+ }
+ for i := range input {
+ input[i] = 2
+ }
+
+ for i := uint64(0); i < 1e10; i++ {
+ Sum(&output, input[:], &key)
+ copy(key[0:], output[:])
+ copy(key[16:], output[:])
+ copy(input[:], output[:])
+ copy(input[16:], output[:])
+ }
+
+ const expected = "5e3b866aea0b636d240c83c428f84bfa"
+ if got := hex.EncodeToString(output[:]); got != expected {
+ t.Errorf("expected %s, got %s", expected, got)
+ }
+}
+
func TestSum(t *testing.T) { testSum(t, false) }
func TestSumUnaligned(t *testing.T) { testSum(t, true) }
diff --git a/vendor/golang.org/x/crypto/poly1305/sum_ref.go b/vendor/golang.org/x/crypto/poly1305/sum_ref.go
index dbe50e7..b2805a5 100644
--- a/vendor/golang.org/x/crypto/poly1305/sum_ref.go
+++ b/vendor/golang.org/x/crypto/poly1305/sum_ref.go
@@ -6,1526 +6,136 @@
package poly1305
-// Based on original, public domain implementation from NaCl by D. J.
-// Bernstein.
+import "encoding/binary"
-import "math"
-
-const (
- alpham80 = 0.00000000558793544769287109375
- alpham48 = 24.0
- alpham16 = 103079215104.0
- alpha0 = 6755399441055744.0
- alpha18 = 1770887431076116955136.0
- alpha32 = 29014219670751100192948224.0
- alpha50 = 7605903601369376408980219232256.0
- alpha64 = 124615124604835863084731911901282304.0
- alpha82 = 32667107224410092492483962313449748299776.0
- alpha96 = 535217884764734955396857238543560676143529984.0
- alpha112 = 35076039295941670036888435985190792471742381031424.0
- alpha130 = 9194973245195333150150082162901855101712434733101613056.0
- scale = 0.0000000000000000000000000000000000000036734198463196484624023016788195177431833298649127735047148490821200539357960224151611328125
- offset0 = 6755408030990331.0
- offset1 = 29014256564239239022116864.0
- offset2 = 124615283061160854719918951570079744.0
- offset3 = 535219245894202480694386063513315216128475136.0
-)
-
-// Sum generates an authenticator for m using a one-time key and puts the
+// Sum generates an authenticator for msg using a one-time key and puts the
// 16-byte result into out. Authenticating two different messages with the same
// key allows an attacker to forge messages at will.
-func Sum(out *[16]byte, m []byte, key *[32]byte) {
- r := key
- s := key[16:]
+func Sum(out *[TagSize]byte, msg []byte, key *[32]byte) {
var (
- y7 float64
- y6 float64
- y1 float64
- y0 float64
- y5 float64
- y4 float64
- x7 float64
- x6 float64
- x1 float64
- x0 float64
- y3 float64
- y2 float64
- x5 float64
- r3lowx0 float64
- x4 float64
- r0lowx6 float64
- x3 float64
- r3highx0 float64
- x2 float64
- r0highx6 float64
- r0lowx0 float64
- sr1lowx6 float64
- r0highx0 float64
- sr1highx6 float64
- sr3low float64
- r1lowx0 float64
- sr2lowx6 float64
- r1highx0 float64
- sr2highx6 float64
- r2lowx0 float64
- sr3lowx6 float64
- r2highx0 float64
- sr3highx6 float64
- r1highx4 float64
- r1lowx4 float64
- r0highx4 float64
- r0lowx4 float64
- sr3highx4 float64
- sr3lowx4 float64
- sr2highx4 float64
- sr2lowx4 float64
- r0lowx2 float64
- r0highx2 float64
- r1lowx2 float64
- r1highx2 float64
- r2lowx2 float64
- r2highx2 float64
- sr3lowx2 float64
- sr3highx2 float64
- z0 float64
- z1 float64
- z2 float64
- z3 float64
- m0 int64
- m1 int64
- m2 int64
- m3 int64
- m00 uint32
- m01 uint32
- m02 uint32
- m03 uint32
- m10 uint32
- m11 uint32
- m12 uint32
- m13 uint32
- m20 uint32
- m21 uint32
- m22 uint32
- m23 uint32
- m30 uint32
- m31 uint32
- m32 uint32
- m33 uint64
- lbelow2 int32
- lbelow3 int32
- lbelow4 int32
- lbelow5 int32
- lbelow6 int32
- lbelow7 int32
- lbelow8 int32
- lbelow9 int32
- lbelow10 int32
- lbelow11 int32
- lbelow12 int32
- lbelow13 int32
- lbelow14 int32
- lbelow15 int32
- s00 uint32
- s01 uint32
- s02 uint32
- s03 uint32
- s10 uint32
- s11 uint32
- s12 uint32
- s13 uint32
- s20 uint32
- s21 uint32
- s22 uint32
- s23 uint32
- s30 uint32
- s31 uint32
- s32 uint32
- s33 uint32
- bits32 uint64
- f uint64
- f0 uint64
- f1 uint64
- f2 uint64
- f3 uint64
- f4 uint64
- g uint64
- g0 uint64
- g1 uint64
- g2 uint64
- g3 uint64
- g4 uint64
+ h0, h1, h2, h3, h4 uint32 // the hash accumulators
+ r0, r1, r2, r3, r4 uint64 // the r part of the key
)
- var p int32
+ r0 = uint64(binary.LittleEndian.Uint32(key[0:]) & 0x3ffffff)
+ r1 = uint64((binary.LittleEndian.Uint32(key[3:]) >> 2) & 0x3ffff03)
+ r2 = uint64((binary.LittleEndian.Uint32(key[6:]) >> 4) & 0x3ffc0ff)
+ r3 = uint64((binary.LittleEndian.Uint32(key[9:]) >> 6) & 0x3f03fff)
+ r4 = uint64((binary.LittleEndian.Uint32(key[12:]) >> 8) & 0x00fffff)
- l := int32(len(m))
+ R1, R2, R3, R4 := r1*5, r2*5, r3*5, r4*5
- r00 := uint32(r[0])
+ for len(msg) >= TagSize {
+ // h += msg
+ h0 += binary.LittleEndian.Uint32(msg[0:]) & 0x3ffffff
+ h1 += (binary.LittleEndian.Uint32(msg[3:]) >> 2) & 0x3ffffff
+ h2 += (binary.LittleEndian.Uint32(msg[6:]) >> 4) & 0x3ffffff
+ h3 += (binary.LittleEndian.Uint32(msg[9:]) >> 6) & 0x3ffffff
+ h4 += (binary.LittleEndian.Uint32(msg[12:]) >> 8) | (1 << 24)
- r01 := uint32(r[1])
+ // h *= r
+ d0 := (uint64(h0) * r0) + (uint64(h1) * R4) + (uint64(h2) * R3) + (uint64(h3) * R2) + (uint64(h4) * R1)
+ d1 := (d0 >> 26) + (uint64(h0) * r1) + (uint64(h1) * r0) + (uint64(h2) * R4) + (uint64(h3) * R3) + (uint64(h4) * R2)
+ d2 := (d1 >> 26) + (uint64(h0) * r2) + (uint64(h1) * r1) + (uint64(h2) * r0) + (uint64(h3) * R4) + (uint64(h4) * R3)
+ d3 := (d2 >> 26) + (uint64(h0) * r3) + (uint64(h1) * r2) + (uint64(h2) * r1) + (uint64(h3) * r0) + (uint64(h4) * R4)
+ d4 := (d3 >> 26) + (uint64(h0) * r4) + (uint64(h1) * r3) + (uint64(h2) * r2) + (uint64(h3) * r1) + (uint64(h4) * r0)
- r02 := uint32(r[2])
- r0 := int64(2151)
+ // h %= p
+ h0 = uint32(d0) & 0x3ffffff
+ h1 = uint32(d1) & 0x3ffffff
+ h2 = uint32(d2) & 0x3ffffff
+ h3 = uint32(d3) & 0x3ffffff
+ h4 = uint32(d4) & 0x3ffffff
- r03 := uint32(r[3])
- r03 &= 15
- r0 <<= 51
+ h0 += uint32(d4>>26) * 5
+ h1 += h0 >> 26
+ h0 = h0 & 0x3ffffff
- r10 := uint32(r[4])
- r10 &= 252
- r01 <<= 8
- r0 += int64(r00)
-
- r11 := uint32(r[5])
- r02 <<= 16
- r0 += int64(r01)
-
- r12 := uint32(r[6])
- r03 <<= 24
- r0 += int64(r02)
-
- r13 := uint32(r[7])
- r13 &= 15
- r1 := int64(2215)
- r0 += int64(r03)
-
- d0 := r0
- r1 <<= 51
- r2 := int64(2279)
-
- r20 := uint32(r[8])
- r20 &= 252
- r11 <<= 8
- r1 += int64(r10)
-
- r21 := uint32(r[9])
- r12 <<= 16
- r1 += int64(r11)
-
- r22 := uint32(r[10])
- r13 <<= 24
- r1 += int64(r12)
-
- r23 := uint32(r[11])
- r23 &= 15
- r2 <<= 51
- r1 += int64(r13)
-
- d1 := r1
- r21 <<= 8
- r2 += int64(r20)
-
- r30 := uint32(r[12])
- r30 &= 252
- r22 <<= 16
- r2 += int64(r21)
-
- r31 := uint32(r[13])
- r23 <<= 24
- r2 += int64(r22)
-
- r32 := uint32(r[14])
- r2 += int64(r23)
- r3 := int64(2343)
-
- d2 := r2
- r3 <<= 51
-
- r33 := uint32(r[15])
- r33 &= 15
- r31 <<= 8
- r3 += int64(r30)
-
- r32 <<= 16
- r3 += int64(r31)
-
- r33 <<= 24
- r3 += int64(r32)
-
- r3 += int64(r33)
- h0 := alpha32 - alpha32
-
- d3 := r3
- h1 := alpha32 - alpha32
-
- h2 := alpha32 - alpha32
-
- h3 := alpha32 - alpha32
-
- h4 := alpha32 - alpha32
-
- r0low := math.Float64frombits(uint64(d0))
- h5 := alpha32 - alpha32
-
- r1low := math.Float64frombits(uint64(d1))
- h6 := alpha32 - alpha32
-
- r2low := math.Float64frombits(uint64(d2))
- h7 := alpha32 - alpha32
-
- r0low -= alpha0
-
- r1low -= alpha32
-
- r2low -= alpha64
-
- r0high := r0low + alpha18
-
- r3low := math.Float64frombits(uint64(d3))
-
- r1high := r1low + alpha50
- sr1low := scale * r1low
-
- r2high := r2low + alpha82
- sr2low := scale * r2low
-
- r0high -= alpha18
- r0high_stack := r0high
-
- r3low -= alpha96
-
- r1high -= alpha50
- r1high_stack := r1high
-
- sr1high := sr1low + alpham80
-
- r0low -= r0high
-
- r2high -= alpha82
- sr3low = scale * r3low
-
- sr2high := sr2low + alpham48
-
- r1low -= r1high
- r1low_stack := r1low
-
- sr1high -= alpham80
- sr1high_stack := sr1high
-
- r2low -= r2high
- r2low_stack := r2low
-
- sr2high -= alpham48
- sr2high_stack := sr2high
-
- r3high := r3low + alpha112
- r0low_stack := r0low
-
- sr1low -= sr1high
- sr1low_stack := sr1low
-
- sr3high := sr3low + alpham16
- r2high_stack := r2high
-
- sr2low -= sr2high
- sr2low_stack := sr2low
-
- r3high -= alpha112
- r3high_stack := r3high
-
- sr3high -= alpham16
- sr3high_stack := sr3high
-
- r3low -= r3high
- r3low_stack := r3low
-
- sr3low -= sr3high
- sr3low_stack := sr3low
-
- if l < 16 {
- goto addatmost15bytes
+ msg = msg[TagSize:]
}
- m00 = uint32(m[p+0])
- m0 = 2151
+ if len(msg) > 0 {
+ var block [TagSize]byte
+ off := copy(block[:], msg)
+ block[off] = 0x01
- m0 <<= 51
- m1 = 2215
- m01 = uint32(m[p+1])
+ // h += msg
+ h0 += binary.LittleEndian.Uint32(block[0:]) & 0x3ffffff
+ h1 += (binary.LittleEndian.Uint32(block[3:]) >> 2) & 0x3ffffff
+ h2 += (binary.LittleEndian.Uint32(block[6:]) >> 4) & 0x3ffffff
+ h3 += (binary.LittleEndian.Uint32(block[9:]) >> 6) & 0x3ffffff
+ h4 += (binary.LittleEndian.Uint32(block[12:]) >> 8)
- m1 <<= 51
- m2 = 2279
- m02 = uint32(m[p+2])
+ // h *= r
+ d0 := (uint64(h0) * r0) + (uint64(h1) * R4) + (uint64(h2) * R3) + (uint64(h3) * R2) + (uint64(h4) * R1)
+ d1 := (d0 >> 26) + (uint64(h0) * r1) + (uint64(h1) * r0) + (uint64(h2) * R4) + (uint64(h3) * R3) + (uint64(h4) * R2)
+ d2 := (d1 >> 26) + (uint64(h0) * r2) + (uint64(h1) * r1) + (uint64(h2) * r0) + (uint64(h3) * R4) + (uint64(h4) * R3)
+ d3 := (d2 >> 26) + (uint64(h0) * r3) + (uint64(h1) * r2) + (uint64(h2) * r1) + (uint64(h3) * r0) + (uint64(h4) * R4)
+ d4 := (d3 >> 26) + (uint64(h0) * r4) + (uint64(h1) * r3) + (uint64(h2) * r2) + (uint64(h3) * r1) + (uint64(h4) * r0)
- m2 <<= 51
- m3 = 2343
- m03 = uint32(m[p+3])
+ // h %= p
+ h0 = uint32(d0) & 0x3ffffff
+ h1 = uint32(d1) & 0x3ffffff
+ h2 = uint32(d2) & 0x3ffffff
+ h3 = uint32(d3) & 0x3ffffff
+ h4 = uint32(d4) & 0x3ffffff
- m10 = uint32(m[p+4])
- m01 <<= 8
- m0 += int64(m00)
-
- m11 = uint32(m[p+5])
- m02 <<= 16
- m0 += int64(m01)
-
- m12 = uint32(m[p+6])
- m03 <<= 24
- m0 += int64(m02)
-
- m13 = uint32(m[p+7])
- m3 <<= 51
- m0 += int64(m03)
-
- m20 = uint32(m[p+8])
- m11 <<= 8
- m1 += int64(m10)
-
- m21 = uint32(m[p+9])
- m12 <<= 16
- m1 += int64(m11)
-
- m22 = uint32(m[p+10])
- m13 <<= 24
- m1 += int64(m12)
-
- m23 = uint32(m[p+11])
- m1 += int64(m13)
-
- m30 = uint32(m[p+12])
- m21 <<= 8
- m2 += int64(m20)
-
- m31 = uint32(m[p+13])
- m22 <<= 16
- m2 += int64(m21)
-
- m32 = uint32(m[p+14])
- m23 <<= 24
- m2 += int64(m22)
-
- m33 = uint64(m[p+15])
- m2 += int64(m23)
-
- d0 = m0
- m31 <<= 8
- m3 += int64(m30)
-
- d1 = m1
- m32 <<= 16
- m3 += int64(m31)
-
- d2 = m2
- m33 += 256
-
- m33 <<= 24
- m3 += int64(m32)
-
- m3 += int64(m33)
- d3 = m3
-
- p += 16
- l -= 16
-
- z0 = math.Float64frombits(uint64(d0))
-
- z1 = math.Float64frombits(uint64(d1))
-
- z2 = math.Float64frombits(uint64(d2))
-
- z3 = math.Float64frombits(uint64(d3))
-
- z0 -= alpha0
-
- z1 -= alpha32
-
- z2 -= alpha64
-
- z3 -= alpha96
-
- h0 += z0
-
- h1 += z1
-
- h3 += z2
-
- h5 += z3
-
- if l < 16 {
- goto multiplyaddatmost15bytes
+ h0 += uint32(d4>>26) * 5
+ h1 += h0 >> 26
+ h0 = h0 & 0x3ffffff
}
-multiplyaddatleast16bytes:
-
- m2 = 2279
- m20 = uint32(m[p+8])
- y7 = h7 + alpha130
-
- m2 <<= 51
- m3 = 2343
- m21 = uint32(m[p+9])
- y6 = h6 + alpha130
-
- m3 <<= 51
- m0 = 2151
- m22 = uint32(m[p+10])
- y1 = h1 + alpha32
-
- m0 <<= 51
- m1 = 2215
- m23 = uint32(m[p+11])
- y0 = h0 + alpha32
-
- m1 <<= 51
- m30 = uint32(m[p+12])
- y7 -= alpha130
-
- m21 <<= 8
- m2 += int64(m20)
- m31 = uint32(m[p+13])
- y6 -= alpha130
-
- m22 <<= 16
- m2 += int64(m21)
- m32 = uint32(m[p+14])
- y1 -= alpha32
-
- m23 <<= 24
- m2 += int64(m22)
- m33 = uint64(m[p+15])
- y0 -= alpha32
-
- m2 += int64(m23)
- m00 = uint32(m[p+0])
- y5 = h5 + alpha96
-
- m31 <<= 8
- m3 += int64(m30)
- m01 = uint32(m[p+1])
- y4 = h4 + alpha96
-
- m32 <<= 16
- m02 = uint32(m[p+2])
- x7 = h7 - y7
- y7 *= scale
-
- m33 += 256
- m03 = uint32(m[p+3])
- x6 = h6 - y6
- y6 *= scale
-
- m33 <<= 24
- m3 += int64(m31)
- m10 = uint32(m[p+4])
- x1 = h1 - y1
-
- m01 <<= 8
- m3 += int64(m32)
- m11 = uint32(m[p+5])
- x0 = h0 - y0
-
- m3 += int64(m33)
- m0 += int64(m00)
- m12 = uint32(m[p+6])
- y5 -= alpha96
-
- m02 <<= 16
- m0 += int64(m01)
- m13 = uint32(m[p+7])
- y4 -= alpha96
-
- m03 <<= 24
- m0 += int64(m02)
- d2 = m2
- x1 += y7
-
- m0 += int64(m03)
- d3 = m3
- x0 += y6
-
- m11 <<= 8
- m1 += int64(m10)
- d0 = m0
- x7 += y5
-
- m12 <<= 16
- m1 += int64(m11)
- x6 += y4
-
- m13 <<= 24
- m1 += int64(m12)
- y3 = h3 + alpha64
-
- m1 += int64(m13)
- d1 = m1
- y2 = h2 + alpha64
-
- x0 += x1
-
- x6 += x7
-
- y3 -= alpha64
- r3low = r3low_stack
-
- y2 -= alpha64
- r0low = r0low_stack
-
- x5 = h5 - y5
- r3lowx0 = r3low * x0
- r3high = r3high_stack
-
- x4 = h4 - y4
- r0lowx6 = r0low * x6
- r0high = r0high_stack
-
- x3 = h3 - y3
- r3highx0 = r3high * x0
- sr1low = sr1low_stack
-
- x2 = h2 - y2
- r0highx6 = r0high * x6
- sr1high = sr1high_stack
-
- x5 += y3
- r0lowx0 = r0low * x0
- r1low = r1low_stack
-
- h6 = r3lowx0 + r0lowx6
- sr1lowx6 = sr1low * x6
- r1high = r1high_stack
-
- x4 += y2
- r0highx0 = r0high * x0
- sr2low = sr2low_stack
-
- h7 = r3highx0 + r0highx6
- sr1highx6 = sr1high * x6
- sr2high = sr2high_stack
-
- x3 += y1
- r1lowx0 = r1low * x0
- r2low = r2low_stack
-
- h0 = r0lowx0 + sr1lowx6
- sr2lowx6 = sr2low * x6
- r2high = r2high_stack
-
- x2 += y0
- r1highx0 = r1high * x0
- sr3low = sr3low_stack
-
- h1 = r0highx0 + sr1highx6
- sr2highx6 = sr2high * x6
- sr3high = sr3high_stack
-
- x4 += x5
- r2lowx0 = r2low * x0
- z2 = math.Float64frombits(uint64(d2))
-
- h2 = r1lowx0 + sr2lowx6
- sr3lowx6 = sr3low * x6
-
- x2 += x3
- r2highx0 = r2high * x0
- z3 = math.Float64frombits(uint64(d3))
-
- h3 = r1highx0 + sr2highx6
- sr3highx6 = sr3high * x6
-
- r1highx4 = r1high * x4
- z2 -= alpha64
-
- h4 = r2lowx0 + sr3lowx6
- r1lowx4 = r1low * x4
-
- r0highx4 = r0high * x4
- z3 -= alpha96
-
- h5 = r2highx0 + sr3highx6
- r0lowx4 = r0low * x4
-
- h7 += r1highx4
- sr3highx4 = sr3high * x4
-
- h6 += r1lowx4
- sr3lowx4 = sr3low * x4
-
- h5 += r0highx4
- sr2highx4 = sr2high * x4
-
- h4 += r0lowx4
- sr2lowx4 = sr2low * x4
-
- h3 += sr3highx4
- r0lowx2 = r0low * x2
-
- h2 += sr3lowx4
- r0highx2 = r0high * x2
-
- h1 += sr2highx4
- r1lowx2 = r1low * x2
-
- h0 += sr2lowx4
- r1highx2 = r1high * x2
-
- h2 += r0lowx2
- r2lowx2 = r2low * x2
-
- h3 += r0highx2
- r2highx2 = r2high * x2
-
- h4 += r1lowx2
- sr3lowx2 = sr3low * x2
-
- h5 += r1highx2
- sr3highx2 = sr3high * x2
-
- p += 16
- l -= 16
- h6 += r2lowx2
-
- h7 += r2highx2
-
- z1 = math.Float64frombits(uint64(d1))
- h0 += sr3lowx2
-
- z0 = math.Float64frombits(uint64(d0))
- h1 += sr3highx2
-
- z1 -= alpha32
-
- z0 -= alpha0
-
- h5 += z3
-
- h3 += z2
-
- h1 += z1
-
- h0 += z0
-
- if l >= 16 {
- goto multiplyaddatleast16bytes
- }
-
-multiplyaddatmost15bytes:
-
- y7 = h7 + alpha130
-
- y6 = h6 + alpha130
-
- y1 = h1 + alpha32
-
- y0 = h0 + alpha32
-
- y7 -= alpha130
-
- y6 -= alpha130
-
- y1 -= alpha32
-
- y0 -= alpha32
-
- y5 = h5 + alpha96
-
- y4 = h4 + alpha96
-
- x7 = h7 - y7
- y7 *= scale
-
- x6 = h6 - y6
- y6 *= scale
-
- x1 = h1 - y1
-
- x0 = h0 - y0
-
- y5 -= alpha96
-
- y4 -= alpha96
-
- x1 += y7
-
- x0 += y6
-
- x7 += y5
-
- x6 += y4
-
- y3 = h3 + alpha64
-
- y2 = h2 + alpha64
-
- x0 += x1
-
- x6 += x7
-
- y3 -= alpha64
- r3low = r3low_stack
-
- y2 -= alpha64
- r0low = r0low_stack
-
- x5 = h5 - y5
- r3lowx0 = r3low * x0
- r3high = r3high_stack
-
- x4 = h4 - y4
- r0lowx6 = r0low * x6
- r0high = r0high_stack
-
- x3 = h3 - y3
- r3highx0 = r3high * x0
- sr1low = sr1low_stack
-
- x2 = h2 - y2
- r0highx6 = r0high * x6
- sr1high = sr1high_stack
-
- x5 += y3
- r0lowx0 = r0low * x0
- r1low = r1low_stack
-
- h6 = r3lowx0 + r0lowx6
- sr1lowx6 = sr1low * x6
- r1high = r1high_stack
-
- x4 += y2
- r0highx0 = r0high * x0
- sr2low = sr2low_stack
-
- h7 = r3highx0 + r0highx6
- sr1highx6 = sr1high * x6
- sr2high = sr2high_stack
-
- x3 += y1
- r1lowx0 = r1low * x0
- r2low = r2low_stack
-
- h0 = r0lowx0 + sr1lowx6
- sr2lowx6 = sr2low * x6
- r2high = r2high_stack
-
- x2 += y0
- r1highx0 = r1high * x0
- sr3low = sr3low_stack
-
- h1 = r0highx0 + sr1highx6
- sr2highx6 = sr2high * x6
- sr3high = sr3high_stack
-
- x4 += x5
- r2lowx0 = r2low * x0
-
- h2 = r1lowx0 + sr2lowx6
- sr3lowx6 = sr3low * x6
-
- x2 += x3
- r2highx0 = r2high * x0
-
- h3 = r1highx0 + sr2highx6
- sr3highx6 = sr3high * x6
-
- r1highx4 = r1high * x4
-
- h4 = r2lowx0 + sr3lowx6
- r1lowx4 = r1low * x4
-
- r0highx4 = r0high * x4
-
- h5 = r2highx0 + sr3highx6
- r0lowx4 = r0low * x4
-
- h7 += r1highx4
- sr3highx4 = sr3high * x4
-
- h6 += r1lowx4
- sr3lowx4 = sr3low * x4
-
- h5 += r0highx4
- sr2highx4 = sr2high * x4
-
- h4 += r0lowx4
- sr2lowx4 = sr2low * x4
-
- h3 += sr3highx4
- r0lowx2 = r0low * x2
-
- h2 += sr3lowx4
- r0highx2 = r0high * x2
-
- h1 += sr2highx4
- r1lowx2 = r1low * x2
-
- h0 += sr2lowx4
- r1highx2 = r1high * x2
-
- h2 += r0lowx2
- r2lowx2 = r2low * x2
-
- h3 += r0highx2
- r2highx2 = r2high * x2
-
- h4 += r1lowx2
- sr3lowx2 = sr3low * x2
-
- h5 += r1highx2
- sr3highx2 = sr3high * x2
-
- h6 += r2lowx2
-
- h7 += r2highx2
-
- h0 += sr3lowx2
-
- h1 += sr3highx2
-
-addatmost15bytes:
-
- if l == 0 {
- goto nomorebytes
- }
-
- lbelow2 = l - 2
-
- lbelow3 = l - 3
-
- lbelow2 >>= 31
- lbelow4 = l - 4
-
- m00 = uint32(m[p+0])
- lbelow3 >>= 31
- p += lbelow2
-
- m01 = uint32(m[p+1])
- lbelow4 >>= 31
- p += lbelow3
-
- m02 = uint32(m[p+2])
- p += lbelow4
- m0 = 2151
-
- m03 = uint32(m[p+3])
- m0 <<= 51
- m1 = 2215
-
- m0 += int64(m00)
- m01 &^= uint32(lbelow2)
-
- m02 &^= uint32(lbelow3)
- m01 -= uint32(lbelow2)
-
- m01 <<= 8
- m03 &^= uint32(lbelow4)
-
- m0 += int64(m01)
- lbelow2 -= lbelow3
-
- m02 += uint32(lbelow2)
- lbelow3 -= lbelow4
-
- m02 <<= 16
- m03 += uint32(lbelow3)
-
- m03 <<= 24
- m0 += int64(m02)
-
- m0 += int64(m03)
- lbelow5 = l - 5
-
- lbelow6 = l - 6
- lbelow7 = l - 7
-
- lbelow5 >>= 31
- lbelow8 = l - 8
-
- lbelow6 >>= 31
- p += lbelow5
-
- m10 = uint32(m[p+4])
- lbelow7 >>= 31
- p += lbelow6
-
- m11 = uint32(m[p+5])
- lbelow8 >>= 31
- p += lbelow7
-
- m12 = uint32(m[p+6])
- m1 <<= 51
- p += lbelow8
-
- m13 = uint32(m[p+7])
- m10 &^= uint32(lbelow5)
- lbelow4 -= lbelow5
-
- m10 += uint32(lbelow4)
- lbelow5 -= lbelow6
-
- m11 &^= uint32(lbelow6)
- m11 += uint32(lbelow5)
-
- m11 <<= 8
- m1 += int64(m10)
-
- m1 += int64(m11)
- m12 &^= uint32(lbelow7)
-
- lbelow6 -= lbelow7
- m13 &^= uint32(lbelow8)
-
- m12 += uint32(lbelow6)
- lbelow7 -= lbelow8
-
- m12 <<= 16
- m13 += uint32(lbelow7)
-
- m13 <<= 24
- m1 += int64(m12)
-
- m1 += int64(m13)
- m2 = 2279
-
- lbelow9 = l - 9
- m3 = 2343
-
- lbelow10 = l - 10
- lbelow11 = l - 11
-
- lbelow9 >>= 31
- lbelow12 = l - 12
-
- lbelow10 >>= 31
- p += lbelow9
-
- m20 = uint32(m[p+8])
- lbelow11 >>= 31
- p += lbelow10
-
- m21 = uint32(m[p+9])
- lbelow12 >>= 31
- p += lbelow11
-
- m22 = uint32(m[p+10])
- m2 <<= 51
- p += lbelow12
-
- m23 = uint32(m[p+11])
- m20 &^= uint32(lbelow9)
- lbelow8 -= lbelow9
-
- m20 += uint32(lbelow8)
- lbelow9 -= lbelow10
-
- m21 &^= uint32(lbelow10)
- m21 += uint32(lbelow9)
-
- m21 <<= 8
- m2 += int64(m20)
-
- m2 += int64(m21)
- m22 &^= uint32(lbelow11)
-
- lbelow10 -= lbelow11
- m23 &^= uint32(lbelow12)
-
- m22 += uint32(lbelow10)
- lbelow11 -= lbelow12
-
- m22 <<= 16
- m23 += uint32(lbelow11)
-
- m23 <<= 24
- m2 += int64(m22)
-
- m3 <<= 51
- lbelow13 = l - 13
-
- lbelow13 >>= 31
- lbelow14 = l - 14
-
- lbelow14 >>= 31
- p += lbelow13
- lbelow15 = l - 15
-
- m30 = uint32(m[p+12])
- lbelow15 >>= 31
- p += lbelow14
-
- m31 = uint32(m[p+13])
- p += lbelow15
- m2 += int64(m23)
-
- m32 = uint32(m[p+14])
- m30 &^= uint32(lbelow13)
- lbelow12 -= lbelow13
-
- m30 += uint32(lbelow12)
- lbelow13 -= lbelow14
-
- m3 += int64(m30)
- m31 &^= uint32(lbelow14)
-
- m31 += uint32(lbelow13)
- m32 &^= uint32(lbelow15)
-
- m31 <<= 8
- lbelow14 -= lbelow15
-
- m3 += int64(m31)
- m32 += uint32(lbelow14)
- d0 = m0
-
- m32 <<= 16
- m33 = uint64(lbelow15 + 1)
- d1 = m1
-
- m33 <<= 24
- m3 += int64(m32)
- d2 = m2
-
- m3 += int64(m33)
- d3 = m3
-
- z3 = math.Float64frombits(uint64(d3))
-
- z2 = math.Float64frombits(uint64(d2))
-
- z1 = math.Float64frombits(uint64(d1))
-
- z0 = math.Float64frombits(uint64(d0))
-
- z3 -= alpha96
-
- z2 -= alpha64
-
- z1 -= alpha32
-
- z0 -= alpha0
-
- h5 += z3
-
- h3 += z2
-
- h1 += z1
-
- h0 += z0
-
- y7 = h7 + alpha130
-
- y6 = h6 + alpha130
-
- y1 = h1 + alpha32
-
- y0 = h0 + alpha32
-
- y7 -= alpha130
-
- y6 -= alpha130
-
- y1 -= alpha32
-
- y0 -= alpha32
-
- y5 = h5 + alpha96
-
- y4 = h4 + alpha96
-
- x7 = h7 - y7
- y7 *= scale
-
- x6 = h6 - y6
- y6 *= scale
-
- x1 = h1 - y1
-
- x0 = h0 - y0
-
- y5 -= alpha96
-
- y4 -= alpha96
-
- x1 += y7
-
- x0 += y6
-
- x7 += y5
-
- x6 += y4
-
- y3 = h3 + alpha64
-
- y2 = h2 + alpha64
-
- x0 += x1
-
- x6 += x7
-
- y3 -= alpha64
- r3low = r3low_stack
-
- y2 -= alpha64
- r0low = r0low_stack
-
- x5 = h5 - y5
- r3lowx0 = r3low * x0
- r3high = r3high_stack
-
- x4 = h4 - y4
- r0lowx6 = r0low * x6
- r0high = r0high_stack
-
- x3 = h3 - y3
- r3highx0 = r3high * x0
- sr1low = sr1low_stack
-
- x2 = h2 - y2
- r0highx6 = r0high * x6
- sr1high = sr1high_stack
-
- x5 += y3
- r0lowx0 = r0low * x0
- r1low = r1low_stack
-
- h6 = r3lowx0 + r0lowx6
- sr1lowx6 = sr1low * x6
- r1high = r1high_stack
-
- x4 += y2
- r0highx0 = r0high * x0
- sr2low = sr2low_stack
-
- h7 = r3highx0 + r0highx6
- sr1highx6 = sr1high * x6
- sr2high = sr2high_stack
-
- x3 += y1
- r1lowx0 = r1low * x0
- r2low = r2low_stack
-
- h0 = r0lowx0 + sr1lowx6
- sr2lowx6 = sr2low * x6
- r2high = r2high_stack
-
- x2 += y0
- r1highx0 = r1high * x0
- sr3low = sr3low_stack
-
- h1 = r0highx0 + sr1highx6
- sr2highx6 = sr2high * x6
- sr3high = sr3high_stack
-
- x4 += x5
- r2lowx0 = r2low * x0
-
- h2 = r1lowx0 + sr2lowx6
- sr3lowx6 = sr3low * x6
-
- x2 += x3
- r2highx0 = r2high * x0
-
- h3 = r1highx0 + sr2highx6
- sr3highx6 = sr3high * x6
-
- r1highx4 = r1high * x4
-
- h4 = r2lowx0 + sr3lowx6
- r1lowx4 = r1low * x4
-
- r0highx4 = r0high * x4
-
- h5 = r2highx0 + sr3highx6
- r0lowx4 = r0low * x4
-
- h7 += r1highx4
- sr3highx4 = sr3high * x4
-
- h6 += r1lowx4
- sr3lowx4 = sr3low * x4
-
- h5 += r0highx4
- sr2highx4 = sr2high * x4
-
- h4 += r0lowx4
- sr2lowx4 = sr2low * x4
-
- h3 += sr3highx4
- r0lowx2 = r0low * x2
-
- h2 += sr3lowx4
- r0highx2 = r0high * x2
-
- h1 += sr2highx4
- r1lowx2 = r1low * x2
-
- h0 += sr2lowx4
- r1highx2 = r1high * x2
-
- h2 += r0lowx2
- r2lowx2 = r2low * x2
-
- h3 += r0highx2
- r2highx2 = r2high * x2
-
- h4 += r1lowx2
- sr3lowx2 = sr3low * x2
-
- h5 += r1highx2
- sr3highx2 = sr3high * x2
-
- h6 += r2lowx2
-
- h7 += r2highx2
-
- h0 += sr3lowx2
-
- h1 += sr3highx2
-
-nomorebytes:
-
- y7 = h7 + alpha130
-
- y0 = h0 + alpha32
-
- y1 = h1 + alpha32
-
- y2 = h2 + alpha64
-
- y7 -= alpha130
-
- y3 = h3 + alpha64
-
- y4 = h4 + alpha96
-
- y5 = h5 + alpha96
-
- x7 = h7 - y7
- y7 *= scale
-
- y0 -= alpha32
-
- y1 -= alpha32
-
- y2 -= alpha64
-
- h6 += x7
-
- y3 -= alpha64
-
- y4 -= alpha96
-
- y5 -= alpha96
-
- y6 = h6 + alpha130
-
- x0 = h0 - y0
-
- x1 = h1 - y1
-
- x2 = h2 - y2
-
- y6 -= alpha130
-
- x0 += y7
-
- x3 = h3 - y3
-
- x4 = h4 - y4
-
- x5 = h5 - y5
-
- x6 = h6 - y6
-
- y6 *= scale
-
- x2 += y0
-
- x3 += y1
-
- x4 += y2
-
- x0 += y6
-
- x5 += y3
-
- x6 += y4
-
- x2 += x3
-
- x0 += x1
-
- x4 += x5
-
- x6 += y5
-
- x2 += offset1
- d1 = int64(math.Float64bits(x2))
-
- x0 += offset0
- d0 = int64(math.Float64bits(x0))
-
- x4 += offset2
- d2 = int64(math.Float64bits(x4))
-
- x6 += offset3
- d3 = int64(math.Float64bits(x6))
-
- f0 = uint64(d0)
-
- f1 = uint64(d1)
- bits32 = math.MaxUint64
-
- f2 = uint64(d2)
- bits32 >>= 32
-
- f3 = uint64(d3)
- f = f0 >> 32
-
- f0 &= bits32
- f &= 255
-
- f1 += f
- g0 = f0 + 5
-
- g = g0 >> 32
- g0 &= bits32
-
- f = f1 >> 32
- f1 &= bits32
-
- f &= 255
- g1 = f1 + g
-
- g = g1 >> 32
- f2 += f
-
- f = f2 >> 32
- g1 &= bits32
-
- f2 &= bits32
- f &= 255
-
- f3 += f
- g2 = f2 + g
-
- g = g2 >> 32
- g2 &= bits32
-
- f4 = f3 >> 32
- f3 &= bits32
-
- f4 &= 255
- g3 = f3 + g
-
- g = g3 >> 32
- g3 &= bits32
-
- g4 = f4 + g
-
- g4 = g4 - 4
- s00 = uint32(s[0])
-
- f = uint64(int64(g4) >> 63)
- s01 = uint32(s[1])
-
- f0 &= f
- g0 &^= f
- s02 = uint32(s[2])
-
- f1 &= f
- f0 |= g0
- s03 = uint32(s[3])
-
- g1 &^= f
- f2 &= f
- s10 = uint32(s[4])
-
- f3 &= f
- g2 &^= f
- s11 = uint32(s[5])
-
- g3 &^= f
- f1 |= g1
- s12 = uint32(s[6])
-
- f2 |= g2
- f3 |= g3
- s13 = uint32(s[7])
-
- s01 <<= 8
- f0 += uint64(s00)
- s20 = uint32(s[8])
-
- s02 <<= 16
- f0 += uint64(s01)
- s21 = uint32(s[9])
-
- s03 <<= 24
- f0 += uint64(s02)
- s22 = uint32(s[10])
-
- s11 <<= 8
- f1 += uint64(s10)
- s23 = uint32(s[11])
-
- s12 <<= 16
- f1 += uint64(s11)
- s30 = uint32(s[12])
-
- s13 <<= 24
- f1 += uint64(s12)
- s31 = uint32(s[13])
-
- f0 += uint64(s03)
- f1 += uint64(s13)
- s32 = uint32(s[14])
-
- s21 <<= 8
- f2 += uint64(s20)
- s33 = uint32(s[15])
-
- s22 <<= 16
- f2 += uint64(s21)
-
- s23 <<= 24
- f2 += uint64(s22)
-
- s31 <<= 8
- f3 += uint64(s30)
-
- s32 <<= 16
- f3 += uint64(s31)
-
- s33 <<= 24
- f3 += uint64(s32)
-
- f2 += uint64(s23)
- f3 += uint64(s33)
-
- out[0] = byte(f0)
- f0 >>= 8
- out[1] = byte(f0)
- f0 >>= 8
- out[2] = byte(f0)
- f0 >>= 8
- out[3] = byte(f0)
- f0 >>= 8
- f1 += f0
-
- out[4] = byte(f1)
- f1 >>= 8
- out[5] = byte(f1)
- f1 >>= 8
- out[6] = byte(f1)
- f1 >>= 8
- out[7] = byte(f1)
- f1 >>= 8
- f2 += f1
-
- out[8] = byte(f2)
- f2 >>= 8
- out[9] = byte(f2)
- f2 >>= 8
- out[10] = byte(f2)
- f2 >>= 8
- out[11] = byte(f2)
- f2 >>= 8
- f3 += f2
-
- out[12] = byte(f3)
- f3 >>= 8
- out[13] = byte(f3)
- f3 >>= 8
- out[14] = byte(f3)
- f3 >>= 8
- out[15] = byte(f3)
+ // h %= p reduction
+ h2 += h1 >> 26
+ h1 &= 0x3ffffff
+ h3 += h2 >> 26
+ h2 &= 0x3ffffff
+ h4 += h3 >> 26
+ h3 &= 0x3ffffff
+ h0 += 5 * (h4 >> 26)
+ h4 &= 0x3ffffff
+ h1 += h0 >> 26
+ h0 &= 0x3ffffff
+
+ // h - p
+ t0 := h0 + 5
+ t1 := h1 + (t0 >> 26)
+ t2 := h2 + (t1 >> 26)
+ t3 := h3 + (t2 >> 26)
+ t4 := h4 + (t3 >> 26) - (1 << 26)
+ t0 &= 0x3ffffff
+ t1 &= 0x3ffffff
+ t2 &= 0x3ffffff
+ t3 &= 0x3ffffff
+
+ // select h if h < p else h - p
+ t_mask := (t4 >> 31) - 1
+ h_mask := ^t_mask
+ h0 = (h0 & h_mask) | (t0 & t_mask)
+ h1 = (h1 & h_mask) | (t1 & t_mask)
+ h2 = (h2 & h_mask) | (t2 & t_mask)
+ h3 = (h3 & h_mask) | (t3 & t_mask)
+ h4 = (h4 & h_mask) | (t4 & t_mask)
+
+ // h %= 2^128
+ h0 |= h1 << 26
+ h1 = ((h1 >> 6) | (h2 << 20))
+ h2 = ((h2 >> 12) | (h3 << 14))
+ h3 = ((h3 >> 18) | (h4 << 8))
+
+ // s: the s part of the key
+ // tag = (h + s) % (2^128)
+ t := uint64(h0) + uint64(binary.LittleEndian.Uint32(key[16:]))
+ h0 = uint32(t)
+ t = uint64(h1) + uint64(binary.LittleEndian.Uint32(key[20:])) + (t >> 32)
+ h1 = uint32(t)
+ t = uint64(h2) + uint64(binary.LittleEndian.Uint32(key[24:])) + (t >> 32)
+ h2 = uint32(t)
+ t = uint64(h3) + uint64(binary.LittleEndian.Uint32(key[28:])) + (t >> 32)
+ h3 = uint32(t)
+
+ binary.LittleEndian.PutUint32(out[0:], h0)
+ binary.LittleEndian.PutUint32(out[4:], h1)
+ binary.LittleEndian.PutUint32(out[8:], h2)
+ binary.LittleEndian.PutUint32(out[12:], h3)
}
diff --git a/vendor/golang.org/x/crypto/ssh/agent/client_test.go b/vendor/golang.org/x/crypto/ssh/agent/client_test.go
index e33d471..5fc47e5 100644
--- a/vendor/golang.org/x/crypto/ssh/agent/client_test.go
+++ b/vendor/golang.org/x/crypto/ssh/agent/client_test.go
@@ -182,7 +182,10 @@ func TestCert(t *testing.T) {
func netPipe() (net.Conn, net.Conn, error) {
listener, err := net.Listen("tcp", "127.0.0.1:0")
if err != nil {
- return nil, nil, err
+ listener, err = net.Listen("tcp", "[::1]:0")
+ if err != nil {
+ return nil, nil, err
+ }
}
defer listener.Close()
c1, err := net.Dial("tcp", listener.Addr().String())
@@ -200,6 +203,9 @@ func netPipe() (net.Conn, net.Conn, error) {
}
func TestAuth(t *testing.T) {
+ agent, _, cleanup := startAgent(t)
+ defer cleanup()
+
a, b, err := netPipe()
if err != nil {
t.Fatalf("netPipe: %v", err)
@@ -208,9 +214,6 @@ func TestAuth(t *testing.T) {
defer a.Close()
defer b.Close()
- agent, _, cleanup := startAgent(t)
- defer cleanup()
-
if err := agent.Add(AddedKey{PrivateKey: testPrivateKeys["rsa"], Comment: "comment"}); err != nil {
t.Errorf("Add: %v", err)
}
@@ -233,7 +236,9 @@ func TestAuth(t *testing.T) {
conn.Close()
}()
- conf := ssh.ClientConfig{}
+ conf := ssh.ClientConfig{
+ HostKeyCallback: ssh.InsecureIgnoreHostKey(),
+ }
conf.Auth = append(conf.Auth, ssh.PublicKeysCallback(agent.Signers))
conn, _, _, err := ssh.NewClientConn(b, "", &conf)
if err != nil {
diff --git a/vendor/golang.org/x/crypto/ssh/agent/example_test.go b/vendor/golang.org/x/crypto/ssh/agent/example_test.go
index c1130f7..8556225 100644
--- a/vendor/golang.org/x/crypto/ssh/agent/example_test.go
+++ b/vendor/golang.org/x/crypto/ssh/agent/example_test.go
@@ -6,20 +6,20 @@ package agent_test
import (
"log"
- "os"
"net"
+ "os"
- "golang.org/x/crypto/ssh"
- "golang.org/x/crypto/ssh/agent"
+ "golang.org/x/crypto/ssh"
+ "golang.org/x/crypto/ssh/agent"
)
func ExampleClientAgent() {
// ssh-agent has a UNIX socket under $SSH_AUTH_SOCK
socket := os.Getenv("SSH_AUTH_SOCK")
- conn, err := net.Dial("unix", socket)
- if err != nil {
- log.Fatalf("net.Dial: %v", err)
- }
+ conn, err := net.Dial("unix", socket)
+ if err != nil {
+ log.Fatalf("net.Dial: %v", err)
+ }
agentClient := agent.NewClient(conn)
config := &ssh.ClientConfig{
User: "username",
@@ -29,6 +29,7 @@ func ExampleClientAgent() {
// wants it.
ssh.PublicKeysCallback(agentClient.Signers),
},
+ HostKeyCallback: ssh.InsecureIgnoreHostKey(),
}
sshc, err := ssh.Dial("tcp", "localhost:22", config)
diff --git a/vendor/golang.org/x/crypto/ssh/agent/server_test.go b/vendor/golang.org/x/crypto/ssh/agent/server_test.go
index ec9cdee..6b0837d 100644
--- a/vendor/golang.org/x/crypto/ssh/agent/server_test.go
+++ b/vendor/golang.org/x/crypto/ssh/agent/server_test.go
@@ -56,7 +56,9 @@ func TestSetupForwardAgent(t *testing.T) {
incoming <- conn
}()
- conf := ssh.ClientConfig{}
+ conf := ssh.ClientConfig{
+ HostKeyCallback: ssh.InsecureIgnoreHostKey(),
+ }
conn, chans, reqs, err := ssh.NewClientConn(b, "", &conf)
if err != nil {
t.Fatalf("NewClientConn: %v", err)
diff --git a/vendor/golang.org/x/crypto/ssh/certs.go b/vendor/golang.org/x/crypto/ssh/certs.go
index 6331c94..b1f0220 100644
--- a/vendor/golang.org/x/crypto/ssh/certs.go
+++ b/vendor/golang.org/x/crypto/ssh/certs.go
@@ -251,10 +251,18 @@ type CertChecker struct {
// for user certificates.
SupportedCriticalOptions []string
- // IsAuthority should return true if the key is recognized as
- // an authority. This allows for certificates to be signed by other
- // certificates.
- IsAuthority func(auth PublicKey) bool
+ // IsUserAuthority should return true if the key is recognized as an
+ // authority for the given user certificate. This allows for
+ // certificates to be signed by other certificates. This must be set
+ // if this CertChecker will be checking user certificates.
+ IsUserAuthority func(auth PublicKey) bool
+
+ // IsHostAuthority should report whether the key is recognized as
+ // an authority for this host. This allows for certificates to be
+ // signed by other keys, and for those other keys to only be valid
+ // signers for particular hostnames. This must be set if this
+ // CertChecker will be checking host certificates.
+ IsHostAuthority func(auth PublicKey, address string) bool
// Clock is used for verifying time stamps. If nil, time.Now
// is used.
@@ -268,7 +276,7 @@ type CertChecker struct {
// HostKeyFallback is called when CertChecker.CheckHostKey encounters a
// public key that is not a certificate. It must implement host key
// validation or else, if nil, all such keys are rejected.
- HostKeyFallback func(addr string, remote net.Addr, key PublicKey) error
+ HostKeyFallback HostKeyCallback
// IsRevoked is called for each certificate so that revocation checking
// can be implemented. It should return true if the given certificate
@@ -290,8 +298,17 @@ func (c *CertChecker) CheckHostKey(addr string, remote net.Addr, key PublicKey)
if cert.CertType != HostCert {
return fmt.Errorf("ssh: certificate presented as a host key has type %d", cert.CertType)
}
+ if !c.IsHostAuthority(cert.SignatureKey, addr) {
+ return fmt.Errorf("ssh: no authorities for hostname: %v", addr)
+ }
- return c.CheckCert(addr, cert)
+ hostname, _, err := net.SplitHostPort(addr)
+ if err != nil {
+ return err
+ }
+
+ // Pass hostname only as principal for host certificates (consistent with OpenSSH)
+ return c.CheckCert(hostname, cert)
}
// Authenticate checks a user certificate. Authenticate can be used as
@@ -308,6 +325,9 @@ func (c *CertChecker) Authenticate(conn ConnMetadata, pubKey PublicKey) (*Permis
if cert.CertType != UserCert {
return nil, fmt.Errorf("ssh: cert has type %d", cert.CertType)
}
+ if !c.IsUserAuthority(cert.SignatureKey) {
+ return nil, fmt.Errorf("ssh: certificate signed by unrecognized authority")
+ }
if err := c.CheckCert(conn.User(), cert); err != nil {
return nil, err
@@ -356,10 +376,6 @@ func (c *CertChecker) CheckCert(principal string, cert *Certificate) error {
}
}
- if !c.IsAuthority(cert.SignatureKey) {
- return fmt.Errorf("ssh: certificate signed by unrecognized authority")
- }
-
clock := c.Clock
if clock == nil {
clock = time.Now
diff --git a/vendor/golang.org/x/crypto/ssh/certs_test.go b/vendor/golang.org/x/crypto/ssh/certs_test.go
index c5f2e53..0200531 100644
--- a/vendor/golang.org/x/crypto/ssh/certs_test.go
+++ b/vendor/golang.org/x/crypto/ssh/certs_test.go
@@ -104,7 +104,7 @@ func TestValidateCert(t *testing.T) {
t.Fatalf("got %v (%T), want *Certificate", key, key)
}
checker := CertChecker{}
- checker.IsAuthority = func(k PublicKey) bool {
+ checker.IsUserAuthority = func(k PublicKey) bool {
return bytes.Equal(k.Marshal(), validCert.SignatureKey.Marshal())
}
@@ -142,7 +142,7 @@ func TestValidateCertTime(t *testing.T) {
checker := CertChecker{
Clock: func() time.Time { return time.Unix(ts, 0) },
}
- checker.IsAuthority = func(k PublicKey) bool {
+ checker.IsUserAuthority = func(k PublicKey) bool {
return bytes.Equal(k.Marshal(),
testPublicKeys["ecdsa"].Marshal())
}
@@ -160,7 +160,7 @@ func TestValidateCertTime(t *testing.T) {
func TestHostKeyCert(t *testing.T) {
cert := &Certificate{
- ValidPrincipals: []string{"hostname", "hostname.domain"},
+ ValidPrincipals: []string{"hostname", "hostname.domain", "otherhost"},
Key: testPublicKeys["rsa"],
ValidBefore: CertTimeInfinity,
CertType: HostCert,
@@ -168,8 +168,8 @@ func TestHostKeyCert(t *testing.T) {
cert.SignCert(rand.Reader, testSigners["ecdsa"])
checker := &CertChecker{
- IsAuthority: func(p PublicKey) bool {
- return bytes.Equal(testPublicKeys["ecdsa"].Marshal(), p.Marshal())
+ IsHostAuthority: func(p PublicKey, addr string) bool {
+ return addr == "hostname:22" && bytes.Equal(testPublicKeys["ecdsa"].Marshal(), p.Marshal())
},
}
@@ -178,7 +178,14 @@ func TestHostKeyCert(t *testing.T) {
t.Errorf("NewCertSigner: %v", err)
}
- for _, name := range []string{"hostname", "otherhost"} {
+ for _, test := range []struct {
+ addr string
+ succeed bool
+ }{
+ {addr: "hostname:22", succeed: true},
+ {addr: "otherhost:22", succeed: false}, // The certificate is valid for 'otherhost' as hostname, but we only recognize the authority of the signer for the address 'hostname:22'
+ {addr: "lasthost:22", succeed: false},
+ } {
c1, c2, err := netPipe()
if err != nil {
t.Fatalf("netPipe: %v", err)
@@ -201,16 +208,15 @@ func TestHostKeyCert(t *testing.T) {
User: "user",
HostKeyCallback: checker.CheckHostKey,
}
- _, _, _, err = NewClientConn(c2, name, config)
+ _, _, _, err = NewClientConn(c2, test.addr, config)
- succeed := name == "hostname"
- if (err == nil) != succeed {
- t.Fatalf("NewClientConn(%q): %v", name, err)
+ if (err == nil) != test.succeed {
+ t.Fatalf("NewClientConn(%q): %v", test.addr, err)
}
err = <-errc
- if (err == nil) != succeed {
- t.Fatalf("NewServerConn(%q): %v", name, err)
+ if (err == nil) != test.succeed {
+ t.Fatalf("NewServerConn(%q): %v", test.addr, err)
}
}
}
diff --git a/vendor/golang.org/x/crypto/ssh/channel.go b/vendor/golang.org/x/crypto/ssh/channel.go
index 6d709b5..195530e 100644
--- a/vendor/golang.org/x/crypto/ssh/channel.go
+++ b/vendor/golang.org/x/crypto/ssh/channel.go
@@ -461,8 +461,8 @@ func (m *mux) newChannel(chanType string, direction channelDirection, extraData
pending: newBuffer(),
extPending: newBuffer(),
direction: direction,
- incomingRequests: make(chan *Request, 16),
- msg: make(chan interface{}, 16),
+ incomingRequests: make(chan *Request, chanSize),
+ msg: make(chan interface{}, chanSize),
chanType: chanType,
extraData: extraData,
mux: m,
diff --git a/vendor/golang.org/x/crypto/ssh/cipher.go b/vendor/golang.org/x/crypto/ssh/cipher.go
index 34d3917..13484ab 100644
--- a/vendor/golang.org/x/crypto/ssh/cipher.go
+++ b/vendor/golang.org/x/crypto/ssh/cipher.go
@@ -135,6 +135,7 @@ const prefixLen = 5
type streamPacketCipher struct {
mac hash.Hash
cipher cipher.Stream
+ etm bool
// The following members are to avoid per-packet allocations.
prefix [prefixLen]byte
@@ -150,7 +151,14 @@ func (s *streamPacketCipher) readPacket(seqNum uint32, r io.Reader) ([]byte, err
return nil, err
}
- s.cipher.XORKeyStream(s.prefix[:], s.prefix[:])
+ var encryptedPaddingLength [1]byte
+ if s.mac != nil && s.etm {
+ copy(encryptedPaddingLength[:], s.prefix[4:5])
+ s.cipher.XORKeyStream(s.prefix[4:5], s.prefix[4:5])
+ } else {
+ s.cipher.XORKeyStream(s.prefix[:], s.prefix[:])
+ }
+
length := binary.BigEndian.Uint32(s.prefix[0:4])
paddingLength := uint32(s.prefix[4])
@@ -159,7 +167,12 @@ func (s *streamPacketCipher) readPacket(seqNum uint32, r io.Reader) ([]byte, err
s.mac.Reset()
binary.BigEndian.PutUint32(s.seqNumBytes[:], seqNum)
s.mac.Write(s.seqNumBytes[:])
- s.mac.Write(s.prefix[:])
+ if s.etm {
+ s.mac.Write(s.prefix[:4])
+ s.mac.Write(encryptedPaddingLength[:])
+ } else {
+ s.mac.Write(s.prefix[:])
+ }
macSize = uint32(s.mac.Size())
}
@@ -184,10 +197,17 @@ func (s *streamPacketCipher) readPacket(seqNum uint32, r io.Reader) ([]byte, err
}
mac := s.packetData[length-1:]
data := s.packetData[:length-1]
+
+ if s.mac != nil && s.etm {
+ s.mac.Write(data)
+ }
+
s.cipher.XORKeyStream(data, data)
if s.mac != nil {
- s.mac.Write(data)
+ if !s.etm {
+ s.mac.Write(data)
+ }
s.macResult = s.mac.Sum(s.macResult[:0])
if subtle.ConstantTimeCompare(s.macResult, mac) != 1 {
return nil, errors.New("ssh: MAC failure")
@@ -203,7 +223,13 @@ func (s *streamPacketCipher) writePacket(seqNum uint32, w io.Writer, rand io.Rea
return errors.New("ssh: packet too large")
}
- paddingLength := packetSizeMultiple - (prefixLen+len(packet))%packetSizeMultiple
+ aadlen := 0
+ if s.mac != nil && s.etm {
+ // packet length is not encrypted for EtM modes
+ aadlen = 4
+ }
+
+ paddingLength := packetSizeMultiple - (prefixLen+len(packet)-aadlen)%packetSizeMultiple
if paddingLength < 4 {
paddingLength += packetSizeMultiple
}
@@ -220,15 +246,37 @@ func (s *streamPacketCipher) writePacket(seqNum uint32, w io.Writer, rand io.Rea
s.mac.Reset()
binary.BigEndian.PutUint32(s.seqNumBytes[:], seqNum)
s.mac.Write(s.seqNumBytes[:])
+
+ if s.etm {
+ // For EtM algorithms, the packet length must stay unencrypted,
+ // but the following data (padding length) must be encrypted
+ s.cipher.XORKeyStream(s.prefix[4:5], s.prefix[4:5])
+ }
+
s.mac.Write(s.prefix[:])
+
+ if !s.etm {
+ // For non-EtM algorithms, the algorithm is applied on unencrypted data
+ s.mac.Write(packet)
+ s.mac.Write(padding)
+ }
+ }
+
+ if !(s.mac != nil && s.etm) {
+ // For EtM algorithms, the padding length has already been encrypted
+ // and the packet length must remain unencrypted
+ s.cipher.XORKeyStream(s.prefix[:], s.prefix[:])
+ }
+
+ s.cipher.XORKeyStream(packet, packet)
+ s.cipher.XORKeyStream(padding, padding)
+
+ if s.mac != nil && s.etm {
+ // For EtM algorithms, packet and padding must be encrypted
s.mac.Write(packet)
s.mac.Write(padding)
}
- s.cipher.XORKeyStream(s.prefix[:], s.prefix[:])
- s.cipher.XORKeyStream(packet, packet)
- s.cipher.XORKeyStream(padding, padding)
-
if _, err := w.Write(s.prefix[:]); err != nil {
return err
}
diff --git a/vendor/golang.org/x/crypto/ssh/cipher_test.go b/vendor/golang.org/x/crypto/ssh/cipher_test.go
index eced8d8..5cfa17a 100644
--- a/vendor/golang.org/x/crypto/ssh/cipher_test.go
+++ b/vendor/golang.org/x/crypto/ssh/cipher_test.go
@@ -26,39 +26,41 @@ func TestPacketCiphers(t *testing.T) {
defer delete(cipherModes, aes128cbcID)
for cipher := range cipherModes {
- kr := &kexResult{Hash: crypto.SHA1}
- algs := directionAlgorithms{
- Cipher: cipher,
- MAC: "hmac-sha1",
- Compression: "none",
- }
- client, err := newPacketCipher(clientKeys, algs, kr)
- if err != nil {
- t.Errorf("newPacketCipher(client, %q): %v", cipher, err)
- continue
- }
- server, err := newPacketCipher(clientKeys, algs, kr)
- if err != nil {
- t.Errorf("newPacketCipher(client, %q): %v", cipher, err)
- continue
- }
+ for mac := range macModes {
+ kr := &kexResult{Hash: crypto.SHA1}
+ algs := directionAlgorithms{
+ Cipher: cipher,
+ MAC: mac,
+ Compression: "none",
+ }
+ client, err := newPacketCipher(clientKeys, algs, kr)
+ if err != nil {
+ t.Errorf("newPacketCipher(client, %q, %q): %v", cipher, mac, err)
+ continue
+ }
+ server, err := newPacketCipher(clientKeys, algs, kr)
+ if err != nil {
+ t.Errorf("newPacketCipher(client, %q, %q): %v", cipher, mac, err)
+ continue
+ }
- want := "bla bla"
- input := []byte(want)
- buf := &bytes.Buffer{}
- if err := client.writePacket(0, buf, rand.Reader, input); err != nil {
- t.Errorf("writePacket(%q): %v", cipher, err)
- continue
- }
+ want := "bla bla"
+ input := []byte(want)
+ buf := &bytes.Buffer{}
+ if err := client.writePacket(0, buf, rand.Reader, input); err != nil {
+ t.Errorf("writePacket(%q, %q): %v", cipher, mac, err)
+ continue
+ }
- packet, err := server.readPacket(0, buf)
- if err != nil {
- t.Errorf("readPacket(%q): %v", cipher, err)
- continue
- }
+ packet, err := server.readPacket(0, buf)
+ if err != nil {
+ t.Errorf("readPacket(%q, %q): %v", cipher, mac, err)
+ continue
+ }
- if string(packet) != want {
- t.Errorf("roundtrip(%q): got %q, want %q", cipher, packet, want)
+ if string(packet) != want {
+ t.Errorf("roundtrip(%q, %q): got %q, want %q", cipher, mac, packet, want)
+ }
}
}
}
diff --git a/vendor/golang.org/x/crypto/ssh/client.go b/vendor/golang.org/x/crypto/ssh/client.go
index c841e8d..a7e3263 100644
--- a/vendor/golang.org/x/crypto/ssh/client.go
+++ b/vendor/golang.org/x/crypto/ssh/client.go
@@ -5,6 +5,7 @@
package ssh
import (
+ "bytes"
"errors"
"fmt"
"net"
@@ -13,7 +14,7 @@ import (
)
// Client implements a traditional SSH client that supports shells,
-// subprocesses, port forwarding and tunneled dialing.
+// subprocesses, TCP port/streamlocal forwarding and tunneled dialing.
type Client struct {
Conn
@@ -40,7 +41,7 @@ func (c *Client) HandleChannelOpen(channelType string) <-chan NewChannel {
return nil
}
- ch = make(chan NewChannel, 16)
+ ch = make(chan NewChannel, chanSize)
c.channelHandlers[channelType] = ch
return ch
}
@@ -59,6 +60,7 @@ func NewClient(c Conn, chans <-chan NewChannel, reqs <-chan *Request) *Client {
conn.forwards.closeAll()
}()
go conn.forwards.handleChannels(conn.HandleChannelOpen("forwarded-tcpip"))
+ go conn.forwards.handleChannels(conn.HandleChannelOpen("forwarded-streamlocal@openssh.com"))
return conn
}
@@ -68,6 +70,11 @@ func NewClient(c Conn, chans <-chan NewChannel, reqs <-chan *Request) *Client {
func NewClientConn(c net.Conn, addr string, config *ClientConfig) (Conn, <-chan NewChannel, <-chan *Request, error) {
fullConf := *config
fullConf.SetDefaults()
+ if fullConf.HostKeyCallback == nil {
+ c.Close()
+ return nil, nil, nil, errors.New("ssh: must specify HostKeyCallback")
+ }
+
conn := &connection{
sshConn: sshConn{conn: c},
}
@@ -173,6 +180,13 @@ func Dial(network, addr string, config *ClientConfig) (*Client, error) {
return NewClient(c, chans, reqs), nil
}
+// HostKeyCallback is the function type used for verifying server
+// keys. A HostKeyCallback must return nil if the host key is OK, or
+// an error to reject it. It receives the hostname as passed to Dial
+// or NewClientConn. The remote address is the RemoteAddr of the
+// net.Conn underlying the the SSH connection.
+type HostKeyCallback func(hostname string, remote net.Addr, key PublicKey) error
+
// A ClientConfig structure is used to configure a Client. It must not be
// modified after having been passed to an SSH function.
type ClientConfig struct {
@@ -188,10 +202,12 @@ type ClientConfig struct {
// be used during authentication.
Auth []AuthMethod
- // HostKeyCallback, if not nil, is called during the cryptographic
- // handshake to validate the server's host key. A nil HostKeyCallback
- // implies that all host keys are accepted.
- HostKeyCallback func(hostname string, remote net.Addr, key PublicKey) error
+ // HostKeyCallback is called during the cryptographic
+ // handshake to validate the server's host key. The client
+ // configuration must supply this callback for the connection
+ // to succeed. The functions InsecureIgnoreHostKey or
+ // FixedHostKey can be used for simplistic host key checks.
+ HostKeyCallback HostKeyCallback
// ClientVersion contains the version identification string that will
// be used for the connection. If empty, a reasonable default is used.
@@ -209,3 +225,33 @@ type ClientConfig struct {
// A Timeout of zero means no timeout.
Timeout time.Duration
}
+
+// InsecureIgnoreHostKey returns a function that can be used for
+// ClientConfig.HostKeyCallback to accept any host key. It should
+// not be used for production code.
+func InsecureIgnoreHostKey() HostKeyCallback {
+ return func(hostname string, remote net.Addr, key PublicKey) error {
+ return nil
+ }
+}
+
+type fixedHostKey struct {
+ key PublicKey
+}
+
+func (f *fixedHostKey) check(hostname string, remote net.Addr, key PublicKey) error {
+ if f.key == nil {
+ return fmt.Errorf("ssh: required host key was nil")
+ }
+ if !bytes.Equal(key.Marshal(), f.key.Marshal()) {
+ return fmt.Errorf("ssh: host key mismatch")
+ }
+ return nil
+}
+
+// FixedHostKey returns a function for use in
+// ClientConfig.HostKeyCallback to accept only a specific host key.
+func FixedHostKey(key PublicKey) HostKeyCallback {
+ hk := &fixedHostKey{key}
+ return hk.check
+}
diff --git a/vendor/golang.org/x/crypto/ssh/client_auth.go b/vendor/golang.org/x/crypto/ssh/client_auth.go
index fd1ec5d..b882da0 100644
--- a/vendor/golang.org/x/crypto/ssh/client_auth.go
+++ b/vendor/golang.org/x/crypto/ssh/client_auth.go
@@ -179,31 +179,26 @@ func (cb publicKeyCallback) method() string {
}
func (cb publicKeyCallback) auth(session []byte, user string, c packetConn, rand io.Reader) (bool, []string, error) {
- // Authentication is performed in two stages. The first stage sends an
- // enquiry to test if each key is acceptable to the remote. The second
- // stage attempts to authenticate with the valid keys obtained in the
- // first stage.
+ // Authentication is performed by sending an enquiry to test if a key is
+ // acceptable to the remote. If the key is acceptable, the client will
+ // attempt to authenticate with the valid key. If not the client will repeat
+ // the process with the remaining keys.
signers, err := cb()
if err != nil {
return false, nil, err
}
- var validKeys []Signer
- for _, signer := range signers {
- if ok, err := validateKey(signer.PublicKey(), user, c); ok {
- validKeys = append(validKeys, signer)
- } else {
- if err != nil {
- return false, nil, err
- }
- }
- }
-
- // methods that may continue if this auth is not successful.
var methods []string
- for _, signer := range validKeys {
- pub := signer.PublicKey()
+ for _, signer := range signers {
+ ok, err := validateKey(signer.PublicKey(), user, c)
+ if err != nil {
+ return false, nil, err
+ }
+ if !ok {
+ continue
+ }
+ pub := signer.PublicKey()
pubKey := pub.Marshal()
sign, err := signer.Sign(rand, buildDataSignedForAuth(session, userAuthRequestMsg{
User: user,
@@ -236,13 +231,29 @@ func (cb publicKeyCallback) auth(session []byte, user string, c packetConn, rand
if err != nil {
return false, nil, err
}
- if success {
+
+ // If authentication succeeds or the list of available methods does not
+ // contain the "publickey" method, do not attempt to authenticate with any
+ // other keys. According to RFC 4252 Section 7, the latter can occur when
+ // additional authentication methods are required.
+ if success || !containsMethod(methods, cb.method()) {
return success, methods, err
}
}
+
return false, methods, nil
}
+func containsMethod(methods []string, method string) bool {
+ for _, m := range methods {
+ if m == method {
+ return true
+ }
+ }
+
+ return false
+}
+
// validateKey validates the key provided is acceptable to the server.
func validateKey(key PublicKey, user string, c packetConn) (bool, error) {
pubKey := key.Marshal()
diff --git a/vendor/golang.org/x/crypto/ssh/client_auth_test.go b/vendor/golang.org/x/crypto/ssh/client_auth_test.go
index 1d9681a..bd9f8a1 100644
--- a/vendor/golang.org/x/crypto/ssh/client_auth_test.go
+++ b/vendor/golang.org/x/crypto/ssh/client_auth_test.go
@@ -38,7 +38,7 @@ func tryAuth(t *testing.T, config *ClientConfig) error {
defer c2.Close()
certChecker := CertChecker{
- IsAuthority: func(k PublicKey) bool {
+ IsUserAuthority: func(k PublicKey) bool {
return bytes.Equal(k.Marshal(), testPublicKeys["ecdsa"].Marshal())
},
UserKeyFallback: func(conn ConnMetadata, key PublicKey) (*Permissions, error) {
@@ -76,8 +76,6 @@ func tryAuth(t *testing.T, config *ClientConfig) error {
}
return nil, errors.New("keyboard-interactive failed")
},
- AuthLogCallback: func(conn ConnMetadata, method string, err error) {
- },
}
serverConfig.AddHostKey(testSigners["rsa"])
@@ -92,6 +90,7 @@ func TestClientAuthPublicKey(t *testing.T) {
Auth: []AuthMethod{
PublicKeys(testSigners["rsa"]),
},
+ HostKeyCallback: InsecureIgnoreHostKey(),
}
if err := tryAuth(t, config); err != nil {
t.Fatalf("unable to dial remote side: %s", err)
@@ -104,6 +103,7 @@ func TestAuthMethodPassword(t *testing.T) {
Auth: []AuthMethod{
Password(clientPassword),
},
+ HostKeyCallback: InsecureIgnoreHostKey(),
}
if err := tryAuth(t, config); err != nil {
@@ -123,6 +123,7 @@ func TestAuthMethodFallback(t *testing.T) {
return "WRONG", nil
}),
},
+ HostKeyCallback: InsecureIgnoreHostKey(),
}
if err := tryAuth(t, config); err != nil {
@@ -141,6 +142,7 @@ func TestAuthMethodWrongPassword(t *testing.T) {
Password("wrong"),
PublicKeys(testSigners["rsa"]),
},
+ HostKeyCallback: InsecureIgnoreHostKey(),
}
if err := tryAuth(t, config); err != nil {
@@ -158,6 +160,7 @@ func TestAuthMethodKeyboardInteractive(t *testing.T) {
Auth: []AuthMethod{
KeyboardInteractive(answers.Challenge),
},
+ HostKeyCallback: InsecureIgnoreHostKey(),
}
if err := tryAuth(t, config); err != nil {
@@ -203,6 +206,7 @@ func TestAuthMethodRSAandDSA(t *testing.T) {
Auth: []AuthMethod{
PublicKeys(testSigners["dsa"], testSigners["rsa"]),
},
+ HostKeyCallback: InsecureIgnoreHostKey(),
}
if err := tryAuth(t, config); err != nil {
t.Fatalf("client could not authenticate with rsa key: %v", err)
@@ -219,6 +223,7 @@ func TestClientHMAC(t *testing.T) {
Config: Config{
MACs: []string{mac},
},
+ HostKeyCallback: InsecureIgnoreHostKey(),
}
if err := tryAuth(t, config); err != nil {
t.Fatalf("client could not authenticate with mac algo %s: %v", mac, err)
@@ -254,6 +259,7 @@ func TestClientUnsupportedKex(t *testing.T) {
Config: Config{
KeyExchanges: []string{"diffie-hellman-group-exchange-sha256"}, // not currently supported
},
+ HostKeyCallback: InsecureIgnoreHostKey(),
}
if err := tryAuth(t, config); err == nil || !strings.Contains(err.Error(), "common algorithm") {
t.Errorf("got %v, expected 'common algorithm'", err)
@@ -273,7 +279,8 @@ func TestClientLoginCert(t *testing.T) {
}
clientConfig := &ClientConfig{
- User: "user",
+ User: "user",
+ HostKeyCallback: InsecureIgnoreHostKey(),
}
clientConfig.Auth = append(clientConfig.Auth, PublicKeys(certSigner))
@@ -333,14 +340,14 @@ func TestClientLoginCert(t *testing.T) {
}
// allowed source address
- cert.CriticalOptions = map[string]string{"source-address": "127.0.0.42/24"}
+ cert.CriticalOptions = map[string]string{"source-address": "127.0.0.42/24,::42/120"}
cert.SignCert(rand.Reader, testSigners["ecdsa"])
if err := tryAuth(t, clientConfig); err != nil {
t.Errorf("cert login with source-address failed: %v", err)
}
// disallowed source address
- cert.CriticalOptions = map[string]string{"source-address": "127.0.0.42"}
+ cert.CriticalOptions = map[string]string{"source-address": "127.0.0.42,::42"}
cert.SignCert(rand.Reader, testSigners["ecdsa"])
if err := tryAuth(t, clientConfig); err == nil {
t.Errorf("cert login with source-address succeeded")
@@ -363,6 +370,7 @@ func testPermissionsPassing(withPermissions bool, t *testing.T) {
Auth: []AuthMethod{
PublicKeys(testSigners["rsa"]),
},
+ HostKeyCallback: InsecureIgnoreHostKey(),
}
if withPermissions {
clientConfig.User = "permissions"
@@ -409,6 +417,7 @@ func TestRetryableAuth(t *testing.T) {
}), 2),
PublicKeys(testSigners["rsa"]),
},
+ HostKeyCallback: InsecureIgnoreHostKey(),
}
if err := tryAuth(t, config); err != nil {
@@ -430,7 +439,8 @@ func ExampleRetryableAuthMethod(t *testing.T) {
}
config := &ClientConfig{
- User: user,
+ HostKeyCallback: InsecureIgnoreHostKey(),
+ User: user,
Auth: []AuthMethod{
RetryableAuthMethod(KeyboardInteractiveChallenge(Cb), NumberOfPrompts),
},
@@ -450,7 +460,8 @@ func TestClientAuthNone(t *testing.T) {
serverConfig.AddHostKey(testSigners["rsa"])
clientConfig := &ClientConfig{
- User: user,
+ User: user,
+ HostKeyCallback: InsecureIgnoreHostKey(),
}
c1, c2, err := netPipe()
@@ -469,3 +480,100 @@ func TestClientAuthNone(t *testing.T) {
t.Fatalf("server: got %q, want %q", serverConn.User(), user)
}
}
+
+// Test if authentication attempts are limited on server when MaxAuthTries is set
+func TestClientAuthMaxAuthTries(t *testing.T) {
+ user := "testuser"
+
+ serverConfig := &ServerConfig{
+ MaxAuthTries: 2,
+ PasswordCallback: func(conn ConnMetadata, pass []byte) (*Permissions, error) {
+ if conn.User() == "testuser" && string(pass) == "right" {
+ return nil, nil
+ }
+ return nil, errors.New("password auth failed")
+ },
+ }
+ serverConfig.AddHostKey(testSigners["rsa"])
+
+ expectedErr := fmt.Errorf("ssh: handshake failed: %v", &disconnectMsg{
+ Reason: 2,
+ Message: "too many authentication failures",
+ })
+
+ for tries := 2; tries < 4; tries++ {
+ n := tries
+ clientConfig := &ClientConfig{
+ User: user,
+ Auth: []AuthMethod{
+ RetryableAuthMethod(PasswordCallback(func() (string, error) {
+ n--
+ if n == 0 {
+ return "right", nil
+ } else {
+ return "wrong", nil
+ }
+ }), tries),
+ },
+ HostKeyCallback: InsecureIgnoreHostKey(),
+ }
+
+ c1, c2, err := netPipe()
+ if err != nil {
+ t.Fatalf("netPipe: %v", err)
+ }
+ defer c1.Close()
+ defer c2.Close()
+
+ go newServer(c1, serverConfig)
+ _, _, _, err = NewClientConn(c2, "", clientConfig)
+ if tries > 2 {
+ if err == nil {
+ t.Fatalf("client: got no error, want %s", expectedErr)
+ } else if err.Error() != expectedErr.Error() {
+ t.Fatalf("client: got %s, want %s", err, expectedErr)
+ }
+ } else {
+ if err != nil {
+ t.Fatalf("client: got %s, want no error", err)
+ }
+ }
+ }
+}
+
+// Test if authentication attempts are correctly limited on server
+// when more public keys are provided then MaxAuthTries
+func TestClientAuthMaxAuthTriesPublicKey(t *testing.T) {
+ signers := []Signer{}
+ for i := 0; i < 6; i++ {
+ signers = append(signers, testSigners["dsa"])
+ }
+
+ validConfig := &ClientConfig{
+ User: "testuser",
+ Auth: []AuthMethod{
+ PublicKeys(append([]Signer{testSigners["rsa"]}, signers...)...),
+ },
+ HostKeyCallback: InsecureIgnoreHostKey(),
+ }
+ if err := tryAuth(t, validConfig); err != nil {
+ t.Fatalf("unable to dial remote side: %s", err)
+ }
+
+ expectedErr := fmt.Errorf("ssh: handshake failed: %v", &disconnectMsg{
+ Reason: 2,
+ Message: "too many authentication failures",
+ })
+ invalidConfig := &ClientConfig{
+ User: "testuser",
+ Auth: []AuthMethod{
+ PublicKeys(append(signers, testSigners["rsa"])...),
+ },
+ HostKeyCallback: InsecureIgnoreHostKey(),
+ }
+ if err := tryAuth(t, invalidConfig); err == nil {
+ t.Fatalf("client: got no error, want %s", expectedErr)
+ } else if err.Error() != expectedErr.Error() {
+ t.Fatalf("client: got %s, want %s", err, expectedErr)
+ }
+}
diff --git a/vendor/golang.org/x/crypto/ssh/client_test.go b/vendor/golang.org/x/crypto/ssh/client_test.go
index 1fe790c..ccf5607 100644
--- a/vendor/golang.org/x/crypto/ssh/client_test.go
+++ b/vendor/golang.org/x/crypto/ssh/client_test.go
@@ -6,6 +6,7 @@ package ssh
import (
"net"
+ "strings"
"testing"
)
@@ -13,6 +14,7 @@ func testClientVersion(t *testing.T, config *ClientConfig, expected string) {
clientConn, serverConn := net.Pipe()
defer clientConn.Close()
receivedVersion := make(chan string, 1)
+ config.HostKeyCallback = InsecureIgnoreHostKey()
go func() {
version, err := readVersion(serverConn)
if err != nil {
@@ -37,3 +39,43 @@ func TestCustomClientVersion(t *testing.T) {
func TestDefaultClientVersion(t *testing.T) {
testClientVersion(t, &ClientConfig{}, packageVersion)
}
+
+func TestHostKeyCheck(t *testing.T) {
+ for _, tt := range []struct {
+ name string
+ wantError string
+ key PublicKey
+ }{
+ {"no callback", "must specify HostKeyCallback", nil},
+ {"correct key", "", testSigners["rsa"].PublicKey()},
+ {"mismatch", "mismatch", testSigners["ecdsa"].PublicKey()},
+ } {
+ c1, c2, err := netPipe()
+ if err != nil {
+ t.Fatalf("netPipe: %v", err)
+ }
+ defer c1.Close()
+ defer c2.Close()
+ serverConf := &ServerConfig{
+ NoClientAuth: true,
+ }
+ serverConf.AddHostKey(testSigners["rsa"])
+
+ go NewServerConn(c1, serverConf)
+ clientConf := ClientConfig{
+ User: "user",
+ }
+ if tt.key != nil {
+ clientConf.HostKeyCallback = FixedHostKey(tt.key)
+ }
+
+ _, _, _, err = NewClientConn(c2, "", &clientConf)
+ if err != nil {
+ if tt.wantError == "" || !strings.Contains(err.Error(), tt.wantError) {
+ t.Errorf("%s: got error %q, missing %q", tt.name, err.Error(), tt.wantError)
+ }
+ } else if tt.wantError != "" {
+ t.Errorf("%s: succeeded, but want error string %q", tt.name, tt.wantError)
+ }
+ }
+}
diff --git a/vendor/golang.org/x/crypto/ssh/common.go b/vendor/golang.org/x/crypto/ssh/common.go
index 2c72ab5..dc39e4d 100644
--- a/vendor/golang.org/x/crypto/ssh/common.go
+++ b/vendor/golang.org/x/crypto/ssh/common.go
@@ -9,6 +9,7 @@ import (
"crypto/rand"
"fmt"
"io"
+ "math"
"sync"
_ "crypto/sha1"
@@ -40,7 +41,7 @@ var supportedKexAlgos = []string{
kexAlgoDH14SHA1, kexAlgoDH1SHA1,
}
-// supportedKexAlgos specifies the supported host-key algorithms (i.e. methods
+// supportedHostKeyAlgos specifies the supported host-key algorithms (i.e. methods
// of authenticating servers) in preference order.
var supportedHostKeyAlgos = []string{
CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01,
@@ -56,7 +57,7 @@ var supportedHostKeyAlgos = []string{
// This is based on RFC 4253, section 6.4, but with hmac-md5 variants removed
// because they have reached the end of their useful life.
var supportedMACs = []string{
- "hmac-sha2-256", "hmac-sha1", "hmac-sha1-96",
+ "hmac-sha2-256-etm@openssh.com", "hmac-sha2-256", "hmac-sha1", "hmac-sha1-96",
}
var supportedCompressions = []string{compressionNone}
@@ -104,6 +105,21 @@ type directionAlgorithms struct {
Compression string
}
+// rekeyBytes returns a rekeying intervals in bytes.
+func (a *directionAlgorithms) rekeyBytes() int64 {
+ // According to RFC4344 block ciphers should rekey after
+ // 2^(BLOCKSIZE/4) blocks. For all AES flavors BLOCKSIZE is
+ // 128.
+ switch a.Cipher {
+ case "aes128-ctr", "aes192-ctr", "aes256-ctr", gcmCipherID, aes128cbcID:
+ return 16 * (1 << 32)
+
+ }
+
+ // For others, stick with RFC4253 recommendation to rekey after 1 Gb of data.
+ return 1 << 30
+}
+
type algorithms struct {
kex string
hostKey string
@@ -171,7 +187,7 @@ type Config struct {
// The maximum number of bytes sent or received after which a
// new key is negotiated. It must be at least 256. If
- // unspecified, 1 gigabyte is used.
+ // unspecified, a size suitable for the chosen cipher is used.
RekeyThreshold uint64
// The allowed key exchanges algorithms. If unspecified then a
@@ -215,11 +231,12 @@ func (c *Config) SetDefaults() {
}
if c.RekeyThreshold == 0 {
- // RFC 4253, section 9 suggests rekeying after 1G.
- c.RekeyThreshold = 1 << 30
- }
- if c.RekeyThreshold < minRekeyThreshold {
+ // cipher specific default
+ } else if c.RekeyThreshold < minRekeyThreshold {
c.RekeyThreshold = minRekeyThreshold
+ } else if c.RekeyThreshold >= math.MaxInt64 {
+ // Avoid weirdness if somebody uses -1 as a threshold.
+ c.RekeyThreshold = math.MaxInt64
}
}
diff --git a/vendor/golang.org/x/crypto/ssh/connection.go b/vendor/golang.org/x/crypto/ssh/connection.go
index e786f2f..fd6b068 100644
--- a/vendor/golang.org/x/crypto/ssh/connection.go
+++ b/vendor/golang.org/x/crypto/ssh/connection.go
@@ -25,7 +25,7 @@ type ConnMetadata interface {
// User returns the user ID for this connection.
User() string
- // SessionID returns the sesson hash, also denoted by H.
+ // SessionID returns the session hash, also denoted by H.
SessionID() []byte
// ClientVersion returns the client's version string as hashed
diff --git a/vendor/golang.org/x/crypto/ssh/doc.go b/vendor/golang.org/x/crypto/ssh/doc.go
index d6be894..67b7322 100644
--- a/vendor/golang.org/x/crypto/ssh/doc.go
+++ b/vendor/golang.org/x/crypto/ssh/doc.go
@@ -14,5 +14,8 @@ others.
References:
[PROTOCOL.certkeys]: http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL.certkeys?rev=HEAD
[SSH-PARAMETERS]: http://www.iana.org/assignments/ssh-parameters/ssh-parameters.xml#ssh-parameters-1
+
+This package does not fall under the stability promise of the Go language itself,
+so its API may be changed when pressing needs arise.
*/
package ssh // import "golang.org/x/crypto/ssh"
diff --git a/vendor/golang.org/x/crypto/ssh/example_test.go b/vendor/golang.org/x/crypto/ssh/example_test.go
index 4d2eabd..b910c7b 100644
--- a/vendor/golang.org/x/crypto/ssh/example_test.go
+++ b/vendor/golang.org/x/crypto/ssh/example_test.go
@@ -5,12 +5,16 @@
package ssh_test
import (
+ "bufio"
"bytes"
"fmt"
"io/ioutil"
"log"
"net"
"net/http"
+ "os"
+ "path/filepath"
+ "strings"
"golang.org/x/crypto/ssh"
"golang.org/x/crypto/ssh/terminal"
@@ -52,7 +56,12 @@ func ExampleNewServerConn() {
// Remove to disable public key auth.
PublicKeyCallback: func(c ssh.ConnMetadata, pubKey ssh.PublicKey) (*ssh.Permissions, error) {
if authorizedKeysMap[string(pubKey.Marshal())] {
- return nil, nil
+ return &ssh.Permissions{
+ // Record the public key used for authentication.
+ Extensions: map[string]string{
+ "pubkey-fp": ssh.FingerprintSHA256(pubKey),
+ },
+ }, nil
}
return nil, fmt.Errorf("unknown public key for %q", c.User())
},
@@ -83,15 +92,15 @@ func ExampleNewServerConn() {
// Before use, a handshake must be performed on the incoming
// net.Conn.
- _, chans, reqs, err := ssh.NewServerConn(nConn, config)
+ conn, chans, reqs, err := ssh.NewServerConn(nConn, config)
if err != nil {
log.Fatal("failed to handshake: ", err)
}
+ log.Printf("logged in with key %s", conn.Permissions.Extensions["pubkey-fp"])
+
// The incoming Request channel must be serviced.
go ssh.DiscardRequests(reqs)
- // Service the incoming Channel channel.
-
// Service the incoming Channel channel.
for newChannel := range chans {
// Channels have a type, depending on the application level
@@ -131,16 +140,59 @@ func ExampleNewServerConn() {
}
}
+func ExampleHostKeyCheck() {
+ // Every client must provide a host key check. Here is a
+ // simple-minded parse of OpenSSH's known_hosts file
+ host := "hostname"
+ file, err := os.Open(filepath.Join(os.Getenv("HOME"), ".ssh", "known_hosts"))
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer file.Close()
+
+ scanner := bufio.NewScanner(file)
+ var hostKey ssh.PublicKey
+ for scanner.Scan() {
+ fields := strings.Split(scanner.Text(), " ")
+ if len(fields) != 3 {
+ continue
+ }
+ if strings.Contains(fields[0], host) {
+ var err error
+ hostKey, _, _, _, err = ssh.ParseAuthorizedKey(scanner.Bytes())
+ if err != nil {
+ log.Fatalf("error parsing %q: %v", fields[2], err)
+ }
+ break
+ }
+ }
+
+ if hostKey == nil {
+ log.Fatalf("no hostkey for %s", host)
+ }
+
+ config := ssh.ClientConfig{
+ User: os.Getenv("USER"),
+ HostKeyCallback: ssh.FixedHostKey(hostKey),
+ }
+
+ _, err = ssh.Dial("tcp", host+":22", &config)
+ log.Println(err)
+}
+
func ExampleDial() {
+ var hostKey ssh.PublicKey
// An SSH client is represented with a ClientConn.
//
// To authenticate with the remote server you must pass at least one
- // implementation of AuthMethod via the Auth field in ClientConfig.
+ // implementation of AuthMethod via the Auth field in ClientConfig,
+ // and provide a HostKeyCallback.
config := &ssh.ClientConfig{
User: "username",
Auth: []ssh.AuthMethod{
ssh.Password("yourpassword"),
},
+ HostKeyCallback: ssh.FixedHostKey(hostKey),
}
client, err := ssh.Dial("tcp", "yourserver.com:22", config)
if err != nil {
@@ -166,6 +218,7 @@ func ExampleDial() {
}
func ExamplePublicKeys() {
+ var hostKey ssh.PublicKey
// A public key may be used to authenticate against the remote
// server by using an unencrypted PEM-encoded private key file.
//
@@ -188,6 +241,7 @@ func ExamplePublicKeys() {
// Use the PublicKeys method for remote authentication.
ssh.PublicKeys(signer),
},
+ HostKeyCallback: ssh.FixedHostKey(hostKey),
}
// Connect to the remote server and perform the SSH handshake.
@@ -199,11 +253,13 @@ func ExamplePublicKeys() {
}
func ExampleClient_Listen() {
+ var hostKey ssh.PublicKey
config := &ssh.ClientConfig{
User: "username",
Auth: []ssh.AuthMethod{
ssh.Password("password"),
},
+ HostKeyCallback: ssh.FixedHostKey(hostKey),
}
// Dial your ssh server.
conn, err := ssh.Dial("tcp", "localhost:22", config)
@@ -226,12 +282,14 @@ func ExampleClient_Listen() {
}
func ExampleSession_RequestPty() {
+ var hostKey ssh.PublicKey
// Create client config
config := &ssh.ClientConfig{
User: "username",
Auth: []ssh.AuthMethod{
ssh.Password("password"),
},
+ HostKeyCallback: ssh.FixedHostKey(hostKey),
}
// Connect to ssh server
conn, err := ssh.Dial("tcp", "localhost:22", config)
diff --git a/vendor/golang.org/x/crypto/ssh/handshake.go b/vendor/golang.org/x/crypto/ssh/handshake.go
index 03c950d..932ce83 100644
--- a/vendor/golang.org/x/crypto/ssh/handshake.go
+++ b/vendor/golang.org/x/crypto/ssh/handshake.go
@@ -19,6 +19,11 @@ import (
// messages are wrong when using ECDH.
const debugHandshake = false
+// chanSize sets the amount of buffering SSH connections. This is
+// primarily for testing: setting chanSize=0 uncovers deadlocks more
+// quickly.
+const chanSize = 16
+
// keyingTransport is a packet based transport that supports key
// changes. It need not be thread-safe. It should pass through
// msgNewKeys in both directions.
@@ -60,7 +65,8 @@ type handshakeTransport struct {
pendingPackets [][]byte // Used when a key exchange is in progress.
// If the read loop wants to schedule a kex, it pings this
- // channel, and the write loop will send out a kex message.
+ // channel, and the write loop will send out a kex
+ // message.
requestKex chan struct{}
// If the other side requests or confirms a kex, its kexInit
@@ -68,13 +74,18 @@ type handshakeTransport struct {
startKex chan *pendingKex
// data for host key checking
- hostKeyCallback func(hostname string, remote net.Addr, key PublicKey) error
+ hostKeyCallback HostKeyCallback
dialAddress string
remoteAddr net.Addr
- readSinceKex uint64
+ // Algorithms agreed in the last key exchange.
+ algorithms *algorithms
- writtenSinceKex uint64
+ readPacketsLeft uint32
+ readBytesLeft int64
+
+ writePacketsLeft uint32
+ writeBytesLeft int64
// The session ID or nil if first kex did not complete yet.
sessionID []byte
@@ -90,12 +101,17 @@ func newHandshakeTransport(conn keyingTransport, config *Config, clientVersion,
conn: conn,
serverVersion: serverVersion,
clientVersion: clientVersion,
- incoming: make(chan []byte, 16),
+ incoming: make(chan []byte, chanSize),
requestKex: make(chan struct{}, 1),
startKex: make(chan *pendingKex, 1),
config: config,
}
+ t.resetReadThresholds()
+ t.resetWriteThresholds()
+
+ // We always start with a mandatory key exchange.
+ t.requestKex <- struct{}{}
return t
}
@@ -152,6 +168,7 @@ func (t *handshakeTransport) printPacket(p []byte, write bool) {
if write {
action = "sent"
}
+
if p[0] == msgChannelData || p[0] == msgChannelExtendedData {
log.Printf("%s %s data (packet %d bytes)", t.id(), action, len(p))
} else {
@@ -169,12 +186,6 @@ func (t *handshakeTransport) readPacket() ([]byte, error) {
}
func (t *handshakeTransport) readLoop() {
- // We always start with the mandatory key exchange. We use
- // the channel for simplicity, and this works if we can rely
- // on the SSH package itself not doing anything else before
- // waitSession has completed.
- t.requestKeyExchange()
-
first := true
for {
p, err := t.readOnePacket(first)
@@ -226,10 +237,21 @@ func (t *handshakeTransport) requestKeyExchange() {
default:
// something already requested a kex, so do nothing.
}
+}
+func (t *handshakeTransport) resetWriteThresholds() {
+ t.writePacketsLeft = packetRekeyThreshold
+ if t.config.RekeyThreshold > 0 {
+ t.writeBytesLeft = int64(t.config.RekeyThreshold)
+ } else if t.algorithms != nil {
+ t.writeBytesLeft = t.algorithms.w.rekeyBytes()
+ } else {
+ t.writeBytesLeft = 1 << 30
+ }
}
func (t *handshakeTransport) kexLoop() {
+
write:
for t.getWriteError() == nil {
var request *pendingKex
@@ -243,6 +265,7 @@ write:
break write
}
case <-t.requestKex:
+ break
}
if !sent {
@@ -266,7 +289,8 @@ write:
// We're not servicing t.startKex, but the remote end
// has just sent us a kexInitMsg, so it can't send
- // another key change request.
+ // another key change request, until we close the done
+ // channel on the pendingKex request.
err := t.enterKeyExchange(request.otherInit)
@@ -274,7 +298,25 @@ write:
t.writeError = err
t.sentInitPacket = nil
t.sentInitMsg = nil
- t.writtenSinceKex = 0
+
+ t.resetWriteThresholds()
+
+ // we have completed the key exchange. Since the
+ // reader is still blocked, it is safe to clear out
+ // the requestKex channel. This avoids the situation
+ // where: 1) we consumed our own request for the
+ // initial kex, and 2) the kex from the remote side
+ // caused another send on the requestKex channel,
+ clear:
+ for {
+ select {
+ case <-t.requestKex:
+ //
+ default:
+ break clear
+ }
+ }
+
request.done <- t.writeError
// kex finished. Push packets that we received while
@@ -288,7 +330,7 @@ write:
break
}
}
- t.pendingPackets = t.pendingPackets[0:]
+ t.pendingPackets = t.pendingPackets[:0]
t.mu.Unlock()
}
@@ -304,17 +346,42 @@ write:
t.conn.Close()
}
-func (t *handshakeTransport) readOnePacket(first bool) ([]byte, error) {
- if t.readSinceKex > t.config.RekeyThreshold {
- t.requestKeyExchange()
- }
+// The protocol uses uint32 for packet counters, so we can't let them
+// reach 1<<32. We will actually read and write more packets than
+// this, though: the other side may send more packets, and after we
+// hit this limit on writing we will send a few more packets for the
+// key exchange itself.
+const packetRekeyThreshold = (1 << 31)
+func (t *handshakeTransport) resetReadThresholds() {
+ t.readPacketsLeft = packetRekeyThreshold
+ if t.config.RekeyThreshold > 0 {
+ t.readBytesLeft = int64(t.config.RekeyThreshold)
+ } else if t.algorithms != nil {
+ t.readBytesLeft = t.algorithms.r.rekeyBytes()
+ } else {
+ t.readBytesLeft = 1 << 30
+ }
+}
+
+func (t *handshakeTransport) readOnePacket(first bool) ([]byte, error) {
p, err := t.conn.readPacket()
if err != nil {
return nil, err
}
- t.readSinceKex += uint64(len(p))
+ if t.readPacketsLeft > 0 {
+ t.readPacketsLeft--
+ } else {
+ t.requestKeyExchange()
+ }
+
+ if t.readBytesLeft > 0 {
+ t.readBytesLeft -= int64(len(p))
+ } else {
+ t.requestKeyExchange()
+ }
+
if debugHandshake {
t.printPacket(p, false)
}
@@ -344,7 +411,7 @@ func (t *handshakeTransport) readOnePacket(first bool) ([]byte, error) {
return nil, err
}
- t.readSinceKex = 0
+ t.resetReadThresholds()
// By default, a key exchange is hidden from higher layers by
// translating it into msgIgnore.
@@ -427,8 +494,16 @@ func (t *handshakeTransport) writePacket(p []byte) error {
t.pendingPackets = append(t.pendingPackets, cp)
return nil
}
- t.writtenSinceKex += uint64(len(p))
- if t.writtenSinceKex > t.config.RekeyThreshold {
+
+ if t.writeBytesLeft > 0 {
+ t.writeBytesLeft -= int64(len(p))
+ } else {
+ t.requestKeyExchange()
+ }
+
+ if t.writePacketsLeft > 0 {
+ t.writePacketsLeft--
+ } else {
t.requestKeyExchange()
}
@@ -469,7 +544,8 @@ func (t *handshakeTransport) enterKeyExchange(otherInitPacket []byte) error {
magics.serverKexInit = otherInitPacket
}
- algs, err := findAgreedAlgorithms(clientInit, serverInit)
+ var err error
+ t.algorithms, err = findAgreedAlgorithms(clientInit, serverInit)
if err != nil {
return err
}
@@ -492,16 +568,16 @@ func (t *handshakeTransport) enterKeyExchange(otherInitPacket []byte) error {
}
}
- kex, ok := kexAlgoMap[algs.kex]
+ kex, ok := kexAlgoMap[t.algorithms.kex]
if !ok {
- return fmt.Errorf("ssh: unexpected key exchange algorithm %v", algs.kex)
+ return fmt.Errorf("ssh: unexpected key exchange algorithm %v", t.algorithms.kex)
}
var result *kexResult
if len(t.hostKeys) > 0 {
- result, err = t.server(kex, algs, &magics)
+ result, err = t.server(kex, t.algorithms, &magics)
} else {
- result, err = t.client(kex, algs, &magics)
+ result, err = t.client(kex, t.algorithms, &magics)
}
if err != nil {
@@ -513,7 +589,9 @@ func (t *handshakeTransport) enterKeyExchange(otherInitPacket []byte) error {
}
result.SessionID = t.sessionID
- t.conn.prepareKeyChange(algs, result)
+ if err := t.conn.prepareKeyChange(t.algorithms, result); err != nil {
+ return err
+ }
if err = t.conn.writePacket([]byte{msgNewKeys}); err != nil {
return err
}
@@ -553,11 +631,9 @@ func (t *handshakeTransport) client(kex kexAlgorithm, algs *algorithms, magics *
return nil, err
}
- if t.hostKeyCallback != nil {
- err = t.hostKeyCallback(t.dialAddress, t.remoteAddr, hostKey)
- if err != nil {
- return nil, err
- }
+ err = t.hostKeyCallback(t.dialAddress, t.remoteAddr, hostKey)
+ if err != nil {
+ return nil, err
}
return result, nil
diff --git a/vendor/golang.org/x/crypto/ssh/handshake_test.go b/vendor/golang.org/x/crypto/ssh/handshake_test.go
index 530d7d2..91d4935 100644
--- a/vendor/golang.org/x/crypto/ssh/handshake_test.go
+++ b/vendor/golang.org/x/crypto/ssh/handshake_test.go
@@ -42,7 +42,10 @@ func (t *testChecker) Check(dialAddr string, addr net.Addr, key PublicKey) error
func netPipe() (net.Conn, net.Conn, error) {
listener, err := net.Listen("tcp", "127.0.0.1:0")
if err != nil {
- return nil, nil, err
+ listener, err = net.Listen("tcp", "[::1]:0")
+ if err != nil {
+ return nil, nil, err
+ }
}
defer listener.Close()
c1, err := net.Dial("tcp", listener.Addr().String())
@@ -125,7 +128,12 @@ func TestHandshakeBasic(t *testing.T) {
t.Skip("see golang.org/issue/7237")
}
- checker := &syncChecker{make(chan int, 10)}
+ checker := &syncChecker{
+ waitCall: make(chan int, 10),
+ called: make(chan int, 10),
+ }
+
+ checker.waitCall <- 1
trC, trS, err := handshakePair(&ClientConfig{HostKeyCallback: checker.Check}, "addr", false)
if err != nil {
t.Fatalf("handshakePair: %v", err)
@@ -134,22 +142,25 @@ func TestHandshakeBasic(t *testing.T) {
defer trC.Close()
defer trS.Close()
+ // Let first kex complete normally.
<-checker.called
clientDone := make(chan int, 0)
gotHalf := make(chan int, 0)
+ const N = 20
go func() {
defer close(clientDone)
// Client writes a bunch of stuff, and does a key
// change in the middle. This should not confuse the
- // handshake in progress
- for i := 0; i < 10; i++ {
+ // handshake in progress. We do this twice, so we test
+ // that the packet buffer is reset correctly.
+ for i := 0; i < N; i++ {
p := []byte{msgRequestSuccess, byte(i)}
if err := trC.writePacket(p); err != nil {
t.Fatalf("sendPacket: %v", err)
}
- if i == 5 {
+ if (i % 10) == 5 {
<-gotHalf
// halfway through, we request a key change.
trC.requestKeyExchange()
@@ -159,32 +170,38 @@ func TestHandshakeBasic(t *testing.T) {
// write more.
<-checker.called
}
+ if (i % 10) == 7 {
+ // write some packets until the kex
+ // completes, to test buffering of
+ // packets.
+ checker.waitCall <- 1
+ }
}
}()
// Server checks that client messages come in cleanly
i := 0
err = nil
- for ; i < 10; i++ {
+ for ; i < N; i++ {
var p []byte
p, err = trS.readPacket()
if err != nil {
break
}
- if i == 5 {
+ if (i % 10) == 5 {
gotHalf <- 1
}
want := []byte{msgRequestSuccess, byte(i)}
if bytes.Compare(p, want) != 0 {
- t.Errorf("message %d: got %q, want %q", i, p, want)
+ t.Errorf("message %d: got %v, want %v", i, p, want)
}
}
<-clientDone
if err != nil && err != io.EOF {
t.Fatalf("server error: %v", err)
}
- if i != 10 {
+ if i != N {
t.Errorf("received %d messages, want 10.", i)
}
@@ -239,7 +256,10 @@ func TestForceFirstKex(t *testing.T) {
}
func TestHandshakeAutoRekeyWrite(t *testing.T) {
- checker := &syncChecker{make(chan int, 10)}
+ checker := &syncChecker{
+ called: make(chan int, 10),
+ waitCall: nil,
+ }
clientConf := &ClientConfig{HostKeyCallback: checker.Check}
clientConf.RekeyThreshold = 500
trC, trS, err := handshakePair(clientConf, "addr", false)
@@ -249,12 +269,33 @@ func TestHandshakeAutoRekeyWrite(t *testing.T) {
defer trC.Close()
defer trS.Close()
+ input := make([]byte, 251)
+ input[0] = msgRequestSuccess
+
+ done := make(chan int, 1)
+ const numPacket = 5
+ go func() {
+ defer close(done)
+ j := 0
+ for ; j < numPacket; j++ {
+ if p, err := trS.readPacket(); err != nil {
+ break
+ } else if !bytes.Equal(input, p) {
+ t.Errorf("got packet type %d, want %d", p[0], input[0])
+ }
+ }
+
+ if j != numPacket {
+ t.Errorf("got %d, want 5 messages", j)
+ }
+ }()
+
<-checker.called
- for i := 0; i < 5; i++ {
- packet := make([]byte, 251)
- packet[0] = msgRequestSuccess
- if err := trC.writePacket(packet); err != nil {
+ for i := 0; i < numPacket; i++ {
+ p := make([]byte, len(input))
+ copy(p, input)
+ if err := trC.writePacket(p); err != nil {
t.Errorf("writePacket: %v", err)
}
if i == 2 {
@@ -263,31 +304,27 @@ func TestHandshakeAutoRekeyWrite(t *testing.T) {
}
}
-
- j := 0
- for ; j < 5; j++ {
- _, err := trS.readPacket()
- if err != nil {
- break
- }
- }
-
- if j != 5 {
- t.Errorf("got %d, want 5 messages", j)
- }
+ <-done
}
type syncChecker struct {
- called chan int
+ waitCall chan int
+ called chan int
}
func (c *syncChecker) Check(dialAddr string, addr net.Addr, key PublicKey) error {
c.called <- 1
+ if c.waitCall != nil {
+ <-c.waitCall
+ }
return nil
}
func TestHandshakeAutoRekeyRead(t *testing.T) {
- sync := &syncChecker{make(chan int, 2)}
+ sync := &syncChecker{
+ called: make(chan int, 2),
+ waitCall: nil,
+ }
clientConf := &ClientConfig{
HostKeyCallback: sync.Check,
}
@@ -305,12 +342,19 @@ func TestHandshakeAutoRekeyRead(t *testing.T) {
if err := trS.writePacket(packet); err != nil {
t.Fatalf("writePacket: %v", err)
}
+
// While we read out the packet, a key change will be
// initiated.
- if _, err := trC.readPacket(); err != nil {
- t.Fatalf("readPacket(client): %v", err)
- }
+ done := make(chan int, 1)
+ go func() {
+ defer close(done)
+ if _, err := trC.readPacket(); err != nil {
+ t.Fatalf("readPacket(client): %v", err)
+ }
+ }()
+
+ <-done
<-sync.called
}
@@ -395,6 +439,7 @@ func testHandshakeErrorHandlingN(t *testing.T, readLimit, writeLimit int, couple
clientConf.SetDefaults()
clientConn := newHandshakeTransport(&errorKeyingTransport{b, -1, -1}, &clientConf, []byte{'a'}, []byte{'b'})
clientConn.hostKeyAlgorithms = []string{key.PublicKey().Type()}
+ clientConn.hostKeyCallback = InsecureIgnoreHostKey()
go clientConn.readLoop()
go clientConn.kexLoop()
@@ -484,3 +529,31 @@ func TestDisconnect(t *testing.T) {
t.Errorf("readPacket 3 succeeded")
}
}
+
+func TestHandshakeRekeyDefault(t *testing.T) {
+ clientConf := &ClientConfig{
+ Config: Config{
+ Ciphers: []string{"aes128-ctr"},
+ },
+ HostKeyCallback: InsecureIgnoreHostKey(),
+ }
+ trC, trS, err := handshakePair(clientConf, "addr", false)
+ if err != nil {
+ t.Fatalf("handshakePair: %v", err)
+ }
+ defer trC.Close()
+ defer trS.Close()
+
+ trC.writePacket([]byte{msgRequestSuccess, 0, 0})
+ trC.Close()
+
+ rgb := (1024 + trC.readBytesLeft) >> 30
+ wgb := (1024 + trC.writeBytesLeft) >> 30
+
+ if rgb != 64 {
+ t.Errorf("got rekey after %dG read, want 64G", rgb)
+ }
+ if wgb != 64 {
+ t.Errorf("got rekey after %dG write, want 64G", wgb)
+ }
+}
diff --git a/vendor/golang.org/x/crypto/ssh/kex.go b/vendor/golang.org/x/crypto/ssh/kex.go
index c87fbeb..f91c277 100644
--- a/vendor/golang.org/x/crypto/ssh/kex.go
+++ b/vendor/golang.org/x/crypto/ssh/kex.go
@@ -383,8 +383,8 @@ func init() {
// 4253 and Oakley Group 2 in RFC 2409.
p, _ := new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF", 16)
kexAlgoMap[kexAlgoDH1SHA1] = &dhGroup{
- g: new(big.Int).SetInt64(2),
- p: p,
+ g: new(big.Int).SetInt64(2),
+ p: p,
pMinus1: new(big.Int).Sub(p, bigOne),
}
@@ -393,8 +393,8 @@ func init() {
p, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF", 16)
kexAlgoMap[kexAlgoDH14SHA1] = &dhGroup{
- g: new(big.Int).SetInt64(2),
- p: p,
+ g: new(big.Int).SetInt64(2),
+ p: p,
pMinus1: new(big.Int).Sub(p, bigOne),
}
diff --git a/vendor/golang.org/x/crypto/ssh/keys.go b/vendor/golang.org/x/crypto/ssh/keys.go
index f38de98..4c8b1a8 100644
--- a/vendor/golang.org/x/crypto/ssh/keys.go
+++ b/vendor/golang.org/x/crypto/ssh/keys.go
@@ -756,6 +756,18 @@ func ParsePrivateKey(pemBytes []byte) (Signer, error) {
return NewSignerFromKey(key)
}
+// ParsePrivateKeyWithPassphrase returns a Signer from a PEM encoded private
+// key and passphrase. It supports the same keys as
+// ParseRawPrivateKeyWithPassphrase.
+func ParsePrivateKeyWithPassphrase(pemBytes, passPhrase []byte) (Signer, error) {
+ key, err := ParseRawPrivateKeyWithPassphrase(pemBytes, passPhrase)
+ if err != nil {
+ return nil, err
+ }
+
+ return NewSignerFromKey(key)
+}
+
// encryptedBlock tells whether a private key is
// encrypted by examining its Proc-Type header
// for a mention of ENCRYPTED
@@ -790,6 +802,37 @@ func ParseRawPrivateKey(pemBytes []byte) (interface{}, error) {
}
}
+func ParseRawPrivateKeyWithPassphrase(pemBytes, passPhrase []byte) (interface{}, error) {
+ block, _ := pem.Decode(pemBytes)
+ if block == nil {
+ return nil, errors.New("ssh: no key found")
+ }
+ buf := block.Bytes
+
+ if encryptedBlock(block) {
+ if x509.IsEncryptedPEMBlock(block) {
+ var err error
+ buf, err = x509.DecryptPEMBlock(block, passPhrase)
+ if err != nil {
+ return nil, fmt.Errorf("ssh: cannot decode encrypted private keys: %v", err)
+ }
+ }
+ }
+
+ switch block.Type {
+ case "RSA PRIVATE KEY":
+ return x509.ParsePKCS1PrivateKey(buf)
+ case "EC PRIVATE KEY":
+ return x509.ParseECPrivateKey(buf)
+ case "DSA PRIVATE KEY":
+ return ParseDSAPrivateKey(buf)
+ case "OPENSSH PRIVATE KEY":
+ return parseOpenSSHPrivateKey(buf)
+ default:
+ return nil, fmt.Errorf("ssh: unsupported key type %q", block.Type)
+ }
+}
+
// ParseDSAPrivateKey returns a DSA private key from its ASN.1 DER encoding, as
// specified by the OpenSSL DSA man page.
func ParseDSAPrivateKey(der []byte) (*dsa.PrivateKey, error) {
@@ -824,7 +867,7 @@ func ParseDSAPrivateKey(der []byte) (*dsa.PrivateKey, error) {
// Implemented based on the documentation at
// https://github.com/openssh/openssh-portable/blob/master/PROTOCOL.key
-func parseOpenSSHPrivateKey(key []byte) (*ed25519.PrivateKey, error) {
+func parseOpenSSHPrivateKey(key []byte) (crypto.PrivateKey, error) {
magic := append([]byte("openssh-key-v1"), 0)
if !bytes.Equal(magic, key[0:len(magic)]) {
return nil, errors.New("ssh: invalid openssh private key format")
@@ -844,14 +887,15 @@ func parseOpenSSHPrivateKey(key []byte) (*ed25519.PrivateKey, error) {
return nil, err
}
+ if w.KdfName != "none" || w.CipherName != "none" {
+ return nil, errors.New("ssh: cannot decode encrypted private keys")
+ }
+
pk1 := struct {
Check1 uint32
Check2 uint32
Keytype string
- Pub []byte
- Priv []byte
- Comment string
- Pad []byte `ssh:"rest"`
+ Rest []byte `ssh:"rest"`
}{}
if err := Unmarshal(w.PrivKeyBlock, &pk1); err != nil {
@@ -862,24 +906,75 @@ func parseOpenSSHPrivateKey(key []byte) (*ed25519.PrivateKey, error) {
return nil, errors.New("ssh: checkint mismatch")
}
- // we only handle ed25519 keys currently
- if pk1.Keytype != KeyAlgoED25519 {
+ // we only handle ed25519 and rsa keys currently
+ switch pk1.Keytype {
+ case KeyAlgoRSA:
+ // https://github.com/openssh/openssh-portable/blob/master/sshkey.c#L2760-L2773
+ key := struct {
+ N *big.Int
+ E *big.Int
+ D *big.Int
+ Iqmp *big.Int
+ P *big.Int
+ Q *big.Int
+ Comment string
+ Pad []byte `ssh:"rest"`
+ }{}
+
+ if err := Unmarshal(pk1.Rest, &key); err != nil {
+ return nil, err
+ }
+
+ for i, b := range key.Pad {
+ if int(b) != i+1 {
+ return nil, errors.New("ssh: padding not as expected")
+ }
+ }
+
+ pk := &rsa.PrivateKey{
+ PublicKey: rsa.PublicKey{
+ N: key.N,
+ E: int(key.E.Int64()),
+ },
+ D: key.D,
+ Primes: []*big.Int{key.P, key.Q},
+ }
+
+ if err := pk.Validate(); err != nil {
+ return nil, err
+ }
+
+ pk.Precompute()
+
+ return pk, nil
+ case KeyAlgoED25519:
+ key := struct {
+ Pub []byte
+ Priv []byte
+ Comment string
+ Pad []byte `ssh:"rest"`
+ }{}
+
+ if err := Unmarshal(pk1.Rest, &key); err != nil {
+ return nil, err
+ }
+
+ if len(key.Priv) != ed25519.PrivateKeySize {
+ return nil, errors.New("ssh: private key unexpected length")
+ }
+
+ for i, b := range key.Pad {
+ if int(b) != i+1 {
+ return nil, errors.New("ssh: padding not as expected")
+ }
+ }
+
+ pk := ed25519.PrivateKey(make([]byte, ed25519.PrivateKeySize))
+ copy(pk, key.Priv)
+ return &pk, nil
+ default:
return nil, errors.New("ssh: unhandled key type")
}
-
- for i, b := range pk1.Pad {
- if int(b) != i+1 {
- return nil, errors.New("ssh: padding not as expected")
- }
- }
-
- if len(pk1.Priv) != ed25519.PrivateKeySize {
- return nil, errors.New("ssh: private key unexpected length")
- }
-
- pk := ed25519.PrivateKey(make([]byte, ed25519.PrivateKeySize))
- copy(pk, pk1.Priv)
- return &pk, nil
}
// FingerprintLegacyMD5 returns the user presentation of the key's
diff --git a/vendor/golang.org/x/crypto/ssh/keys_test.go b/vendor/golang.org/x/crypto/ssh/keys_test.go
index a65e87e..2bacc52 100644
--- a/vendor/golang.org/x/crypto/ssh/keys_test.go
+++ b/vendor/golang.org/x/crypto/ssh/keys_test.go
@@ -148,6 +148,25 @@ func TestParseEncryptedPrivateKeysFails(t *testing.T) {
}
}
+// Parse encrypted private keys with passphrase
+func TestParseEncryptedPrivateKeysWithPassphrase(t *testing.T) {
+ data := []byte("sign me")
+ for _, tt := range testdata.PEMEncryptedKeys {
+ s, err := ParsePrivateKeyWithPassphrase(tt.PEMBytes, []byte(tt.EncryptionKey))
+ if err != nil {
+ t.Fatalf("ParsePrivateKeyWithPassphrase returned error: %s", err)
+ continue
+ }
+ sig, err := s.Sign(rand.Reader, data)
+ if err != nil {
+ t.Fatalf("dsa.Sign: %v", err)
+ }
+ if err := s.PublicKey().Verify(data, sig); err != nil {
+ t.Errorf("Verify failed: %v", err)
+ }
+ }
+}
+
func TestParseDSA(t *testing.T) {
// We actually exercise the ParsePrivateKey codepath here, as opposed to
// using the ParseRawPrivateKey+NewSignerFromKey path that testdata_test.go
diff --git a/vendor/golang.org/x/crypto/ssh/knownhosts/knownhosts.go b/vendor/golang.org/x/crypto/ssh/knownhosts/knownhosts.go
new file mode 100644
index 0000000..ea92b29
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/knownhosts/knownhosts.go
@@ -0,0 +1,546 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package knownhosts implements a parser for the OpenSSH
+// known_hosts host key database.
+package knownhosts
+
+import (
+ "bufio"
+ "bytes"
+ "crypto/hmac"
+ "crypto/rand"
+ "crypto/sha1"
+ "encoding/base64"
+ "errors"
+ "fmt"
+ "io"
+ "net"
+ "os"
+ "strings"
+
+ "golang.org/x/crypto/ssh"
+)
+
+// See the sshd manpage
+// (http://man.openbsd.org/sshd#SSH_KNOWN_HOSTS_FILE_FORMAT) for
+// background.
+
+type addr struct{ host, port string }
+
+func (a *addr) String() string {
+ h := a.host
+ if strings.Contains(h, ":") {
+ h = "[" + h + "]"
+ }
+ return h + ":" + a.port
+}
+
+type matcher interface {
+ match([]addr) bool
+}
+
+type hostPattern struct {
+ negate bool
+ addr addr
+}
+
+func (p *hostPattern) String() string {
+ n := ""
+ if p.negate {
+ n = "!"
+ }
+
+ return n + p.addr.String()
+}
+
+type hostPatterns []hostPattern
+
+func (ps hostPatterns) match(addrs []addr) bool {
+ matched := false
+ for _, p := range ps {
+ for _, a := range addrs {
+ m := p.match(a)
+ if !m {
+ continue
+ }
+ if p.negate {
+ return false
+ }
+ matched = true
+ }
+ }
+ return matched
+}
+
+// See
+// https://android.googlesource.com/platform/external/openssh/+/ab28f5495c85297e7a597c1ba62e996416da7c7e/addrmatch.c
+// The matching of * has no regard for separators, unlike filesystem globs
+func wildcardMatch(pat []byte, str []byte) bool {
+ for {
+ if len(pat) == 0 {
+ return len(str) == 0
+ }
+ if len(str) == 0 {
+ return false
+ }
+
+ if pat[0] == '*' {
+ if len(pat) == 1 {
+ return true
+ }
+
+ for j := range str {
+ if wildcardMatch(pat[1:], str[j:]) {
+ return true
+ }
+ }
+ return false
+ }
+
+ if pat[0] == '?' || pat[0] == str[0] {
+ pat = pat[1:]
+ str = str[1:]
+ } else {
+ return false
+ }
+ }
+}
+
+func (l *hostPattern) match(a addr) bool {
+ return wildcardMatch([]byte(l.addr.host), []byte(a.host)) && l.addr.port == a.port
+}
+
+type keyDBLine struct {
+ cert bool
+ matcher matcher
+ knownKey KnownKey
+}
+
+func serialize(k ssh.PublicKey) string {
+ return k.Type() + " " + base64.StdEncoding.EncodeToString(k.Marshal())
+}
+
+func (l *keyDBLine) match(addrs []addr) bool {
+ return l.matcher.match(addrs)
+}
+
+type hostKeyDB struct {
+ // Serialized version of revoked keys
+ revoked map[string]*KnownKey
+ lines []keyDBLine
+}
+
+func newHostKeyDB() *hostKeyDB {
+ db := &hostKeyDB{
+ revoked: make(map[string]*KnownKey),
+ }
+
+ return db
+}
+
+func keyEq(a, b ssh.PublicKey) bool {
+ return bytes.Equal(a.Marshal(), b.Marshal())
+}
+
+// IsAuthorityForHost can be used as a callback in ssh.CertChecker
+func (db *hostKeyDB) IsHostAuthority(remote ssh.PublicKey, address string) bool {
+ h, p, err := net.SplitHostPort(address)
+ if err != nil {
+ return false
+ }
+ a := addr{host: h, port: p}
+
+ for _, l := range db.lines {
+ if l.cert && keyEq(l.knownKey.Key, remote) && l.match([]addr{a}) {
+ return true
+ }
+ }
+ return false
+}
+
+// IsRevoked can be used as a callback in ssh.CertChecker
+func (db *hostKeyDB) IsRevoked(key *ssh.Certificate) bool {
+ _, ok := db.revoked[string(key.Marshal())]
+ return ok
+}
+
+const markerCert = "@cert-authority"
+const markerRevoked = "@revoked"
+
+func nextWord(line []byte) (string, []byte) {
+ i := bytes.IndexAny(line, "\t ")
+ if i == -1 {
+ return string(line), nil
+ }
+
+ return string(line[:i]), bytes.TrimSpace(line[i:])
+}
+
+func parseLine(line []byte) (marker, host string, key ssh.PublicKey, err error) {
+ if w, next := nextWord(line); w == markerCert || w == markerRevoked {
+ marker = w
+ line = next
+ }
+
+ host, line = nextWord(line)
+ if len(line) == 0 {
+ return "", "", nil, errors.New("knownhosts: missing host pattern")
+ }
+
+ // ignore the keytype as it's in the key blob anyway.
+ _, line = nextWord(line)
+ if len(line) == 0 {
+ return "", "", nil, errors.New("knownhosts: missing key type pattern")
+ }
+
+ keyBlob, _ := nextWord(line)
+
+ keyBytes, err := base64.StdEncoding.DecodeString(keyBlob)
+ if err != nil {
+ return "", "", nil, err
+ }
+ key, err = ssh.ParsePublicKey(keyBytes)
+ if err != nil {
+ return "", "", nil, err
+ }
+
+ return marker, host, key, nil
+}
+
+func (db *hostKeyDB) parseLine(line []byte, filename string, linenum int) error {
+ marker, pattern, key, err := parseLine(line)
+ if err != nil {
+ return err
+ }
+
+ if marker == markerRevoked {
+ db.revoked[string(key.Marshal())] = &KnownKey{
+ Key: key,
+ Filename: filename,
+ Line: linenum,
+ }
+
+ return nil
+ }
+
+ entry := keyDBLine{
+ cert: marker == markerCert,
+ knownKey: KnownKey{
+ Filename: filename,
+ Line: linenum,
+ Key: key,
+ },
+ }
+
+ if pattern[0] == '|' {
+ entry.matcher, err = newHashedHost(pattern)
+ } else {
+ entry.matcher, err = newHostnameMatcher(pattern)
+ }
+
+ if err != nil {
+ return err
+ }
+
+ db.lines = append(db.lines, entry)
+ return nil
+}
+
+func newHostnameMatcher(pattern string) (matcher, error) {
+ var hps hostPatterns
+ for _, p := range strings.Split(pattern, ",") {
+ if len(p) == 0 {
+ continue
+ }
+
+ var a addr
+ var negate bool
+ if p[0] == '!' {
+ negate = true
+ p = p[1:]
+ }
+
+ if len(p) == 0 {
+ return nil, errors.New("knownhosts: negation without following hostname")
+ }
+
+ var err error
+ if p[0] == '[' {
+ a.host, a.port, err = net.SplitHostPort(p)
+ if err != nil {
+ return nil, err
+ }
+ } else {
+ a.host, a.port, err = net.SplitHostPort(p)
+ if err != nil {
+ a.host = p
+ a.port = "22"
+ }
+ }
+ hps = append(hps, hostPattern{
+ negate: negate,
+ addr: a,
+ })
+ }
+ return hps, nil
+}
+
+// KnownKey represents a key declared in a known_hosts file.
+type KnownKey struct {
+ Key ssh.PublicKey
+ Filename string
+ Line int
+}
+
+func (k *KnownKey) String() string {
+ return fmt.Sprintf("%s:%d: %s", k.Filename, k.Line, serialize(k.Key))
+}
+
+// KeyError is returned if we did not find the key in the host key
+// database, or there was a mismatch. Typically, in batch
+// applications, this should be interpreted as failure. Interactive
+// applications can offer an interactive prompt to the user.
+type KeyError struct {
+ // Want holds the accepted host keys. For each key algorithm,
+ // there can be one hostkey. If Want is empty, the host is
+ // unknown. If Want is non-empty, there was a mismatch, which
+ // can signify a MITM attack.
+ Want []KnownKey
+}
+
+func (u *KeyError) Error() string {
+ if len(u.Want) == 0 {
+ return "knownhosts: key is unknown"
+ }
+ return "knownhosts: key mismatch"
+}
+
+// RevokedError is returned if we found a key that was revoked.
+type RevokedError struct {
+ Revoked KnownKey
+}
+
+func (r *RevokedError) Error() string {
+ return "knownhosts: key is revoked"
+}
+
+// check checks a key against the host database. This should not be
+// used for verifying certificates.
+func (db *hostKeyDB) check(address string, remote net.Addr, remoteKey ssh.PublicKey) error {
+ if revoked := db.revoked[string(remoteKey.Marshal())]; revoked != nil {
+ return &RevokedError{Revoked: *revoked}
+ }
+
+ host, port, err := net.SplitHostPort(remote.String())
+ if err != nil {
+ return fmt.Errorf("knownhosts: SplitHostPort(%s): %v", remote, err)
+ }
+
+ addrs := []addr{
+ {host, port},
+ }
+
+ if address != "" {
+ host, port, err := net.SplitHostPort(address)
+ if err != nil {
+ return fmt.Errorf("knownhosts: SplitHostPort(%s): %v", address, err)
+ }
+
+ addrs = append(addrs, addr{host, port})
+ }
+
+ return db.checkAddrs(addrs, remoteKey)
+}
+
+// checkAddrs checks if we can find the given public key for any of
+// the given addresses. If we only find an entry for the IP address,
+// or only the hostname, then this still succeeds.
+func (db *hostKeyDB) checkAddrs(addrs []addr, remoteKey ssh.PublicKey) error {
+ // TODO(hanwen): are these the right semantics? What if there
+ // is just a key for the IP address, but not for the
+ // hostname?
+
+ // Algorithm => key.
+ knownKeys := map[string]KnownKey{}
+ for _, l := range db.lines {
+ if l.match(addrs) {
+ typ := l.knownKey.Key.Type()
+ if _, ok := knownKeys[typ]; !ok {
+ knownKeys[typ] = l.knownKey
+ }
+ }
+ }
+
+ keyErr := &KeyError{}
+ for _, v := range knownKeys {
+ keyErr.Want = append(keyErr.Want, v)
+ }
+
+ // Unknown remote host.
+ if len(knownKeys) == 0 {
+ return keyErr
+ }
+
+ // If the remote host starts using a different, unknown key type, we
+ // also interpret that as a mismatch.
+ if known, ok := knownKeys[remoteKey.Type()]; !ok || !keyEq(known.Key, remoteKey) {
+ return keyErr
+ }
+
+ return nil
+}
+
+// The Read function parses file contents.
+func (db *hostKeyDB) Read(r io.Reader, filename string) error {
+ scanner := bufio.NewScanner(r)
+
+ lineNum := 0
+ for scanner.Scan() {
+ lineNum++
+ line := scanner.Bytes()
+ line = bytes.TrimSpace(line)
+ if len(line) == 0 || line[0] == '#' {
+ continue
+ }
+
+ if err := db.parseLine(line, filename, lineNum); err != nil {
+ return fmt.Errorf("knownhosts: %s:%d: %v", filename, lineNum, err)
+ }
+ }
+ return scanner.Err()
+}
+
+// New creates a host key callback from the given OpenSSH host key
+// files. The returned callback is for use in
+// ssh.ClientConfig.HostKeyCallback. Hashed hostnames are not supported.
+func New(files ...string) (ssh.HostKeyCallback, error) {
+ db := newHostKeyDB()
+ for _, fn := range files {
+ f, err := os.Open(fn)
+ if err != nil {
+ return nil, err
+ }
+ defer f.Close()
+ if err := db.Read(f, fn); err != nil {
+ return nil, err
+ }
+ }
+
+ var certChecker ssh.CertChecker
+ certChecker.IsHostAuthority = db.IsHostAuthority
+ certChecker.IsRevoked = db.IsRevoked
+ certChecker.HostKeyFallback = db.check
+
+ return certChecker.CheckHostKey, nil
+}
+
+// Normalize normalizes an address into the form used in known_hosts
+func Normalize(address string) string {
+ host, port, err := net.SplitHostPort(address)
+ if err != nil {
+ host = address
+ port = "22"
+ }
+ entry := host
+ if port != "22" {
+ entry = "[" + entry + "]:" + port
+ } else if strings.Contains(host, ":") && !strings.HasPrefix(host, "[") {
+ entry = "[" + entry + "]"
+ }
+ return entry
+}
+
+// Line returns a line to add append to the known_hosts files.
+func Line(addresses []string, key ssh.PublicKey) string {
+ var trimmed []string
+ for _, a := range addresses {
+ trimmed = append(trimmed, Normalize(a))
+ }
+
+ return strings.Join(trimmed, ",") + " " + serialize(key)
+}
+
+// HashHostname hashes the given hostname. The hostname is not
+// normalized before hashing.
+func HashHostname(hostname string) string {
+ // TODO(hanwen): check if we can safely normalize this always.
+ salt := make([]byte, sha1.Size)
+
+ _, err := rand.Read(salt)
+ if err != nil {
+ panic(fmt.Sprintf("crypto/rand failure %v", err))
+ }
+
+ hash := hashHost(hostname, salt)
+ return encodeHash(sha1HashType, salt, hash)
+}
+
+func decodeHash(encoded string) (hashType string, salt, hash []byte, err error) {
+ if len(encoded) == 0 || encoded[0] != '|' {
+ err = errors.New("knownhosts: hashed host must start with '|'")
+ return
+ }
+ components := strings.Split(encoded, "|")
+ if len(components) != 4 {
+ err = fmt.Errorf("knownhosts: got %d components, want 3", len(components))
+ return
+ }
+
+ hashType = components[1]
+ if salt, err = base64.StdEncoding.DecodeString(components[2]); err != nil {
+ return
+ }
+ if hash, err = base64.StdEncoding.DecodeString(components[3]); err != nil {
+ return
+ }
+ return
+}
+
+func encodeHash(typ string, salt []byte, hash []byte) string {
+ return strings.Join([]string{"",
+ typ,
+ base64.StdEncoding.EncodeToString(salt),
+ base64.StdEncoding.EncodeToString(hash),
+ }, "|")
+}
+
+// See https://android.googlesource.com/platform/external/openssh/+/ab28f5495c85297e7a597c1ba62e996416da7c7e/hostfile.c#120
+func hashHost(hostname string, salt []byte) []byte {
+ mac := hmac.New(sha1.New, salt)
+ mac.Write([]byte(hostname))
+ return mac.Sum(nil)
+}
+
+type hashedHost struct {
+ salt []byte
+ hash []byte
+}
+
+const sha1HashType = "1"
+
+func newHashedHost(encoded string) (*hashedHost, error) {
+ typ, salt, hash, err := decodeHash(encoded)
+ if err != nil {
+ return nil, err
+ }
+
+ // The type field seems for future algorithm agility, but it's
+ // actually hardcoded in openssh currently, see
+ // https://android.googlesource.com/platform/external/openssh/+/ab28f5495c85297e7a597c1ba62e996416da7c7e/hostfile.c#120
+ if typ != sha1HashType {
+ return nil, fmt.Errorf("knownhosts: got hash type %s, must be '1'", typ)
+ }
+
+ return &hashedHost{salt: salt, hash: hash}, nil
+}
+
+func (h *hashedHost) match(addrs []addr) bool {
+ for _, a := range addrs {
+ if bytes.Equal(hashHost(Normalize(a.String()), h.salt), h.hash) {
+ return true
+ }
+ }
+ return false
+}
diff --git a/vendor/golang.org/x/crypto/ssh/knownhosts/knownhosts_test.go b/vendor/golang.org/x/crypto/ssh/knownhosts/knownhosts_test.go
new file mode 100644
index 0000000..be7cc0e
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/knownhosts/knownhosts_test.go
@@ -0,0 +1,329 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package knownhosts
+
+import (
+ "bytes"
+ "fmt"
+ "net"
+ "reflect"
+ "testing"
+
+ "golang.org/x/crypto/ssh"
+)
+
+const edKeyStr = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGBAarftlLeoyf+v+nVchEZII/vna2PCV8FaX4vsF5BX"
+const alternateEdKeyStr = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIXffBYeYL+WVzVru8npl5JHt2cjlr4ornFTWzoij9sx"
+const ecKeyStr = "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBNLCu01+wpXe3xB5olXCN4SqU2rQu0qjSRKJO4Bg+JRCPU+ENcgdA5srTU8xYDz/GEa4dzK5ldPw4J/gZgSXCMs="
+
+var ecKey, alternateEdKey, edKey ssh.PublicKey
+var testAddr = &net.TCPAddr{
+ IP: net.IP{198, 41, 30, 196},
+ Port: 22,
+}
+
+var testAddr6 = &net.TCPAddr{
+ IP: net.IP{198, 41, 30, 196,
+ 1, 2, 3, 4,
+ 1, 2, 3, 4,
+ 1, 2, 3, 4,
+ },
+ Port: 22,
+}
+
+func init() {
+ var err error
+ ecKey, _, _, _, err = ssh.ParseAuthorizedKey([]byte(ecKeyStr))
+ if err != nil {
+ panic(err)
+ }
+ edKey, _, _, _, err = ssh.ParseAuthorizedKey([]byte(edKeyStr))
+ if err != nil {
+ panic(err)
+ }
+ alternateEdKey, _, _, _, err = ssh.ParseAuthorizedKey([]byte(alternateEdKeyStr))
+ if err != nil {
+ panic(err)
+ }
+}
+
+func testDB(t *testing.T, s string) *hostKeyDB {
+ db := newHostKeyDB()
+ if err := db.Read(bytes.NewBufferString(s), "testdb"); err != nil {
+ t.Fatalf("Read: %v", err)
+ }
+
+ return db
+}
+
+func TestRevoked(t *testing.T) {
+ db := testDB(t, "\n\n@revoked * "+edKeyStr+"\n")
+ want := &RevokedError{
+ Revoked: KnownKey{
+ Key: edKey,
+ Filename: "testdb",
+ Line: 3,
+ },
+ }
+ if err := db.check("", &net.TCPAddr{
+ Port: 42,
+ }, edKey); err == nil {
+ t.Fatal("no error for revoked key")
+ } else if !reflect.DeepEqual(want, err) {
+ t.Fatalf("got %#v, want %#v", want, err)
+ }
+}
+
+func TestHostAuthority(t *testing.T) {
+ for _, m := range []struct {
+ authorityFor string
+ address string
+
+ good bool
+ }{
+ {authorityFor: "localhost", address: "localhost:22", good: true},
+ {authorityFor: "localhost", address: "localhost", good: false},
+ {authorityFor: "localhost", address: "localhost:1234", good: false},
+ {authorityFor: "[localhost]:1234", address: "localhost:1234", good: true},
+ {authorityFor: "[localhost]:1234", address: "localhost:22", good: false},
+ {authorityFor: "[localhost]:1234", address: "localhost", good: false},
+ } {
+ db := testDB(t, `@cert-authority `+m.authorityFor+` `+edKeyStr)
+ if ok := db.IsHostAuthority(db.lines[0].knownKey.Key, m.address); ok != m.good {
+ t.Errorf("IsHostAuthority: authority %s, address %s, wanted good = %v, got good = %v",
+ m.authorityFor, m.address, m.good, ok)
+ }
+ }
+}
+
+func TestBracket(t *testing.T) {
+ db := testDB(t, `[git.eclipse.org]:29418,[198.41.30.196]:29418 `+edKeyStr)
+
+ if err := db.check("git.eclipse.org:29418", &net.TCPAddr{
+ IP: net.IP{198, 41, 30, 196},
+ Port: 29418,
+ }, edKey); err != nil {
+ t.Errorf("got error %v, want none", err)
+ }
+
+ if err := db.check("git.eclipse.org:29419", &net.TCPAddr{
+ Port: 42,
+ }, edKey); err == nil {
+ t.Fatalf("no error for unknown address")
+ } else if ke, ok := err.(*KeyError); !ok {
+ t.Fatalf("got type %T, want *KeyError", err)
+ } else if len(ke.Want) > 0 {
+ t.Fatalf("got Want %v, want []", ke.Want)
+ }
+}
+
+func TestNewKeyType(t *testing.T) {
+ str := fmt.Sprintf("%s %s", testAddr, edKeyStr)
+ db := testDB(t, str)
+ if err := db.check("", testAddr, ecKey); err == nil {
+ t.Fatalf("no error for unknown address")
+ } else if ke, ok := err.(*KeyError); !ok {
+ t.Fatalf("got type %T, want *KeyError", err)
+ } else if len(ke.Want) == 0 {
+ t.Fatalf("got empty KeyError.Want")
+ }
+}
+
+func TestSameKeyType(t *testing.T) {
+ str := fmt.Sprintf("%s %s", testAddr, edKeyStr)
+ db := testDB(t, str)
+ if err := db.check("", testAddr, alternateEdKey); err == nil {
+ t.Fatalf("no error for unknown address")
+ } else if ke, ok := err.(*KeyError); !ok {
+ t.Fatalf("got type %T, want *KeyError", err)
+ } else if len(ke.Want) == 0 {
+ t.Fatalf("got empty KeyError.Want")
+ } else if got, want := ke.Want[0].Key.Marshal(), edKey.Marshal(); !bytes.Equal(got, want) {
+ t.Fatalf("got key %q, want %q", got, want)
+ }
+}
+
+func TestIPAddress(t *testing.T) {
+ str := fmt.Sprintf("%s %s", testAddr, edKeyStr)
+ db := testDB(t, str)
+ if err := db.check("", testAddr, edKey); err != nil {
+ t.Errorf("got error %q, want none", err)
+ }
+}
+
+func TestIPv6Address(t *testing.T) {
+ str := fmt.Sprintf("%s %s", testAddr6, edKeyStr)
+ db := testDB(t, str)
+
+ if err := db.check("", testAddr6, edKey); err != nil {
+ t.Errorf("got error %q, want none", err)
+ }
+}
+
+func TestBasic(t *testing.T) {
+ str := fmt.Sprintf("#comment\n\nserver.org,%s %s\notherhost %s", testAddr, edKeyStr, ecKeyStr)
+ db := testDB(t, str)
+ if err := db.check("server.org:22", testAddr, edKey); err != nil {
+ t.Errorf("got error %q, want none", err)
+ }
+
+ want := KnownKey{
+ Key: edKey,
+ Filename: "testdb",
+ Line: 3,
+ }
+ if err := db.check("server.org:22", testAddr, ecKey); err == nil {
+ t.Errorf("succeeded, want KeyError")
+ } else if ke, ok := err.(*KeyError); !ok {
+ t.Errorf("got %T, want *KeyError", err)
+ } else if len(ke.Want) != 1 {
+ t.Errorf("got %v, want 1 entry", ke)
+ } else if !reflect.DeepEqual(ke.Want[0], want) {
+ t.Errorf("got %v, want %v", ke.Want[0], want)
+ }
+}
+
+func TestNegate(t *testing.T) {
+ str := fmt.Sprintf("%s,!server.org %s", testAddr, edKeyStr)
+ db := testDB(t, str)
+ if err := db.check("server.org:22", testAddr, ecKey); err == nil {
+ t.Errorf("succeeded")
+ } else if ke, ok := err.(*KeyError); !ok {
+ t.Errorf("got error type %T, want *KeyError", err)
+ } else if len(ke.Want) != 0 {
+ t.Errorf("got expected keys %d (first of type %s), want []", len(ke.Want), ke.Want[0].Key.Type())
+ }
+}
+
+func TestWildcard(t *testing.T) {
+ str := fmt.Sprintf("server*.domain %s", edKeyStr)
+ db := testDB(t, str)
+
+ want := &KeyError{
+ Want: []KnownKey{{
+ Filename: "testdb",
+ Line: 1,
+ Key: edKey,
+ }},
+ }
+
+ got := db.check("server.domain:22", &net.TCPAddr{}, ecKey)
+ if !reflect.DeepEqual(got, want) {
+ t.Errorf("got %s, want %s", got, want)
+ }
+}
+
+func TestLine(t *testing.T) {
+ for in, want := range map[string]string{
+ "server.org": "server.org " + edKeyStr,
+ "server.org:22": "server.org " + edKeyStr,
+ "server.org:23": "[server.org]:23 " + edKeyStr,
+ "[c629:1ec4:102:304:102:304:102:304]:22": "[c629:1ec4:102:304:102:304:102:304] " + edKeyStr,
+ "[c629:1ec4:102:304:102:304:102:304]:23": "[c629:1ec4:102:304:102:304:102:304]:23 " + edKeyStr,
+ } {
+ if got := Line([]string{in}, edKey); got != want {
+ t.Errorf("Line(%q) = %q, want %q", in, got, want)
+ }
+ }
+}
+
+func TestWildcardMatch(t *testing.T) {
+ for _, c := range []struct {
+ pat, str string
+ want bool
+ }{
+ {"a?b", "abb", true},
+ {"ab", "abc", false},
+ {"abc", "ab", false},
+ {"a*b", "axxxb", true},
+ {"a*b", "axbxb", true},
+ {"a*b", "axbxbc", false},
+ {"a*?", "axbxc", true},
+ {"a*b*", "axxbxxxxxx", true},
+ {"a*b*c", "axxbxxxxxxc", true},
+ {"a*b*?", "axxbxxxxxxc", true},
+ {"a*b*z", "axxbxxbxxxz", true},
+ {"a*b*z", "axxbxxzxxxz", true},
+ {"a*b*z", "axxbxxzxxx", false},
+ } {
+ got := wildcardMatch([]byte(c.pat), []byte(c.str))
+ if got != c.want {
+ t.Errorf("wildcardMatch(%q, %q) = %v, want %v", c.pat, c.str, got, c.want)
+ }
+
+ }
+}
+
+// TODO(hanwen): test coverage for certificates.
+
+const testHostname = "hostname"
+
+// generated with keygen -H -f
+const encodedTestHostnameHash = "|1|IHXZvQMvTcZTUU29+2vXFgx8Frs=|UGccIWfRVDwilMBnA3WJoRAC75Y="
+
+func TestHostHash(t *testing.T) {
+ testHostHash(t, testHostname, encodedTestHostnameHash)
+}
+
+func TestHashList(t *testing.T) {
+ encoded := HashHostname(testHostname)
+ testHostHash(t, testHostname, encoded)
+}
+
+func testHostHash(t *testing.T, hostname, encoded string) {
+ typ, salt, hash, err := decodeHash(encoded)
+ if err != nil {
+ t.Fatalf("decodeHash: %v", err)
+ }
+
+ if got := encodeHash(typ, salt, hash); got != encoded {
+ t.Errorf("got encoding %s want %s", got, encoded)
+ }
+
+ if typ != sha1HashType {
+ t.Fatalf("got hash type %q, want %q", typ, sha1HashType)
+ }
+
+ got := hashHost(hostname, salt)
+ if !bytes.Equal(got, hash) {
+ t.Errorf("got hash %x want %x", got, hash)
+ }
+}
+
+func TestNormalize(t *testing.T) {
+ for in, want := range map[string]string{
+ "127.0.0.1:22": "127.0.0.1",
+ "[127.0.0.1]:22": "127.0.0.1",
+ "[127.0.0.1]:23": "[127.0.0.1]:23",
+ "127.0.0.1:23": "[127.0.0.1]:23",
+ "[a.b.c]:22": "a.b.c",
+ "[abcd:abcd:abcd:abcd]": "[abcd:abcd:abcd:abcd]",
+ "[abcd:abcd:abcd:abcd]:22": "[abcd:abcd:abcd:abcd]",
+ "[abcd:abcd:abcd:abcd]:23": "[abcd:abcd:abcd:abcd]:23",
+ } {
+ got := Normalize(in)
+ if got != want {
+ t.Errorf("Normalize(%q) = %q, want %q", in, got, want)
+ }
+ }
+}
+
+func TestHashedHostkeyCheck(t *testing.T) {
+ str := fmt.Sprintf("%s %s", HashHostname(testHostname), edKeyStr)
+ db := testDB(t, str)
+ if err := db.check(testHostname+":22", testAddr, edKey); err != nil {
+ t.Errorf("check(%s): %v", testHostname, err)
+ }
+ want := &KeyError{
+ Want: []KnownKey{{
+ Filename: "testdb",
+ Line: 1,
+ Key: edKey,
+ }},
+ }
+ if got := db.check(testHostname+":22", testAddr, alternateEdKey); !reflect.DeepEqual(got, want) {
+ t.Errorf("got error %v, want %v", got, want)
+ }
+}
diff --git a/vendor/golang.org/x/crypto/ssh/mac.go b/vendor/golang.org/x/crypto/ssh/mac.go
index 07744ad..c07a062 100644
--- a/vendor/golang.org/x/crypto/ssh/mac.go
+++ b/vendor/golang.org/x/crypto/ssh/mac.go
@@ -15,6 +15,7 @@ import (
type macMode struct {
keySize int
+ etm bool
new func(key []byte) hash.Hash
}
@@ -45,13 +46,16 @@ func (t truncatingMAC) Size() int {
func (t truncatingMAC) BlockSize() int { return t.hmac.BlockSize() }
var macModes = map[string]*macMode{
- "hmac-sha2-256": {32, func(key []byte) hash.Hash {
+ "hmac-sha2-256-etm@openssh.com": {32, true, func(key []byte) hash.Hash {
return hmac.New(sha256.New, key)
}},
- "hmac-sha1": {20, func(key []byte) hash.Hash {
+ "hmac-sha2-256": {32, false, func(key []byte) hash.Hash {
+ return hmac.New(sha256.New, key)
+ }},
+ "hmac-sha1": {20, false, func(key []byte) hash.Hash {
return hmac.New(sha1.New, key)
}},
- "hmac-sha1-96": {20, func(key []byte) hash.Hash {
+ "hmac-sha1-96": {20, false, func(key []byte) hash.Hash {
return truncatingMAC{12, hmac.New(sha1.New, key)}
}},
}
diff --git a/vendor/golang.org/x/crypto/ssh/mux.go b/vendor/golang.org/x/crypto/ssh/mux.go
index f3a3ddd..27a527c 100644
--- a/vendor/golang.org/x/crypto/ssh/mux.go
+++ b/vendor/golang.org/x/crypto/ssh/mux.go
@@ -116,9 +116,9 @@ func (m *mux) Wait() error {
func newMux(p packetConn) *mux {
m := &mux{
conn: p,
- incomingChannels: make(chan NewChannel, 16),
+ incomingChannels: make(chan NewChannel, chanSize),
globalResponses: make(chan interface{}, 1),
- incomingRequests: make(chan *Request, 16),
+ incomingRequests: make(chan *Request, chanSize),
errCond: newCond(),
}
if debugMux {
diff --git a/vendor/golang.org/x/crypto/ssh/mux_test.go b/vendor/golang.org/x/crypto/ssh/mux_test.go
index 591aae8..25d2181 100644
--- a/vendor/golang.org/x/crypto/ssh/mux_test.go
+++ b/vendor/golang.org/x/crypto/ssh/mux_test.go
@@ -499,4 +499,7 @@ func TestDebug(t *testing.T) {
if debugHandshake {
t.Error("handshake debug switched on")
}
+ if debugTransport {
+ t.Error("transport debug switched on")
+ }
}
diff --git a/vendor/golang.org/x/crypto/ssh/server.go b/vendor/golang.org/x/crypto/ssh/server.go
index 28b109a..70d6077 100644
--- a/vendor/golang.org/x/crypto/ssh/server.go
+++ b/vendor/golang.org/x/crypto/ssh/server.go
@@ -10,26 +10,38 @@ import (
"fmt"
"io"
"net"
+ "strings"
)
// The Permissions type holds fine-grained permissions that are
-// specific to a user or a specific authentication method for a
-// user. Permissions, except for "source-address", must be enforced in
-// the server application layer, after successful authentication. The
-// Permissions are passed on in ServerConn so a server implementation
-// can honor them.
+// specific to a user or a specific authentication method for a user.
+// The Permissions value for a successful authentication attempt is
+// available in ServerConn, so it can be used to pass information from
+// the user-authentication phase to the application layer.
type Permissions struct {
- // Critical options restrict default permissions. Common
- // restrictions are "source-address" and "force-command". If
- // the server cannot enforce the restriction, or does not
- // recognize it, the user should not authenticate.
+ // CriticalOptions indicate restrictions to the default
+ // permissions, and are typically used in conjunction with
+ // user certificates. The standard for SSH certificates
+ // defines "force-command" (only allow the given command to
+ // execute) and "source-address" (only allow connections from
+ // the given address). The SSH package currently only enforces
+ // the "source-address" critical option. It is up to server
+ // implementations to enforce other critical options, such as
+ // "force-command", by checking them after the SSH handshake
+ // is successful. In general, SSH servers should reject
+ // connections that specify critical options that are unknown
+ // or not supported.
CriticalOptions map[string]string
// Extensions are extra functionality that the server may
- // offer on authenticated connections. Common extensions are
- // "permit-agent-forwarding", "permit-X11-forwarding". Lack of
- // support for an extension does not preclude authenticating a
- // user.
+ // offer on authenticated connections. Lack of support for an
+ // extension does not preclude authenticating a user. Common
+ // extensions are "permit-agent-forwarding",
+ // "permit-X11-forwarding". The Go SSH library currently does
+ // not act on any extension, and it is up to server
+ // implementations to honor them. Extensions can be used to
+ // pass data from the authentication callbacks to the server
+ // application layer.
Extensions map[string]string
}
@@ -44,13 +56,24 @@ type ServerConfig struct {
// authenticating.
NoClientAuth bool
+ // MaxAuthTries specifies the maximum number of authentication attempts
+ // permitted per connection. If set to a negative number, the number of
+ // attempts are unlimited. If set to zero, the number of attempts are limited
+ // to 6.
+ MaxAuthTries int
+
// PasswordCallback, if non-nil, is called when a user
// attempts to authenticate using a password.
PasswordCallback func(conn ConnMetadata, password []byte) (*Permissions, error)
- // PublicKeyCallback, if non-nil, is called when a client attempts public
- // key authentication. It must return true if the given public key is
- // valid for the given user. For example, see CertChecker.Authenticate.
+ // PublicKeyCallback, if non-nil, is called when a client
+ // offers a public key for authentication. It must return true
+ // if the given public key can be used to authenticate the
+ // given user. For example, see CertChecker.Authenticate. A
+ // call to this function does not guarantee that the key
+ // offered is in fact used to authenticate. To record any data
+ // depending on the public key, store it inside a
+ // Permissions.Extensions entry.
PublicKeyCallback func(conn ConnMetadata, key PublicKey) (*Permissions, error)
// KeyboardInteractiveCallback, if non-nil, is called when
@@ -142,6 +165,10 @@ type ServerConn struct {
func NewServerConn(c net.Conn, config *ServerConfig) (*ServerConn, <-chan NewChannel, <-chan *Request, error) {
fullConf := *config
fullConf.SetDefaults()
+ if fullConf.MaxAuthTries == 0 {
+ fullConf.MaxAuthTries = 6
+ }
+
s := &connection{
sshConn: sshConn{conn: c},
}
@@ -231,7 +258,7 @@ func isAcceptableAlgo(algo string) bool {
return false
}
-func checkSourceAddress(addr net.Addr, sourceAddr string) error {
+func checkSourceAddress(addr net.Addr, sourceAddrs string) error {
if addr == nil {
return errors.New("ssh: no address known for client, but source-address match required")
}
@@ -241,18 +268,20 @@ func checkSourceAddress(addr net.Addr, sourceAddr string) error {
return fmt.Errorf("ssh: remote address %v is not an TCP address when checking source-address match", addr)
}
- if allowedIP := net.ParseIP(sourceAddr); allowedIP != nil {
- if allowedIP.Equal(tcpAddr.IP) {
- return nil
- }
- } else {
- _, ipNet, err := net.ParseCIDR(sourceAddr)
- if err != nil {
- return fmt.Errorf("ssh: error parsing source-address restriction %q: %v", sourceAddr, err)
- }
+ for _, sourceAddr := range strings.Split(sourceAddrs, ",") {
+ if allowedIP := net.ParseIP(sourceAddr); allowedIP != nil {
+ if allowedIP.Equal(tcpAddr.IP) {
+ return nil
+ }
+ } else {
+ _, ipNet, err := net.ParseCIDR(sourceAddr)
+ if err != nil {
+ return fmt.Errorf("ssh: error parsing source-address restriction %q: %v", sourceAddr, err)
+ }
- if ipNet.Contains(tcpAddr.IP) {
- return nil
+ if ipNet.Contains(tcpAddr.IP) {
+ return nil
+ }
}
}
@@ -264,8 +293,23 @@ func (s *connection) serverAuthenticate(config *ServerConfig) (*Permissions, err
var cache pubKeyCache
var perms *Permissions
+ authFailures := 0
+
userAuthLoop:
for {
+ if authFailures >= config.MaxAuthTries && config.MaxAuthTries > 0 {
+ discMsg := &disconnectMsg{
+ Reason: 2,
+ Message: "too many authentication failures",
+ }
+
+ if err := s.transport.writePacket(Marshal(discMsg)); err != nil {
+ return nil, err
+ }
+
+ return nil, discMsg
+ }
+
var userAuthReq userAuthRequestMsg
if packet, err := s.transport.readPacket(); err != nil {
return nil, err
@@ -286,6 +330,11 @@ userAuthLoop:
if config.NoClientAuth {
authErr = nil
}
+
+ // allow initial attempt of 'none' without penalty
+ if authFailures == 0 {
+ authFailures--
+ }
case "password":
if config.PasswordCallback == nil {
authErr = errors.New("ssh: password auth not configured")
@@ -357,6 +406,7 @@ userAuthLoop:
if isQuery {
// The client can query if the given public key
// would be okay.
+
if len(payload) > 0 {
return nil, parseError(msgUserAuthRequest)
}
@@ -406,6 +456,8 @@ userAuthLoop:
break userAuthLoop
}
+ authFailures++
+
var failureMsg userAuthFailureMsg
if config.PasswordCallback != nil {
failureMsg.Methods = append(failureMsg.Methods, "password")
diff --git a/vendor/golang.org/x/crypto/ssh/session_test.go b/vendor/golang.org/x/crypto/ssh/session_test.go
index f35a378..7dce6dd 100644
--- a/vendor/golang.org/x/crypto/ssh/session_test.go
+++ b/vendor/golang.org/x/crypto/ssh/session_test.go
@@ -59,7 +59,8 @@ func dial(handler serverType, t *testing.T) *Client {
}()
config := &ClientConfig{
- User: "testuser",
+ User: "testuser",
+ HostKeyCallback: InsecureIgnoreHostKey(),
}
conn, chans, reqs, err := NewClientConn(c2, "", config)
@@ -641,7 +642,8 @@ func TestSessionID(t *testing.T) {
}
serverConf.AddHostKey(testSigners["ecdsa"])
clientConf := &ClientConfig{
- User: "user",
+ HostKeyCallback: InsecureIgnoreHostKey(),
+ User: "user",
}
go func() {
@@ -747,7 +749,9 @@ func TestHostKeyAlgorithms(t *testing.T) {
// By default, we get the preferred algorithm, which is ECDSA 256.
- clientConf := &ClientConfig{}
+ clientConf := &ClientConfig{
+ HostKeyCallback: InsecureIgnoreHostKey(),
+ }
connect(clientConf, KeyAlgoECDSA256)
// Client asks for RSA explicitly.
diff --git a/vendor/golang.org/x/crypto/ssh/streamlocal.go b/vendor/golang.org/x/crypto/ssh/streamlocal.go
new file mode 100644
index 0000000..a2dccc6
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/streamlocal.go
@@ -0,0 +1,115 @@
+package ssh
+
+import (
+ "errors"
+ "io"
+ "net"
+)
+
+// streamLocalChannelOpenDirectMsg is a struct used for SSH_MSG_CHANNEL_OPEN message
+// with "direct-streamlocal@openssh.com" string.
+//
+// See openssh-portable/PROTOCOL, section 2.4. connection: Unix domain socket forwarding
+// https://github.com/openssh/openssh-portable/blob/master/PROTOCOL#L235
+type streamLocalChannelOpenDirectMsg struct {
+ socketPath string
+ reserved0 string
+ reserved1 uint32
+}
+
+// forwardedStreamLocalPayload is a struct used for SSH_MSG_CHANNEL_OPEN message
+// with "forwarded-streamlocal@openssh.com" string.
+type forwardedStreamLocalPayload struct {
+ SocketPath string
+ Reserved0 string
+}
+
+// streamLocalChannelForwardMsg is a struct used for SSH2_MSG_GLOBAL_REQUEST message
+// with "streamlocal-forward@openssh.com"/"cancel-streamlocal-forward@openssh.com" string.
+type streamLocalChannelForwardMsg struct {
+ socketPath string
+}
+
+// ListenUnix is similar to ListenTCP but uses a Unix domain socket.
+func (c *Client) ListenUnix(socketPath string) (net.Listener, error) {
+ m := streamLocalChannelForwardMsg{
+ socketPath,
+ }
+ // send message
+ ok, _, err := c.SendRequest("streamlocal-forward@openssh.com", true, Marshal(&m))
+ if err != nil {
+ return nil, err
+ }
+ if !ok {
+ return nil, errors.New("ssh: streamlocal-forward@openssh.com request denied by peer")
+ }
+ ch := c.forwards.add(&net.UnixAddr{Name: socketPath, Net: "unix"})
+
+ return &unixListener{socketPath, c, ch}, nil
+}
+
+func (c *Client) dialStreamLocal(socketPath string) (Channel, error) {
+ msg := streamLocalChannelOpenDirectMsg{
+ socketPath: socketPath,
+ }
+ ch, in, err := c.OpenChannel("direct-streamlocal@openssh.com", Marshal(&msg))
+ if err != nil {
+ return nil, err
+ }
+ go DiscardRequests(in)
+ return ch, err
+}
+
+type unixListener struct {
+ socketPath string
+
+ conn *Client
+ in <-chan forward
+}
+
+// Accept waits for and returns the next connection to the listener.
+func (l *unixListener) Accept() (net.Conn, error) {
+ s, ok := <-l.in
+ if !ok {
+ return nil, io.EOF
+ }
+ ch, incoming, err := s.newCh.Accept()
+ if err != nil {
+ return nil, err
+ }
+ go DiscardRequests(incoming)
+
+ return &chanConn{
+ Channel: ch,
+ laddr: &net.UnixAddr{
+ Name: l.socketPath,
+ Net: "unix",
+ },
+ raddr: &net.UnixAddr{
+ Name: "@",
+ Net: "unix",
+ },
+ }, nil
+}
+
+// Close closes the listener.
+func (l *unixListener) Close() error {
+ // this also closes the listener.
+ l.conn.forwards.remove(&net.UnixAddr{Name: l.socketPath, Net: "unix"})
+ m := streamLocalChannelForwardMsg{
+ l.socketPath,
+ }
+ ok, _, err := l.conn.SendRequest("cancel-streamlocal-forward@openssh.com", true, Marshal(&m))
+ if err == nil && !ok {
+ err = errors.New("ssh: cancel-streamlocal-forward@openssh.com failed")
+ }
+ return err
+}
+
+// Addr returns the listener's network address.
+func (l *unixListener) Addr() net.Addr {
+ return &net.UnixAddr{
+ Name: l.socketPath,
+ Net: "unix",
+ }
+}
diff --git a/vendor/golang.org/x/crypto/ssh/tcpip.go b/vendor/golang.org/x/crypto/ssh/tcpip.go
index 6151241..acf1717 100644
--- a/vendor/golang.org/x/crypto/ssh/tcpip.go
+++ b/vendor/golang.org/x/crypto/ssh/tcpip.go
@@ -20,12 +20,20 @@ import (
// addr. Incoming connections will be available by calling Accept on
// the returned net.Listener. The listener must be serviced, or the
// SSH connection may hang.
+// N must be "tcp", "tcp4", "tcp6", or "unix".
func (c *Client) Listen(n, addr string) (net.Listener, error) {
- laddr, err := net.ResolveTCPAddr(n, addr)
- if err != nil {
- return nil, err
+ switch n {
+ case "tcp", "tcp4", "tcp6":
+ laddr, err := net.ResolveTCPAddr(n, addr)
+ if err != nil {
+ return nil, err
+ }
+ return c.ListenTCP(laddr)
+ case "unix":
+ return c.ListenUnix(addr)
+ default:
+ return nil, fmt.Errorf("ssh: unsupported protocol: %s", n)
}
- return c.ListenTCP(laddr)
}
// Automatic port allocation is broken with OpenSSH before 6.0. See
@@ -116,7 +124,7 @@ func (c *Client) ListenTCP(laddr *net.TCPAddr) (net.Listener, error) {
}
// Register this forward, using the port number we obtained.
- ch := c.forwards.add(*laddr)
+ ch := c.forwards.add(laddr)
return &tcpListener{laddr, c, ch}, nil
}
@@ -131,7 +139,7 @@ type forwardList struct {
// forwardEntry represents an established mapping of a laddr on a
// remote ssh server to a channel connected to a tcpListener.
type forwardEntry struct {
- laddr net.TCPAddr
+ laddr net.Addr
c chan forward
}
@@ -139,16 +147,16 @@ type forwardEntry struct {
// arguments to add/remove/lookup should be address as specified in
// the original forward-request.
type forward struct {
- newCh NewChannel // the ssh client channel underlying this forward
- raddr *net.TCPAddr // the raddr of the incoming connection
+ newCh NewChannel // the ssh client channel underlying this forward
+ raddr net.Addr // the raddr of the incoming connection
}
-func (l *forwardList) add(addr net.TCPAddr) chan forward {
+func (l *forwardList) add(addr net.Addr) chan forward {
l.Lock()
defer l.Unlock()
f := forwardEntry{
- addr,
- make(chan forward, 1),
+ laddr: addr,
+ c: make(chan forward, 1),
}
l.entries = append(l.entries, f)
return f.c
@@ -176,44 +184,69 @@ func parseTCPAddr(addr string, port uint32) (*net.TCPAddr, error) {
func (l *forwardList) handleChannels(in <-chan NewChannel) {
for ch := range in {
- var payload forwardedTCPPayload
- if err := Unmarshal(ch.ExtraData(), &payload); err != nil {
- ch.Reject(ConnectionFailed, "could not parse forwarded-tcpip payload: "+err.Error())
- continue
- }
+ var (
+ laddr net.Addr
+ raddr net.Addr
+ err error
+ )
+ switch channelType := ch.ChannelType(); channelType {
+ case "forwarded-tcpip":
+ var payload forwardedTCPPayload
+ if err = Unmarshal(ch.ExtraData(), &payload); err != nil {
+ ch.Reject(ConnectionFailed, "could not parse forwarded-tcpip payload: "+err.Error())
+ continue
+ }
- // RFC 4254 section 7.2 specifies that incoming
- // addresses should list the address, in string
- // format. It is implied that this should be an IP
- // address, as it would be impossible to connect to it
- // otherwise.
- laddr, err := parseTCPAddr(payload.Addr, payload.Port)
- if err != nil {
- ch.Reject(ConnectionFailed, err.Error())
- continue
- }
- raddr, err := parseTCPAddr(payload.OriginAddr, payload.OriginPort)
- if err != nil {
- ch.Reject(ConnectionFailed, err.Error())
- continue
- }
+ // RFC 4254 section 7.2 specifies that incoming
+ // addresses should list the address, in string
+ // format. It is implied that this should be an IP
+ // address, as it would be impossible to connect to it
+ // otherwise.
+ laddr, err = parseTCPAddr(payload.Addr, payload.Port)
+ if err != nil {
+ ch.Reject(ConnectionFailed, err.Error())
+ continue
+ }
+ raddr, err = parseTCPAddr(payload.OriginAddr, payload.OriginPort)
+ if err != nil {
+ ch.Reject(ConnectionFailed, err.Error())
+ continue
+ }
- if ok := l.forward(*laddr, *raddr, ch); !ok {
+ case "forwarded-streamlocal@openssh.com":
+ var payload forwardedStreamLocalPayload
+ if err = Unmarshal(ch.ExtraData(), &payload); err != nil {
+ ch.Reject(ConnectionFailed, "could not parse forwarded-streamlocal@openssh.com payload: "+err.Error())
+ continue
+ }
+ laddr = &net.UnixAddr{
+ Name: payload.SocketPath,
+ Net: "unix",
+ }
+ raddr = &net.UnixAddr{
+ Name: "@",
+ Net: "unix",
+ }
+ default:
+ panic(fmt.Errorf("ssh: unknown channel type %s", channelType))
+ }
+ if ok := l.forward(laddr, raddr, ch); !ok {
// Section 7.2, implementations MUST reject spurious incoming
// connections.
ch.Reject(Prohibited, "no forward for address")
continue
}
+
}
}
// remove removes the forward entry, and the channel feeding its
// listener.
-func (l *forwardList) remove(addr net.TCPAddr) {
+func (l *forwardList) remove(addr net.Addr) {
l.Lock()
defer l.Unlock()
for i, f := range l.entries {
- if addr.IP.Equal(f.laddr.IP) && addr.Port == f.laddr.Port {
+ if addr.Network() == f.laddr.Network() && addr.String() == f.laddr.String() {
l.entries = append(l.entries[:i], l.entries[i+1:]...)
close(f.c)
return
@@ -231,12 +264,12 @@ func (l *forwardList) closeAll() {
l.entries = nil
}
-func (l *forwardList) forward(laddr, raddr net.TCPAddr, ch NewChannel) bool {
+func (l *forwardList) forward(laddr, raddr net.Addr, ch NewChannel) bool {
l.Lock()
defer l.Unlock()
for _, f := range l.entries {
- if laddr.IP.Equal(f.laddr.IP) && laddr.Port == f.laddr.Port {
- f.c <- forward{ch, &raddr}
+ if laddr.Network() == f.laddr.Network() && laddr.String() == f.laddr.String() {
+ f.c <- forward{newCh: ch, raddr: raddr}
return true
}
}
@@ -262,7 +295,7 @@ func (l *tcpListener) Accept() (net.Conn, error) {
}
go DiscardRequests(incoming)
- return &tcpChanConn{
+ return &chanConn{
Channel: ch,
laddr: l.laddr,
raddr: s.raddr,
@@ -277,7 +310,7 @@ func (l *tcpListener) Close() error {
}
// this also closes the listener.
- l.conn.forwards.remove(*l.laddr)
+ l.conn.forwards.remove(l.laddr)
ok, _, err := l.conn.SendRequest("cancel-tcpip-forward", true, Marshal(&m))
if err == nil && !ok {
err = errors.New("ssh: cancel-tcpip-forward failed")
@@ -293,29 +326,52 @@ func (l *tcpListener) Addr() net.Addr {
// Dial initiates a connection to the addr from the remote host.
// The resulting connection has a zero LocalAddr() and RemoteAddr().
func (c *Client) Dial(n, addr string) (net.Conn, error) {
- // Parse the address into host and numeric port.
- host, portString, err := net.SplitHostPort(addr)
- if err != nil {
- return nil, err
+ var ch Channel
+ switch n {
+ case "tcp", "tcp4", "tcp6":
+ // Parse the address into host and numeric port.
+ host, portString, err := net.SplitHostPort(addr)
+ if err != nil {
+ return nil, err
+ }
+ port, err := strconv.ParseUint(portString, 10, 16)
+ if err != nil {
+ return nil, err
+ }
+ ch, err = c.dial(net.IPv4zero.String(), 0, host, int(port))
+ if err != nil {
+ return nil, err
+ }
+ // Use a zero address for local and remote address.
+ zeroAddr := &net.TCPAddr{
+ IP: net.IPv4zero,
+ Port: 0,
+ }
+ return &chanConn{
+ Channel: ch,
+ laddr: zeroAddr,
+ raddr: zeroAddr,
+ }, nil
+ case "unix":
+ var err error
+ ch, err = c.dialStreamLocal(addr)
+ if err != nil {
+ return nil, err
+ }
+ return &chanConn{
+ Channel: ch,
+ laddr: &net.UnixAddr{
+ Name: "@",
+ Net: "unix",
+ },
+ raddr: &net.UnixAddr{
+ Name: addr,
+ Net: "unix",
+ },
+ }, nil
+ default:
+ return nil, fmt.Errorf("ssh: unsupported protocol: %s", n)
}
- port, err := strconv.ParseUint(portString, 10, 16)
- if err != nil {
- return nil, err
- }
- // Use a zero address for local and remote address.
- zeroAddr := &net.TCPAddr{
- IP: net.IPv4zero,
- Port: 0,
- }
- ch, err := c.dial(net.IPv4zero.String(), 0, host, int(port))
- if err != nil {
- return nil, err
- }
- return &tcpChanConn{
- Channel: ch,
- laddr: zeroAddr,
- raddr: zeroAddr,
- }, nil
}
// DialTCP connects to the remote address raddr on the network net,
@@ -332,7 +388,7 @@ func (c *Client) DialTCP(n string, laddr, raddr *net.TCPAddr) (net.Conn, error)
if err != nil {
return nil, err
}
- return &tcpChanConn{
+ return &chanConn{
Channel: ch,
laddr: laddr,
raddr: raddr,
@@ -366,26 +422,26 @@ type tcpChan struct {
Channel // the backing channel
}
-// tcpChanConn fulfills the net.Conn interface without
+// chanConn fulfills the net.Conn interface without
// the tcpChan having to hold laddr or raddr directly.
-type tcpChanConn struct {
+type chanConn struct {
Channel
laddr, raddr net.Addr
}
// LocalAddr returns the local network address.
-func (t *tcpChanConn) LocalAddr() net.Addr {
+func (t *chanConn) LocalAddr() net.Addr {
return t.laddr
}
// RemoteAddr returns the remote network address.
-func (t *tcpChanConn) RemoteAddr() net.Addr {
+func (t *chanConn) RemoteAddr() net.Addr {
return t.raddr
}
// SetDeadline sets the read and write deadlines associated
// with the connection.
-func (t *tcpChanConn) SetDeadline(deadline time.Time) error {
+func (t *chanConn) SetDeadline(deadline time.Time) error {
if err := t.SetReadDeadline(deadline); err != nil {
return err
}
@@ -396,12 +452,14 @@ func (t *tcpChanConn) SetDeadline(deadline time.Time) error {
// A zero value for t means Read will not time out.
// After the deadline, the error from Read will implement net.Error
// with Timeout() == true.
-func (t *tcpChanConn) SetReadDeadline(deadline time.Time) error {
+func (t *chanConn) SetReadDeadline(deadline time.Time) error {
+ // for compatibility with previous version,
+ // the error message contains "tcpChan"
return errors.New("ssh: tcpChan: deadline not supported")
}
// SetWriteDeadline exists to satisfy the net.Conn interface
// but is not implemented by this type. It always returns an error.
-func (t *tcpChanConn) SetWriteDeadline(deadline time.Time) error {
+func (t *chanConn) SetWriteDeadline(deadline time.Time) error {
return errors.New("ssh: tcpChan: deadline not supported")
}
diff --git a/vendor/golang.org/x/crypto/ssh/terminal/util_solaris.go b/vendor/golang.org/x/crypto/ssh/terminal/util_solaris.go
index 07eb5ed..a2e1b57 100644
--- a/vendor/golang.org/x/crypto/ssh/terminal/util_solaris.go
+++ b/vendor/golang.org/x/crypto/ssh/terminal/util_solaris.go
@@ -14,14 +14,12 @@ import (
// State contains the state of a terminal.
type State struct {
- termios syscall.Termios
+ state *unix.Termios
}
// IsTerminal returns true if the given file descriptor is a terminal.
func IsTerminal(fd int) bool {
- // see: http://src.illumos.org/source/xref/illumos-gate/usr/src/lib/libbc/libc/gen/common/isatty.c
- var termio unix.Termio
- err := unix.IoctlSetTermio(fd, unix.TCGETA, &termio)
+ _, err := unix.IoctlGetTermio(fd, unix.TCGETA)
return err == nil
}
@@ -71,3 +69,60 @@ func ReadPassword(fd int) ([]byte, error) {
return ret, nil
}
+
+// MakeRaw puts the terminal connected to the given file descriptor into raw
+// mode and returns the previous state of the terminal so that it can be
+// restored.
+// see http://cr.illumos.org/~webrev/andy_js/1060/
+func MakeRaw(fd int) (*State, error) {
+ oldTermiosPtr, err := unix.IoctlGetTermios(fd, unix.TCGETS)
+ if err != nil {
+ return nil, err
+ }
+ oldTermios := *oldTermiosPtr
+
+ newTermios := oldTermios
+ newTermios.Iflag &^= syscall.IGNBRK | syscall.BRKINT | syscall.PARMRK | syscall.ISTRIP | syscall.INLCR | syscall.IGNCR | syscall.ICRNL | syscall.IXON
+ newTermios.Oflag &^= syscall.OPOST
+ newTermios.Lflag &^= syscall.ECHO | syscall.ECHONL | syscall.ICANON | syscall.ISIG | syscall.IEXTEN
+ newTermios.Cflag &^= syscall.CSIZE | syscall.PARENB
+ newTermios.Cflag |= syscall.CS8
+ newTermios.Cc[unix.VMIN] = 1
+ newTermios.Cc[unix.VTIME] = 0
+
+ if err := unix.IoctlSetTermios(fd, unix.TCSETS, &newTermios); err != nil {
+ return nil, err
+ }
+
+ return &State{
+ state: oldTermiosPtr,
+ }, nil
+}
+
+// Restore restores the terminal connected to the given file descriptor to a
+// previous state.
+func Restore(fd int, oldState *State) error {
+ return unix.IoctlSetTermios(fd, unix.TCSETS, oldState.state)
+}
+
+// GetState returns the current state of a terminal which may be useful to
+// restore the terminal after a signal.
+func GetState(fd int) (*State, error) {
+ oldTermiosPtr, err := unix.IoctlGetTermios(fd, unix.TCGETS)
+ if err != nil {
+ return nil, err
+ }
+
+ return &State{
+ state: oldTermiosPtr,
+ }, nil
+}
+
+// GetSize returns the dimensions of the given terminal.
+func GetSize(fd int) (width, height int, err error) {
+ ws, err := unix.IoctlGetWinsize(fd, unix.TIOCGWINSZ)
+ if err != nil {
+ return 0, 0, err
+ }
+ return int(ws.Col), int(ws.Row), nil
+}
diff --git a/vendor/golang.org/x/crypto/ssh/test/cert_test.go b/vendor/golang.org/x/crypto/ssh/test/cert_test.go
index 364790f..b231dd8 100644
--- a/vendor/golang.org/x/crypto/ssh/test/cert_test.go
+++ b/vendor/golang.org/x/crypto/ssh/test/cert_test.go
@@ -7,12 +7,14 @@
package test
import (
+ "bytes"
"crypto/rand"
"testing"
"golang.org/x/crypto/ssh"
)
+// Test both logging in with a cert, and also that the certificate presented by an OpenSSH host can be validated correctly
func TestCertLogin(t *testing.T) {
s := newServer(t)
defer s.Shutdown()
@@ -37,11 +39,39 @@ func TestCertLogin(t *testing.T) {
conf := &ssh.ClientConfig{
User: username(),
+ HostKeyCallback: (&ssh.CertChecker{
+ IsHostAuthority: func(pk ssh.PublicKey, addr string) bool {
+ return bytes.Equal(pk.Marshal(), testPublicKeys["ca"].Marshal())
+ },
+ }).CheckHostKey,
}
conf.Auth = append(conf.Auth, ssh.PublicKeys(certSigner))
- client, err := s.TryDial(conf)
- if err != nil {
- t.Fatalf("TryDial: %v", err)
+
+ for _, test := range []struct {
+ addr string
+ succeed bool
+ }{
+ {addr: "host.example.com:22", succeed: true},
+ {addr: "host.example.com:10000", succeed: true}, // non-standard port must be OK
+ {addr: "host.example.com", succeed: false}, // port must be specified
+ {addr: "host.ex4mple.com:22", succeed: false}, // wrong host
+ } {
+ client, err := s.TryDialWithAddr(conf, test.addr)
+
+ // Always close client if opened successfully
+ if err == nil {
+ client.Close()
+ }
+
+ // Now evaluate whether the test failed or passed
+ if test.succeed {
+ if err != nil {
+ t.Fatalf("TryDialWithAddr: %v", err)
+ }
+ } else {
+ if err == nil {
+ t.Fatalf("TryDialWithAddr, unexpected success")
+ }
+ }
}
- client.Close()
}
diff --git a/vendor/golang.org/x/crypto/ssh/test/dial_unix_test.go b/vendor/golang.org/x/crypto/ssh/test/dial_unix_test.go
new file mode 100644
index 0000000..091e48c
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/test/dial_unix_test.go
@@ -0,0 +1,128 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !windows
+
+package test
+
+// direct-tcpip and direct-streamlocal functional tests
+
+import (
+ "fmt"
+ "io"
+ "io/ioutil"
+ "net"
+ "strings"
+ "testing"
+)
+
+type dialTester interface {
+ TestServerConn(t *testing.T, c net.Conn)
+ TestClientConn(t *testing.T, c net.Conn)
+}
+
+func testDial(t *testing.T, n, listenAddr string, x dialTester) {
+ server := newServer(t)
+ defer server.Shutdown()
+ sshConn := server.Dial(clientConfig())
+ defer sshConn.Close()
+
+ l, err := net.Listen(n, listenAddr)
+ if err != nil {
+ t.Fatalf("Listen: %v", err)
+ }
+ defer l.Close()
+
+ testData := fmt.Sprintf("hello from %s, %s", n, listenAddr)
+ go func() {
+ for {
+ c, err := l.Accept()
+ if err != nil {
+ break
+ }
+ x.TestServerConn(t, c)
+
+ io.WriteString(c, testData)
+ c.Close()
+ }
+ }()
+
+ conn, err := sshConn.Dial(n, l.Addr().String())
+ if err != nil {
+ t.Fatalf("Dial: %v", err)
+ }
+ x.TestClientConn(t, conn)
+ defer conn.Close()
+ b, err := ioutil.ReadAll(conn)
+ if err != nil {
+ t.Fatalf("ReadAll: %v", err)
+ }
+ t.Logf("got %q", string(b))
+ if string(b) != testData {
+ t.Fatalf("expected %q, got %q", testData, string(b))
+ }
+}
+
+type tcpDialTester struct {
+ listenAddr string
+}
+
+func (x *tcpDialTester) TestServerConn(t *testing.T, c net.Conn) {
+ host := strings.Split(x.listenAddr, ":")[0]
+ prefix := host + ":"
+ if !strings.HasPrefix(c.LocalAddr().String(), prefix) {
+ t.Fatalf("expected to start with %q, got %q", prefix, c.LocalAddr().String())
+ }
+ if !strings.HasPrefix(c.RemoteAddr().String(), prefix) {
+ t.Fatalf("expected to start with %q, got %q", prefix, c.RemoteAddr().String())
+ }
+}
+
+func (x *tcpDialTester) TestClientConn(t *testing.T, c net.Conn) {
+ // we use zero addresses. see *Client.Dial.
+ if c.LocalAddr().String() != "0.0.0.0:0" {
+ t.Fatalf("expected \"0.0.0.0:0\", got %q", c.LocalAddr().String())
+ }
+ if c.RemoteAddr().String() != "0.0.0.0:0" {
+ t.Fatalf("expected \"0.0.0.0:0\", got %q", c.RemoteAddr().String())
+ }
+}
+
+func TestDialTCP(t *testing.T) {
+ x := &tcpDialTester{
+ listenAddr: "127.0.0.1:0",
+ }
+ testDial(t, "tcp", x.listenAddr, x)
+}
+
+type unixDialTester struct {
+ listenAddr string
+}
+
+func (x *unixDialTester) TestServerConn(t *testing.T, c net.Conn) {
+ if c.LocalAddr().String() != x.listenAddr {
+ t.Fatalf("expected %q, got %q", x.listenAddr, c.LocalAddr().String())
+ }
+ if c.RemoteAddr().String() != "@" {
+ t.Fatalf("expected \"@\", got %q", c.RemoteAddr().String())
+ }
+}
+
+func (x *unixDialTester) TestClientConn(t *testing.T, c net.Conn) {
+ if c.RemoteAddr().String() != x.listenAddr {
+ t.Fatalf("expected %q, got %q", x.listenAddr, c.RemoteAddr().String())
+ }
+ if c.LocalAddr().String() != "@" {
+ t.Fatalf("expected \"@\", got %q", c.LocalAddr().String())
+ }
+}
+
+func TestDialUnix(t *testing.T) {
+ addr, cleanup := newTempSocket(t)
+ defer cleanup()
+ x := &unixDialTester{
+ listenAddr: addr,
+ }
+ testDial(t, "unix", x.listenAddr, x)
+}
diff --git a/vendor/golang.org/x/crypto/ssh/test/forward_unix_test.go b/vendor/golang.org/x/crypto/ssh/test/forward_unix_test.go
index 877a88c..ea81937 100644
--- a/vendor/golang.org/x/crypto/ssh/test/forward_unix_test.go
+++ b/vendor/golang.org/x/crypto/ssh/test/forward_unix_test.go
@@ -16,13 +16,17 @@ import (
"time"
)
-func TestPortForward(t *testing.T) {
+type closeWriter interface {
+ CloseWrite() error
+}
+
+func testPortForward(t *testing.T, n, listenAddr string) {
server := newServer(t)
defer server.Shutdown()
conn := server.Dial(clientConfig())
defer conn.Close()
- sshListener, err := conn.Listen("tcp", "localhost:0")
+ sshListener, err := conn.Listen(n, listenAddr)
if err != nil {
t.Fatal(err)
}
@@ -41,14 +45,14 @@ func TestPortForward(t *testing.T) {
}()
forwardedAddr := sshListener.Addr().String()
- tcpConn, err := net.Dial("tcp", forwardedAddr)
+ netConn, err := net.Dial(n, forwardedAddr)
if err != nil {
- t.Fatalf("TCP dial failed: %v", err)
+ t.Fatalf("net dial failed: %v", err)
}
readChan := make(chan []byte)
go func() {
- data, _ := ioutil.ReadAll(tcpConn)
+ data, _ := ioutil.ReadAll(netConn)
readChan <- data
}()
@@ -62,14 +66,14 @@ func TestPortForward(t *testing.T) {
for len(sent) < 1000*1000 {
// Send random sized chunks
m := rand.Intn(len(data))
- n, err := tcpConn.Write(data[:m])
+ n, err := netConn.Write(data[:m])
if err != nil {
break
}
sent = append(sent, data[:n]...)
}
- if err := tcpConn.(*net.TCPConn).CloseWrite(); err != nil {
- t.Errorf("tcpConn.CloseWrite: %v", err)
+ if err := netConn.(closeWriter).CloseWrite(); err != nil {
+ t.Errorf("netConn.CloseWrite: %v", err)
}
read := <-readChan
@@ -86,19 +90,29 @@ func TestPortForward(t *testing.T) {
}
// Check that the forward disappeared.
- tcpConn, err = net.Dial("tcp", forwardedAddr)
+ netConn, err = net.Dial(n, forwardedAddr)
if err == nil {
- tcpConn.Close()
+ netConn.Close()
t.Errorf("still listening to %s after closing", forwardedAddr)
}
}
-func TestAcceptClose(t *testing.T) {
+func TestPortForwardTCP(t *testing.T) {
+ testPortForward(t, "tcp", "localhost:0")
+}
+
+func TestPortForwardUnix(t *testing.T) {
+ addr, cleanup := newTempSocket(t)
+ defer cleanup()
+ testPortForward(t, "unix", addr)
+}
+
+func testAcceptClose(t *testing.T, n, listenAddr string) {
server := newServer(t)
defer server.Shutdown()
conn := server.Dial(clientConfig())
- sshListener, err := conn.Listen("tcp", "localhost:0")
+ sshListener, err := conn.Listen(n, listenAddr)
if err != nil {
t.Fatal(err)
}
@@ -124,13 +138,23 @@ func TestAcceptClose(t *testing.T) {
}
}
+func TestAcceptCloseTCP(t *testing.T) {
+ testAcceptClose(t, "tcp", "localhost:0")
+}
+
+func TestAcceptCloseUnix(t *testing.T) {
+ addr, cleanup := newTempSocket(t)
+ defer cleanup()
+ testAcceptClose(t, "unix", addr)
+}
+
// Check that listeners exit if the underlying client transport dies.
-func TestPortForwardConnectionClose(t *testing.T) {
+func testPortForwardConnectionClose(t *testing.T, n, listenAddr string) {
server := newServer(t)
defer server.Shutdown()
conn := server.Dial(clientConfig())
- sshListener, err := conn.Listen("tcp", "localhost:0")
+ sshListener, err := conn.Listen(n, listenAddr)
if err != nil {
t.Fatal(err)
}
@@ -158,3 +182,13 @@ func TestPortForwardConnectionClose(t *testing.T) {
t.Logf("quit as expected (error %v)", err)
}
}
+
+func TestPortForwardConnectionCloseTCP(t *testing.T) {
+ testPortForwardConnectionClose(t, "tcp", "localhost:0")
+}
+
+func TestPortForwardConnectionCloseUnix(t *testing.T) {
+ addr, cleanup := newTempSocket(t)
+ defer cleanup()
+ testPortForwardConnectionClose(t, "unix", addr)
+}
diff --git a/vendor/golang.org/x/crypto/ssh/test/tcpip_test.go b/vendor/golang.org/x/crypto/ssh/test/tcpip_test.go
deleted file mode 100644
index a2eb935..0000000
--- a/vendor/golang.org/x/crypto/ssh/test/tcpip_test.go
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright 2012 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build !windows
-
-package test
-
-// direct-tcpip functional tests
-
-import (
- "io"
- "net"
- "testing"
-)
-
-func TestDial(t *testing.T) {
- server := newServer(t)
- defer server.Shutdown()
- sshConn := server.Dial(clientConfig())
- defer sshConn.Close()
-
- l, err := net.Listen("tcp", "127.0.0.1:0")
- if err != nil {
- t.Fatalf("Listen: %v", err)
- }
- defer l.Close()
-
- go func() {
- for {
- c, err := l.Accept()
- if err != nil {
- break
- }
-
- io.WriteString(c, c.RemoteAddr().String())
- c.Close()
- }
- }()
-
- conn, err := sshConn.Dial("tcp", l.Addr().String())
- if err != nil {
- t.Fatalf("Dial: %v", err)
- }
- defer conn.Close()
-}
diff --git a/vendor/golang.org/x/crypto/ssh/test/test_unix_test.go b/vendor/golang.org/x/crypto/ssh/test/test_unix_test.go
index 3bfd881..e673536 100644
--- a/vendor/golang.org/x/crypto/ssh/test/test_unix_test.go
+++ b/vendor/golang.org/x/crypto/ssh/test/test_unix_test.go
@@ -30,6 +30,7 @@ Protocol 2
HostKey {{.Dir}}/id_rsa
HostKey {{.Dir}}/id_dsa
HostKey {{.Dir}}/id_ecdsa
+HostCertificate {{.Dir}}/id_rsa-cert.pub
Pidfile {{.Dir}}/sshd.pid
#UsePrivilegeSeparation no
KeyRegenerationInterval 3600
@@ -119,6 +120,11 @@ func clientConfig() *ssh.ClientConfig {
ssh.PublicKeys(testSigners["user"]),
},
HostKeyCallback: hostKeyDB().Check,
+ HostKeyAlgorithms: []string{ // by default, don't allow certs as this affects the hostKeyDB checker
+ ssh.KeyAlgoECDSA256, ssh.KeyAlgoECDSA384, ssh.KeyAlgoECDSA521,
+ ssh.KeyAlgoRSA, ssh.KeyAlgoDSA,
+ ssh.KeyAlgoED25519,
+ },
}
return config
}
@@ -154,6 +160,12 @@ func unixConnection() (*net.UnixConn, *net.UnixConn, error) {
}
func (s *server) TryDial(config *ssh.ClientConfig) (*ssh.Client, error) {
+ return s.TryDialWithAddr(config, "")
+}
+
+// addr is the user specified host:port. While we don't actually dial it,
+// we need to know this for host key matching
+func (s *server) TryDialWithAddr(config *ssh.ClientConfig, addr string) (*ssh.Client, error) {
sshd, err := exec.LookPath("sshd")
if err != nil {
s.t.Skipf("skipping test: %v", err)
@@ -179,7 +191,7 @@ func (s *server) TryDial(config *ssh.ClientConfig) (*ssh.Client, error) {
s.t.Fatalf("s.cmd.Start: %v", err)
}
s.clientConn = c1
- conn, chans, reqs, err := ssh.NewClientConn(c1, "", config)
+ conn, chans, reqs, err := ssh.NewClientConn(c1, addr, config)
if err != nil {
return nil, err
}
@@ -250,6 +262,11 @@ func newServer(t *testing.T) *server {
writeFile(filepath.Join(dir, filename+".pub"), ssh.MarshalAuthorizedKey(testPublicKeys[k]))
}
+ for k, v := range testdata.SSHCertificates {
+ filename := "id_" + k + "-cert.pub"
+ writeFile(filepath.Join(dir, filename), v)
+ }
+
var authkeys bytes.Buffer
for k, _ := range testdata.PEMBytes {
authkeys.Write(ssh.MarshalAuthorizedKey(testPublicKeys[k]))
@@ -266,3 +283,13 @@ func newServer(t *testing.T) *server {
},
}
}
+
+func newTempSocket(t *testing.T) (string, func()) {
+ dir, err := ioutil.TempDir("", "socket")
+ if err != nil {
+ t.Fatal(err)
+ }
+ deferFunc := func() { os.RemoveAll(dir) }
+ addr := filepath.Join(dir, "sock")
+ return addr, deferFunc
+}
diff --git a/vendor/golang.org/x/crypto/ssh/testdata/keys.go b/vendor/golang.org/x/crypto/ssh/testdata/keys.go
index 736dad9..3b3d26c 100644
--- a/vendor/golang.org/x/crypto/ssh/testdata/keys.go
+++ b/vendor/golang.org/x/crypto/ssh/testdata/keys.go
@@ -48,11 +48,68 @@ AAAEAaYmXltfW6nhRo3iWGglRB48lYq0z0Q3I3KyrdutEr6j7d/uFLuDlRbBc4ZVOsx+Gb
HKuOrPtLHFvHsjWPwO+/AAAAE2dhcnRvbm1AZ2FydG9ubS14cHMBAg==
-----END OPENSSH PRIVATE KEY-----
`),
+ "rsa-openssh-format": []byte(`-----BEGIN OPENSSH PRIVATE KEY-----
+b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAlwAAAAdzc2gtcn
+NhAAAAAwEAAQAAAIEAwa48yfWFi3uIdqzuf9X7C2Zxfea/Iaaw0zIwHudpF8U92WVIiC5l
+oEuW1+OaVi3UWfIEjWMV1tHGysrHOwtwc34BPCJqJknUQO/KtDTBTJ4Pryhw1bWPC999Lz
+a+yrCTdNQYBzoROXKExZgPFh9pTMi5wqpHDuOQ2qZFIEI3lT0AAAIQWL0H31i9B98AAAAH
+c3NoLXJzYQAAAIEAwa48yfWFi3uIdqzuf9X7C2Zxfea/Iaaw0zIwHudpF8U92WVIiC5loE
+uW1+OaVi3UWfIEjWMV1tHGysrHOwtwc34BPCJqJknUQO/KtDTBTJ4Pryhw1bWPC999Lza+
+yrCTdNQYBzoROXKExZgPFh9pTMi5wqpHDuOQ2qZFIEI3lT0AAAADAQABAAAAgCThyTGsT4
+IARDxVMhWl6eiB2ZrgFgWSeJm/NOqtppWgOebsIqPMMg4UVuVFsl422/lE3RkPhVkjGXgE
+pWvZAdCnmLmApK8wK12vF334lZhZT7t3Z9EzJps88PWEHo7kguf285HcnUM7FlFeissJdk
+kXly34y7/3X/a6Tclm+iABAAAAQE0xR/KxZ39slwfMv64Rz7WKk1PPskaryI29aHE3mKHk
+pY2QA+P3QlrKxT/VWUMjHUbNNdYfJm48xu0SGNMRdKMAAABBAORh2NP/06JUV3J9W/2Hju
+X1ViJuqqcQnJPVzpgSL826EC2xwOECTqoY8uvFpUdD7CtpksIxNVqRIhuNOlz0lqEAAABB
+ANkaHTTaPojClO0dKJ/Zjs7pWOCGliebBYprQ/Y4r9QLBkC/XaWMS26gFIrjgC7D2Rv+rZ
+wSD0v0RcmkITP1ZR0AAAAYcHF1ZXJuYUBMdWNreUh5ZHJvLmxvY2FsAQID
+-----END OPENSSH PRIVATE KEY-----`),
"user": []byte(`-----BEGIN EC PRIVATE KEY-----
MHcCAQEEILYCAeq8f7V4vSSypRw7pxy8yz3V5W4qg8kSC3zJhqpQoAoGCCqGSM49
AwEHoUQDQgAEYcO2xNKiRUYOLEHM7VYAp57HNyKbOdYtHD83Z4hzNPVC4tM5mdGD
PLL8IEwvYu2wq+lpXfGQnNMbzYf9gspG0w==
-----END EC PRIVATE KEY-----
+`),
+ "ca": []byte(`-----BEGIN RSA PRIVATE KEY-----
+MIIEpAIBAAKCAQEAvg9dQ9IRG59lYJb+GESfKWTch4yBpr7Ydw1jkK6vvtrx9jLo
+5hkA8X6+ElRPRqTAZSlN5cBm6YCAcQIOsmXDUn6Oj1lVPQAoOjTBTvsjM3NjGhvv
+52kHTY0nsMsBeY9q5DTtlzmlYkVUq2a6Htgf2mNi01dIw5fJ7uTTo8EbNf7O0i3u
+c9a8P19HaZl5NKiWN4EIZkfB2WdXYRJCVBsGgQj3dE/GrEmH9QINq1A+GkNvK96u
+vZm8H1jjmuqzHplWa7lFeXcx8FTVTbVb/iJrZ2Lc/JvIPitKZWhqbR59yrGjpwEp
+Id7bo4WhO5L3OB0fSIJYvfu+o4WYnt4f3UzecwIDAQABAoIBABRD9yHgKErVuC2Q
+bA+SYZY8VvdtF/X7q4EmQFORDNRA7EPgMc03JU6awRGbQ8i4kHs46EFzPoXvWcKz
+AXYsO6N0Myc900Tp22A5d9NAHATEbPC/wdje7hRq1KyZONMJY9BphFv3nZbY5apR
+Dc90JBFZP5RhXjTc3n9GjvqLAKfFEKVmPRCvqxCOZunw6XR+SgIQLJo36nsIsbhW
+QUXIVaCI6cXMN8bRPm8EITdBNZu06Fpu4ZHm6VaxlXN9smERCDkgBSNXNWHKxmmA
+c3Glo2DByUr2/JFBOrLEe9fkYgr24KNCQkHVcSaFxEcZvTggr7StjKISVHlCNEaB
+7Q+kPoECgYEA3zE9FmvFGoQCU4g4Nl3dpQHs6kaAW8vJlrmq3xsireIuaJoa2HMe
+wYdIvgCnK9DIjyxd5OWnE4jXtAEYPsyGD32B5rSLQrRO96lgb3f4bESCLUb3Bsn/
+sdgeE3p1xZMA0B59htqCrvVgN9k8WxyevBxYl3/gSBm/p8OVH1RTW/ECgYEA2f9Z
+95OLj0KQHQtxQXf+I3VjhCw3LkLW39QZOXVI0QrCJfqqP7uxsJXH9NYX0l0GFTcR
+kRrlyoaSU1EGQosZh+n1MvplGBTkTSV47/bPsTzFpgK2NfEZuFm9RoWgltS+nYeH
+Y2k4mnAN3PhReCMwuprmJz8GRLsO3Cs2s2YylKMCgYEA2UX+uO/q7jgqZ5UJW+ue
+1H5+W0aMuFA3i7JtZEnvRaUVFqFGlwXin/WJ2+WY1++k/rPrJ+Rk9IBXtBUIvEGw
+FC5TIfsKQsJyyWgqx/jbbtJ2g4s8+W/1qfTAuqeRNOg5d2DnRDs90wJuS4//0JaY
+9HkHyVwkQyxFxhSA/AHEMJECgYA2MvyFR1O9bIk0D3I7GsA+xKLXa77Ua53MzIjw
+9i4CezBGDQpjCiFli/fI8am+jY5DnAtsDknvjoG24UAzLy5L0mk6IXMdB6SzYYut
+7ak5oahqW+Y9hxIj+XvLmtGQbphtxhJtLu35x75KoBpxSh6FZpmuTEccs31AVCYn
+eFM/DQKBgQDOPUwbLKqVi6ddFGgrV9MrWw+SWsDa43bPuyvYppMM3oqesvyaX1Dt
+qDvN7owaNxNM4OnfKcZr91z8YPVCFo4RbBif3DXRzjNNBlxEjHBtuMOikwvsmucN
+vIrbeEpjTiUMTEAr6PoTiVHjsfS8WAM6MDlF5M+2PNswDsBpa2yLgA==
+-----END RSA PRIVATE KEY-----
+`),
+}
+
+var SSHCertificates = map[string][]byte{
+ // The following are corresponding certificates for the private keys above, signed by the CA key
+ // Generated by the following commands:
+ //
+ // 1. Assumes "rsa" key above in file named "rsa", write out the public key to "rsa.pub":
+ // ssh-keygen -y -f rsa > rsa.pu
+ //
+ // 2. Assumes "ca" key above in file named "ca", sign a cert for "rsa.pub":
+ // ssh-keygen -s ca -h -n host.example.com -V +500w -I host.example.com-key rsa.pub
+ "rsa": []byte(`ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgLjYqmmuTSEmjVhSfLQphBSTJMLwIZhRgmpn8FHKLiEIAAAADAQABAAAAgQC8A6FGHDiWCSREAXCq6yBfNVr0xCVG2CzvktFNRpue+RXrGs/2a6ySEJQb3IYquw7HlJgu6fg3WIWhOmHCjfpG0PrL4CRwbqQ2LaPPXhJErWYejcD8Di00cF3677+G10KMZk9RXbmHtuBFZT98wxg8j+ZsBMqGM1+7yrWUvynswQAAAAAAAAAAAAAAAgAAABRob3N0LmV4YW1wbGUuY29tLWtleQAAABQAAAAQaG9zdC5leGFtcGxlLmNvbQAAAABZHN8UAAAAAGsjIYUAAAAAAAAAAAAAAAAAAAEXAAAAB3NzaC1yc2EAAAADAQABAAABAQC+D11D0hEbn2Vglv4YRJ8pZNyHjIGmvth3DWOQrq++2vH2MujmGQDxfr4SVE9GpMBlKU3lwGbpgIBxAg6yZcNSfo6PWVU9ACg6NMFO+yMzc2MaG+/naQdNjSewywF5j2rkNO2XOaViRVSrZroe2B/aY2LTV0jDl8nu5NOjwRs1/s7SLe5z1rw/X0dpmXk0qJY3gQhmR8HZZ1dhEkJUGwaBCPd0T8asSYf1Ag2rUD4aQ28r3q69mbwfWOOa6rMemVZruUV5dzHwVNVNtVv+ImtnYtz8m8g+K0plaGptHn3KsaOnASkh3tujhaE7kvc4HR9Igli9+76jhZie3h/dTN5zAAABDwAAAAdzc2gtcnNhAAABALeDea+60H6xJGhktAyosHaSY7AYzLocaqd8hJQjEIDifBwzoTlnBmcK9CxGhKuaoJFThdCLdaevCeOSuquh8HTkf+2ebZZc/G5T+2thPvPqmcuEcmMosWo+SIjYhbP3S6KD49aLC1X0kz8IBQeauFvURhkZ5ZjhA1L4aQYt9NjL73nqOl8PplRui+Ov5w8b4ldul4zOvYAFrzfcP6wnnXk3c1Zzwwf5wynD5jakO8GpYKBuhM7Z4crzkKSQjU3hla7xqgfomC5Gz4XbR2TNjcQiRrJQ0UlKtX3X3ObRCEhuvG0Kzjklhv+Ddw6txrhKjMjiSi/Yyius/AE8TmC1p4U= host.example.com
`),
}
diff --git a/vendor/golang.org/x/crypto/ssh/transport.go b/vendor/golang.org/x/crypto/ssh/transport.go
index fd19932..f9780e0 100644
--- a/vendor/golang.org/x/crypto/ssh/transport.go
+++ b/vendor/golang.org/x/crypto/ssh/transport.go
@@ -8,8 +8,13 @@ import (
"bufio"
"errors"
"io"
+ "log"
)
+// debugTransport if set, will print packet types as they go over the
+// wire. No message decoding is done, to minimize the impact on timing.
+const debugTransport = false
+
const (
gcmCipherID = "aes128-gcm@openssh.com"
aes128cbcID = "aes128-cbc"
@@ -40,7 +45,7 @@ type transport struct {
bufReader *bufio.Reader
bufWriter *bufio.Writer
rand io.Reader
-
+ isClient bool
io.Closer
}
@@ -86,6 +91,22 @@ func (t *transport) prepareKeyChange(algs *algorithms, kexResult *kexResult) err
return nil
}
+func (t *transport) printPacket(p []byte, write bool) {
+ if len(p) == 0 {
+ return
+ }
+ who := "server"
+ if t.isClient {
+ who = "client"
+ }
+ what := "read"
+ if write {
+ what = "write"
+ }
+
+ log.Println(what, who, p[0])
+}
+
// Read and decrypt next packet.
func (t *transport) readPacket() (p []byte, err error) {
for {
@@ -97,6 +118,9 @@ func (t *transport) readPacket() (p []byte, err error) {
break
}
}
+ if debugTransport {
+ t.printPacket(p, false)
+ }
return p, err
}
@@ -141,6 +165,9 @@ func (s *connectionState) readPacket(r *bufio.Reader) ([]byte, error) {
}
func (t *transport) writePacket(packet []byte) error {
+ if debugTransport {
+ t.printPacket(packet, true)
+ }
return t.writer.writePacket(t.bufWriter, t.rand, packet)
}
@@ -181,6 +208,8 @@ func newTransport(rwc io.ReadWriteCloser, rand io.Reader, isClient bool) *transp
},
Closer: rwc,
}
+ t.isClient = isClient
+
if isClient {
t.reader.dir = serverKeys
t.writer.dir = clientKeys
@@ -238,6 +267,7 @@ func newPacketCipher(d direction, algs directionAlgorithms, kex *kexResult) (pac
c := &streamPacketCipher{
mac: macModes[algs.MAC].new(macKey),
+ etm: macModes[algs.MAC].etm,
}
c.macResult = make([]byte, c.mac.Size())
diff --git a/vendor/golang.org/x/crypto/xts/xts.go b/vendor/golang.org/x/crypto/xts/xts.go
index c9a283b..a7643fd 100644
--- a/vendor/golang.org/x/crypto/xts/xts.go
+++ b/vendor/golang.org/x/crypto/xts/xts.go
@@ -23,6 +23,7 @@ package xts // import "golang.org/x/crypto/xts"
import (
"crypto/cipher"
+ "encoding/binary"
"errors"
)
@@ -65,21 +66,20 @@ func (c *Cipher) Encrypt(ciphertext, plaintext []byte, sectorNum uint64) {
}
var tweak [blockSize]byte
- for i := 0; i < 8; i++ {
- tweak[i] = byte(sectorNum)
- sectorNum >>= 8
- }
+ binary.LittleEndian.PutUint64(tweak[:8], sectorNum)
c.k2.Encrypt(tweak[:], tweak[:])
- for i := 0; i < len(plaintext); i += blockSize {
- for j := 0; j < blockSize; j++ {
- ciphertext[i+j] = plaintext[i+j] ^ tweak[j]
+ for len(plaintext) > 0 {
+ for j := range tweak {
+ ciphertext[j] = plaintext[j] ^ tweak[j]
}
- c.k1.Encrypt(ciphertext[i:], ciphertext[i:])
- for j := 0; j < blockSize; j++ {
- ciphertext[i+j] ^= tweak[j]
+ c.k1.Encrypt(ciphertext, ciphertext)
+ for j := range tweak {
+ ciphertext[j] ^= tweak[j]
}
+ plaintext = plaintext[blockSize:]
+ ciphertext = ciphertext[blockSize:]
mul2(&tweak)
}
@@ -97,21 +97,20 @@ func (c *Cipher) Decrypt(plaintext, ciphertext []byte, sectorNum uint64) {
}
var tweak [blockSize]byte
- for i := 0; i < 8; i++ {
- tweak[i] = byte(sectorNum)
- sectorNum >>= 8
- }
+ binary.LittleEndian.PutUint64(tweak[:8], sectorNum)
c.k2.Encrypt(tweak[:], tweak[:])
- for i := 0; i < len(plaintext); i += blockSize {
- for j := 0; j < blockSize; j++ {
- plaintext[i+j] = ciphertext[i+j] ^ tweak[j]
+ for len(ciphertext) > 0 {
+ for j := range tweak {
+ plaintext[j] = ciphertext[j] ^ tweak[j]
}
- c.k1.Decrypt(plaintext[i:], plaintext[i:])
- for j := 0; j < blockSize; j++ {
- plaintext[i+j] ^= tweak[j]
+ c.k1.Decrypt(plaintext, plaintext)
+ for j := range tweak {
+ plaintext[j] ^= tweak[j]
}
+ plaintext = plaintext[blockSize:]
+ ciphertext = ciphertext[blockSize:]
mul2(&tweak)
}
diff --git a/vendor/golang.org/x/crypto/xts/xts_test.go b/vendor/golang.org/x/crypto/xts/xts_test.go
index 7a5e9fa..96d3b6c 100644
--- a/vendor/golang.org/x/crypto/xts/xts_test.go
+++ b/vendor/golang.org/x/crypto/xts/xts_test.go
@@ -83,3 +83,23 @@ func TestXTS(t *testing.T) {
}
}
}
+
+func TestShorterCiphertext(t *testing.T) {
+ // Decrypt used to panic if the input was shorter than the output. See
+ // https://go-review.googlesource.com/c/39954/
+ c, err := NewCipher(aes.NewCipher, make([]byte, 32))
+ if err != nil {
+ t.Fatalf("NewCipher failed: %s", err)
+ }
+
+ plaintext := make([]byte, 32)
+ encrypted := make([]byte, 48)
+ decrypted := make([]byte, 48)
+
+ c.Encrypt(encrypted, plaintext, 0)
+ c.Decrypt(decrypted, encrypted[:len(plaintext)], 0)
+
+ if !bytes.Equal(plaintext, decrypted[:len(plaintext)]) {
+ t.Errorf("En/Decryption is not inverse")
+ }
+}
diff --git a/vendor/golang.org/x/sys/.gitattributes b/vendor/golang.org/x/sys/.gitattributes
new file mode 100644
index 0000000..d2f212e
--- /dev/null
+++ b/vendor/golang.org/x/sys/.gitattributes
@@ -0,0 +1,10 @@
+# Treat all files in this repo as binary, with no git magic updating
+# line endings. Windows users contributing to Go will need to use a
+# modern version of git and editors capable of LF line endings.
+#
+# We'll prevent accidental CRLF line endings from entering the repo
+# via the git-review gofmt checks.
+#
+# See golang.org/issue/9281
+
+* -text
diff --git a/vendor/golang.org/x/sys/.gitignore b/vendor/golang.org/x/sys/.gitignore
new file mode 100644
index 0000000..8339fd6
--- /dev/null
+++ b/vendor/golang.org/x/sys/.gitignore
@@ -0,0 +1,2 @@
+# Add no patterns to .hgignore except for files generated by the build.
+last-change
diff --git a/vendor/golang.org/x/sys/AUTHORS b/vendor/golang.org/x/sys/AUTHORS
new file mode 100644
index 0000000..15167cd
--- /dev/null
+++ b/vendor/golang.org/x/sys/AUTHORS
@@ -0,0 +1,3 @@
+# This source code refers to The Go Authors for copyright purposes.
+# The master list of authors is in the main Go distribution,
+# visible at http://tip.golang.org/AUTHORS.
diff --git a/vendor/golang.org/x/sys/CONTRIBUTING.md b/vendor/golang.org/x/sys/CONTRIBUTING.md
new file mode 100644
index 0000000..88dff59
--- /dev/null
+++ b/vendor/golang.org/x/sys/CONTRIBUTING.md
@@ -0,0 +1,31 @@
+# Contributing to Go
+
+Go is an open source project.
+
+It is the work of hundreds of contributors. We appreciate your help!
+
+
+## Filing issues
+
+When [filing an issue](https://golang.org/issue/new), make sure to answer these five questions:
+
+1. What version of Go are you using (`go version`)?
+2. What operating system and processor architecture are you using?
+3. What did you do?
+4. What did you expect to see?
+5. What did you see instead?
+
+General questions should go to the [golang-nuts mailing list](https://groups.google.com/group/golang-nuts) instead of the issue tracker.
+The gophers there will answer or ask you to file an issue if you've tripped over a bug.
+
+## Contributing code
+
+Please read the [Contribution Guidelines](https://golang.org/doc/contribute.html)
+before sending patches.
+
+**We do not accept GitHub pull requests**
+(we use [Gerrit](https://code.google.com/p/gerrit/) instead for code review).
+
+Unless otherwise noted, the Go source files are distributed under
+the BSD-style license found in the LICENSE file.
+
diff --git a/vendor/golang.org/x/sys/CONTRIBUTORS b/vendor/golang.org/x/sys/CONTRIBUTORS
new file mode 100644
index 0000000..1c4577e
--- /dev/null
+++ b/vendor/golang.org/x/sys/CONTRIBUTORS
@@ -0,0 +1,3 @@
+# This source code was written by the Go contributors.
+# The master list of contributors is in the main Go distribution,
+# visible at http://tip.golang.org/CONTRIBUTORS.
diff --git a/vendor/golang.org/x/sys/LICENSE b/vendor/golang.org/x/sys/LICENSE
new file mode 100644
index 0000000..6a66aea
--- /dev/null
+++ b/vendor/golang.org/x/sys/LICENSE
@@ -0,0 +1,27 @@
+Copyright (c) 2009 The Go Authors. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/vendor/golang.org/x/sys/PATENTS b/vendor/golang.org/x/sys/PATENTS
new file mode 100644
index 0000000..7330990
--- /dev/null
+++ b/vendor/golang.org/x/sys/PATENTS
@@ -0,0 +1,22 @@
+Additional IP Rights Grant (Patents)
+
+"This implementation" means the copyrightable works distributed by
+Google as part of the Go project.
+
+Google hereby grants to You a perpetual, worldwide, non-exclusive,
+no-charge, royalty-free, irrevocable (except as stated in this section)
+patent license to make, have made, use, offer to sell, sell, import,
+transfer and otherwise run, modify and propagate the contents of this
+implementation of Go, where such license applies only to those patent
+claims, both currently owned or controlled by Google and acquired in
+the future, licensable by Google that are necessarily infringed by this
+implementation of Go. This grant does not include claims that would be
+infringed only as a consequence of further modification of this
+implementation. If you or your agent or exclusive licensee institute or
+order or agree to the institution of patent litigation against any
+entity (including a cross-claim or counterclaim in a lawsuit) alleging
+that this implementation of Go or any code incorporated within this
+implementation of Go constitutes direct or contributory patent
+infringement, or inducement of patent infringement, then any patent
+rights granted to you under this License for this implementation of Go
+shall terminate as of the date such litigation is filed.
diff --git a/vendor/golang.org/x/sys/README b/vendor/golang.org/x/sys/README
new file mode 100644
index 0000000..bd422b4
--- /dev/null
+++ b/vendor/golang.org/x/sys/README
@@ -0,0 +1,3 @@
+This repository holds supplemental Go packages for low-level interactions with the operating system.
+
+To submit changes to this repository, see http://golang.org/doc/contribute.html.
diff --git a/vendor/golang.org/x/sys/codereview.cfg b/vendor/golang.org/x/sys/codereview.cfg
new file mode 100644
index 0000000..3f8b14b
--- /dev/null
+++ b/vendor/golang.org/x/sys/codereview.cfg
@@ -0,0 +1 @@
+issuerepo: golang/go
diff --git a/vendor/golang.org/x/sys/plan9/asm.s b/vendor/golang.org/x/sys/plan9/asm.s
new file mode 100644
index 0000000..d4ca868
--- /dev/null
+++ b/vendor/golang.org/x/sys/plan9/asm.s
@@ -0,0 +1,8 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "textflag.h"
+
+TEXT ·use(SB),NOSPLIT,$0
+ RET
diff --git a/vendor/golang.org/x/sys/plan9/asm_plan9_386.s b/vendor/golang.org/x/sys/plan9/asm_plan9_386.s
new file mode 100644
index 0000000..bc5cab1
--- /dev/null
+++ b/vendor/golang.org/x/sys/plan9/asm_plan9_386.s
@@ -0,0 +1,30 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "textflag.h"
+
+//
+// System call support for 386, Plan 9
+//
+
+// Just jump to package syscall's implementation for all these functions.
+// The runtime may know about them.
+
+TEXT ·Syscall(SB),NOSPLIT,$0-32
+ JMP syscall·Syscall(SB)
+
+TEXT ·Syscall6(SB),NOSPLIT,$0-44
+ JMP syscall·Syscall6(SB)
+
+TEXT ·RawSyscall(SB),NOSPLIT,$0-28
+ JMP syscall·RawSyscall(SB)
+
+TEXT ·RawSyscall6(SB),NOSPLIT,$0-40
+ JMP syscall·RawSyscall6(SB)
+
+TEXT ·seek(SB),NOSPLIT,$0-36
+ JMP syscall·seek(SB)
+
+TEXT ·exit(SB),NOSPLIT,$4-4
+ JMP syscall·exit(SB)
diff --git a/vendor/golang.org/x/sys/plan9/asm_plan9_amd64.s b/vendor/golang.org/x/sys/plan9/asm_plan9_amd64.s
new file mode 100644
index 0000000..d3448e6
--- /dev/null
+++ b/vendor/golang.org/x/sys/plan9/asm_plan9_amd64.s
@@ -0,0 +1,30 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "textflag.h"
+
+//
+// System call support for amd64, Plan 9
+//
+
+// Just jump to package syscall's implementation for all these functions.
+// The runtime may know about them.
+
+TEXT ·Syscall(SB),NOSPLIT,$0-64
+ JMP syscall·Syscall(SB)
+
+TEXT ·Syscall6(SB),NOSPLIT,$0-88
+ JMP syscall·Syscall6(SB)
+
+TEXT ·RawSyscall(SB),NOSPLIT,$0-56
+ JMP syscall·RawSyscall(SB)
+
+TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
+ JMP syscall·RawSyscall6(SB)
+
+TEXT ·seek(SB),NOSPLIT,$0-56
+ JMP syscall·seek(SB)
+
+TEXT ·exit(SB),NOSPLIT,$8-8
+ JMP syscall·exit(SB)
diff --git a/vendor/golang.org/x/sys/plan9/const_plan9.go b/vendor/golang.org/x/sys/plan9/const_plan9.go
new file mode 100644
index 0000000..b4e85a3
--- /dev/null
+++ b/vendor/golang.org/x/sys/plan9/const_plan9.go
@@ -0,0 +1,70 @@
+package plan9
+
+// Plan 9 Constants
+
+// Open modes
+const (
+ O_RDONLY = 0
+ O_WRONLY = 1
+ O_RDWR = 2
+ O_TRUNC = 16
+ O_CLOEXEC = 32
+ O_EXCL = 0x1000
+)
+
+// Rfork flags
+const (
+ RFNAMEG = 1 << 0
+ RFENVG = 1 << 1
+ RFFDG = 1 << 2
+ RFNOTEG = 1 << 3
+ RFPROC = 1 << 4
+ RFMEM = 1 << 5
+ RFNOWAIT = 1 << 6
+ RFCNAMEG = 1 << 10
+ RFCENVG = 1 << 11
+ RFCFDG = 1 << 12
+ RFREND = 1 << 13
+ RFNOMNT = 1 << 14
+)
+
+// Qid.Type bits
+const (
+ QTDIR = 0x80
+ QTAPPEND = 0x40
+ QTEXCL = 0x20
+ QTMOUNT = 0x10
+ QTAUTH = 0x08
+ QTTMP = 0x04
+ QTFILE = 0x00
+)
+
+// Dir.Mode bits
+const (
+ DMDIR = 0x80000000
+ DMAPPEND = 0x40000000
+ DMEXCL = 0x20000000
+ DMMOUNT = 0x10000000
+ DMAUTH = 0x08000000
+ DMTMP = 0x04000000
+ DMREAD = 0x4
+ DMWRITE = 0x2
+ DMEXEC = 0x1
+)
+
+const (
+ STATMAX = 65535
+ ERRMAX = 128
+ STATFIXLEN = 49
+)
+
+// Mount and bind flags
+const (
+ MREPL = 0x0000
+ MBEFORE = 0x0001
+ MAFTER = 0x0002
+ MORDER = 0x0003
+ MCREATE = 0x0004
+ MCACHE = 0x0010
+ MMASK = 0x0017
+)
diff --git a/vendor/golang.org/x/sys/plan9/dir_plan9.go b/vendor/golang.org/x/sys/plan9/dir_plan9.go
new file mode 100644
index 0000000..0955e0c
--- /dev/null
+++ b/vendor/golang.org/x/sys/plan9/dir_plan9.go
@@ -0,0 +1,212 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Plan 9 directory marshalling. See intro(5).
+
+package plan9
+
+import "errors"
+
+var (
+ ErrShortStat = errors.New("stat buffer too short")
+ ErrBadStat = errors.New("malformed stat buffer")
+ ErrBadName = errors.New("bad character in file name")
+)
+
+// A Qid represents a 9P server's unique identification for a file.
+type Qid struct {
+ Path uint64 // the file server's unique identification for the file
+ Vers uint32 // version number for given Path
+ Type uint8 // the type of the file (plan9.QTDIR for example)
+}
+
+// A Dir contains the metadata for a file.
+type Dir struct {
+ // system-modified data
+ Type uint16 // server type
+ Dev uint32 // server subtype
+
+ // file data
+ Qid Qid // unique id from server
+ Mode uint32 // permissions
+ Atime uint32 // last read time
+ Mtime uint32 // last write time
+ Length int64 // file length
+ Name string // last element of path
+ Uid string // owner name
+ Gid string // group name
+ Muid string // last modifier name
+}
+
+var nullDir = Dir{
+ Type: ^uint16(0),
+ Dev: ^uint32(0),
+ Qid: Qid{
+ Path: ^uint64(0),
+ Vers: ^uint32(0),
+ Type: ^uint8(0),
+ },
+ Mode: ^uint32(0),
+ Atime: ^uint32(0),
+ Mtime: ^uint32(0),
+ Length: ^int64(0),
+}
+
+// Null assigns special "don't touch" values to members of d to
+// avoid modifying them during plan9.Wstat.
+func (d *Dir) Null() { *d = nullDir }
+
+// Marshal encodes a 9P stat message corresponding to d into b
+//
+// If there isn't enough space in b for a stat message, ErrShortStat is returned.
+func (d *Dir) Marshal(b []byte) (n int, err error) {
+ n = STATFIXLEN + len(d.Name) + len(d.Uid) + len(d.Gid) + len(d.Muid)
+ if n > len(b) {
+ return n, ErrShortStat
+ }
+
+ for _, c := range d.Name {
+ if c == '/' {
+ return n, ErrBadName
+ }
+ }
+
+ b = pbit16(b, uint16(n)-2)
+ b = pbit16(b, d.Type)
+ b = pbit32(b, d.Dev)
+ b = pbit8(b, d.Qid.Type)
+ b = pbit32(b, d.Qid.Vers)
+ b = pbit64(b, d.Qid.Path)
+ b = pbit32(b, d.Mode)
+ b = pbit32(b, d.Atime)
+ b = pbit32(b, d.Mtime)
+ b = pbit64(b, uint64(d.Length))
+ b = pstring(b, d.Name)
+ b = pstring(b, d.Uid)
+ b = pstring(b, d.Gid)
+ b = pstring(b, d.Muid)
+
+ return n, nil
+}
+
+// UnmarshalDir decodes a single 9P stat message from b and returns the resulting Dir.
+//
+// If b is too small to hold a valid stat message, ErrShortStat is returned.
+//
+// If the stat message itself is invalid, ErrBadStat is returned.
+func UnmarshalDir(b []byte) (*Dir, error) {
+ if len(b) < STATFIXLEN {
+ return nil, ErrShortStat
+ }
+ size, buf := gbit16(b)
+ if len(b) != int(size)+2 {
+ return nil, ErrBadStat
+ }
+ b = buf
+
+ var d Dir
+ d.Type, b = gbit16(b)
+ d.Dev, b = gbit32(b)
+ d.Qid.Type, b = gbit8(b)
+ d.Qid.Vers, b = gbit32(b)
+ d.Qid.Path, b = gbit64(b)
+ d.Mode, b = gbit32(b)
+ d.Atime, b = gbit32(b)
+ d.Mtime, b = gbit32(b)
+
+ n, b := gbit64(b)
+ d.Length = int64(n)
+
+ var ok bool
+ if d.Name, b, ok = gstring(b); !ok {
+ return nil, ErrBadStat
+ }
+ if d.Uid, b, ok = gstring(b); !ok {
+ return nil, ErrBadStat
+ }
+ if d.Gid, b, ok = gstring(b); !ok {
+ return nil, ErrBadStat
+ }
+ if d.Muid, b, ok = gstring(b); !ok {
+ return nil, ErrBadStat
+ }
+
+ return &d, nil
+}
+
+// pbit8 copies the 8-bit number v to b and returns the remaining slice of b.
+func pbit8(b []byte, v uint8) []byte {
+ b[0] = byte(v)
+ return b[1:]
+}
+
+// pbit16 copies the 16-bit number v to b in little-endian order and returns the remaining slice of b.
+func pbit16(b []byte, v uint16) []byte {
+ b[0] = byte(v)
+ b[1] = byte(v >> 8)
+ return b[2:]
+}
+
+// pbit32 copies the 32-bit number v to b in little-endian order and returns the remaining slice of b.
+func pbit32(b []byte, v uint32) []byte {
+ b[0] = byte(v)
+ b[1] = byte(v >> 8)
+ b[2] = byte(v >> 16)
+ b[3] = byte(v >> 24)
+ return b[4:]
+}
+
+// pbit64 copies the 64-bit number v to b in little-endian order and returns the remaining slice of b.
+func pbit64(b []byte, v uint64) []byte {
+ b[0] = byte(v)
+ b[1] = byte(v >> 8)
+ b[2] = byte(v >> 16)
+ b[3] = byte(v >> 24)
+ b[4] = byte(v >> 32)
+ b[5] = byte(v >> 40)
+ b[6] = byte(v >> 48)
+ b[7] = byte(v >> 56)
+ return b[8:]
+}
+
+// pstring copies the string s to b, prepending it with a 16-bit length in little-endian order, and
+// returning the remaining slice of b..
+func pstring(b []byte, s string) []byte {
+ b = pbit16(b, uint16(len(s)))
+ n := copy(b, s)
+ return b[n:]
+}
+
+// gbit8 reads an 8-bit number from b and returns it with the remaining slice of b.
+func gbit8(b []byte) (uint8, []byte) {
+ return uint8(b[0]), b[1:]
+}
+
+// gbit16 reads a 16-bit number in little-endian order from b and returns it with the remaining slice of b.
+func gbit16(b []byte) (uint16, []byte) {
+ return uint16(b[0]) | uint16(b[1])<<8, b[2:]
+}
+
+// gbit32 reads a 32-bit number in little-endian order from b and returns it with the remaining slice of b.
+func gbit32(b []byte) (uint32, []byte) {
+ return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24, b[4:]
+}
+
+// gbit64 reads a 64-bit number in little-endian order from b and returns it with the remaining slice of b.
+func gbit64(b []byte) (uint64, []byte) {
+ lo := uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
+ hi := uint32(b[4]) | uint32(b[5])<<8 | uint32(b[6])<<16 | uint32(b[7])<<24
+ return uint64(lo) | uint64(hi)<<32, b[8:]
+}
+
+// gstring reads a string from b, prefixed with a 16-bit length in little-endian order.
+// It returns the string with the remaining slice of b and a boolean. If the length is
+// greater than the number of bytes in b, the boolean will be false.
+func gstring(b []byte) (string, []byte, bool) {
+ n, b := gbit16(b)
+ if int(n) > len(b) {
+ return "", b, false
+ }
+ return string(b[:n]), b[n:], true
+}
diff --git a/vendor/golang.org/x/sys/plan9/env_plan9.go b/vendor/golang.org/x/sys/plan9/env_plan9.go
new file mode 100644
index 0000000..25a96e7
--- /dev/null
+++ b/vendor/golang.org/x/sys/plan9/env_plan9.go
@@ -0,0 +1,27 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Plan 9 environment variables.
+
+package plan9
+
+import (
+ "syscall"
+)
+
+func Getenv(key string) (value string, found bool) {
+ return syscall.Getenv(key)
+}
+
+func Setenv(key, value string) error {
+ return syscall.Setenv(key, value)
+}
+
+func Clearenv() {
+ syscall.Clearenv()
+}
+
+func Environ() []string {
+ return syscall.Environ()
+}
diff --git a/vendor/golang.org/x/sys/plan9/env_unset.go b/vendor/golang.org/x/sys/plan9/env_unset.go
new file mode 100644
index 0000000..c37fc26
--- /dev/null
+++ b/vendor/golang.org/x/sys/plan9/env_unset.go
@@ -0,0 +1,14 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build go1.4
+
+package plan9
+
+import "syscall"
+
+func Unsetenv(key string) error {
+ // This was added in Go 1.4.
+ return syscall.Unsetenv(key)
+}
diff --git a/vendor/golang.org/x/sys/plan9/errors_plan9.go b/vendor/golang.org/x/sys/plan9/errors_plan9.go
new file mode 100644
index 0000000..110cf6a
--- /dev/null
+++ b/vendor/golang.org/x/sys/plan9/errors_plan9.go
@@ -0,0 +1,50 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package plan9
+
+import "syscall"
+
+// Constants
+const (
+ // Invented values to support what package os expects.
+ O_CREAT = 0x02000
+ O_APPEND = 0x00400
+ O_NOCTTY = 0x00000
+ O_NONBLOCK = 0x00000
+ O_SYNC = 0x00000
+ O_ASYNC = 0x00000
+
+ S_IFMT = 0x1f000
+ S_IFIFO = 0x1000
+ S_IFCHR = 0x2000
+ S_IFDIR = 0x4000
+ S_IFBLK = 0x6000
+ S_IFREG = 0x8000
+ S_IFLNK = 0xa000
+ S_IFSOCK = 0xc000
+)
+
+// Errors
+var (
+ EINVAL = syscall.NewError("bad arg in system call")
+ ENOTDIR = syscall.NewError("not a directory")
+ EISDIR = syscall.NewError("file is a directory")
+ ENOENT = syscall.NewError("file does not exist")
+ EEXIST = syscall.NewError("file already exists")
+ EMFILE = syscall.NewError("no free file descriptors")
+ EIO = syscall.NewError("i/o error")
+ ENAMETOOLONG = syscall.NewError("file name too long")
+ EINTR = syscall.NewError("interrupted")
+ EPERM = syscall.NewError("permission denied")
+ EBUSY = syscall.NewError("no free devices")
+ ETIMEDOUT = syscall.NewError("connection timed out")
+ EPLAN9 = syscall.NewError("not supported by plan 9")
+
+ // The following errors do not correspond to any
+ // Plan 9 system messages. Invented to support
+ // what package os and others expect.
+ EACCES = syscall.NewError("access permission denied")
+ EAFNOSUPPORT = syscall.NewError("address family not supported by protocol")
+)
diff --git a/vendor/golang.org/x/sys/plan9/mkall.sh b/vendor/golang.org/x/sys/plan9/mkall.sh
new file mode 100755
index 0000000..9f73c60
--- /dev/null
+++ b/vendor/golang.org/x/sys/plan9/mkall.sh
@@ -0,0 +1,138 @@
+#!/usr/bin/env bash
+# Copyright 2009 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+# The plan9 package provides access to the raw system call
+# interface of the underlying operating system. Porting Go to
+# a new architecture/operating system combination requires
+# some manual effort, though there are tools that automate
+# much of the process. The auto-generated files have names
+# beginning with z.
+#
+# This script runs or (given -n) prints suggested commands to generate z files
+# for the current system. Running those commands is not automatic.
+# This script is documentation more than anything else.
+#
+# * asm_${GOOS}_${GOARCH}.s
+#
+# This hand-written assembly file implements system call dispatch.
+# There are three entry points:
+#
+# func Syscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr);
+# func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr);
+# func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr);
+#
+# The first and second are the standard ones; they differ only in
+# how many arguments can be passed to the kernel.
+# The third is for low-level use by the ForkExec wrapper;
+# unlike the first two, it does not call into the scheduler to
+# let it know that a system call is running.
+#
+# * syscall_${GOOS}.go
+#
+# This hand-written Go file implements system calls that need
+# special handling and lists "//sys" comments giving prototypes
+# for ones that can be auto-generated. Mksyscall reads those
+# comments to generate the stubs.
+#
+# * syscall_${GOOS}_${GOARCH}.go
+#
+# Same as syscall_${GOOS}.go except that it contains code specific
+# to ${GOOS} on one particular architecture.
+#
+# * types_${GOOS}.c
+#
+# This hand-written C file includes standard C headers and then
+# creates typedef or enum names beginning with a dollar sign
+# (use of $ in variable names is a gcc extension). The hardest
+# part about preparing this file is figuring out which headers to
+# include and which symbols need to be #defined to get the
+# actual data structures that pass through to the kernel system calls.
+# Some C libraries present alternate versions for binary compatibility
+# and translate them on the way in and out of system calls, but
+# there is almost always a #define that can get the real ones.
+# See types_darwin.c and types_linux.c for examples.
+#
+# * zerror_${GOOS}_${GOARCH}.go
+#
+# This machine-generated file defines the system's error numbers,
+# error strings, and signal numbers. The generator is "mkerrors.sh".
+# Usually no arguments are needed, but mkerrors.sh will pass its
+# arguments on to godefs.
+#
+# * zsyscall_${GOOS}_${GOARCH}.go
+#
+# Generated by mksyscall.pl; see syscall_${GOOS}.go above.
+#
+# * zsysnum_${GOOS}_${GOARCH}.go
+#
+# Generated by mksysnum_${GOOS}.
+#
+# * ztypes_${GOOS}_${GOARCH}.go
+#
+# Generated by godefs; see types_${GOOS}.c above.
+
+GOOSARCH="${GOOS}_${GOARCH}"
+
+# defaults
+mksyscall="./mksyscall.pl"
+mkerrors="./mkerrors.sh"
+zerrors="zerrors_$GOOSARCH.go"
+mksysctl=""
+zsysctl="zsysctl_$GOOSARCH.go"
+mksysnum=
+mktypes=
+run="sh"
+
+case "$1" in
+-syscalls)
+ for i in zsyscall*go
+ do
+ sed 1q $i | sed 's;^// ;;' | sh > _$i && gofmt < _$i > $i
+ rm _$i
+ done
+ exit 0
+ ;;
+-n)
+ run="cat"
+ shift
+esac
+
+case "$#" in
+0)
+ ;;
+*)
+ echo 'usage: mkall.sh [-n]' 1>&2
+ exit 2
+esac
+
+case "$GOOSARCH" in
+_* | *_ | _)
+ echo 'undefined $GOOS_$GOARCH:' "$GOOSARCH" 1>&2
+ exit 1
+ ;;
+plan9_386)
+ mkerrors=
+ mksyscall="./mksyscall.pl -l32 -plan9"
+ mksysnum="./mksysnum_plan9.sh /n/sources/plan9/sys/src/libc/9syscall/sys.h"
+ mktypes="XXX"
+ ;;
+*)
+ echo 'unrecognized $GOOS_$GOARCH: ' "$GOOSARCH" 1>&2
+ exit 1
+ ;;
+esac
+
+(
+ if [ -n "$mkerrors" ]; then echo "$mkerrors |gofmt >$zerrors"; fi
+ case "$GOOS" in
+ plan9)
+ syscall_goos="syscall_$GOOS.go"
+ if [ -n "$mksyscall" ]; then echo "$mksyscall $syscall_goos syscall_$GOOSARCH.go |gofmt >zsyscall_$GOOSARCH.go"; fi
+ ;;
+ esac
+ if [ -n "$mksysctl" ]; then echo "$mksysctl |gofmt >$zsysctl"; fi
+ if [ -n "$mksysnum" ]; then echo "$mksysnum |gofmt >zsysnum_$GOOSARCH.go"; fi
+ if [ -n "$mktypes" ]; then echo "$mktypes types_$GOOS.go |gofmt >ztypes_$GOOSARCH.go"; fi
+) | $run
diff --git a/vendor/golang.org/x/sys/plan9/mkerrors.sh b/vendor/golang.org/x/sys/plan9/mkerrors.sh
new file mode 100755
index 0000000..052c86d
--- /dev/null
+++ b/vendor/golang.org/x/sys/plan9/mkerrors.sh
@@ -0,0 +1,246 @@
+#!/usr/bin/env bash
+# Copyright 2009 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+# Generate Go code listing errors and other #defined constant
+# values (ENAMETOOLONG etc.), by asking the preprocessor
+# about the definitions.
+
+unset LANG
+export LC_ALL=C
+export LC_CTYPE=C
+
+CC=${CC:-gcc}
+
+uname=$(uname)
+
+includes='
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+'
+
+ccflags="$@"
+
+# Write go tool cgo -godefs input.
+(
+ echo package plan9
+ echo
+ echo '/*'
+ indirect="includes_$(uname)"
+ echo "${!indirect} $includes"
+ echo '*/'
+ echo 'import "C"'
+ echo
+ echo 'const ('
+
+ # The gcc command line prints all the #defines
+ # it encounters while processing the input
+ echo "${!indirect} $includes" | $CC -x c - -E -dM $ccflags |
+ awk '
+ $1 != "#define" || $2 ~ /\(/ || $3 == "" {next}
+
+ $2 ~ /^E([ABCD]X|[BIS]P|[SD]I|S|FL)$/ {next} # 386 registers
+ $2 ~ /^(SIGEV_|SIGSTKSZ|SIGRT(MIN|MAX))/ {next}
+ $2 ~ /^(SCM_SRCRT)$/ {next}
+ $2 ~ /^(MAP_FAILED)$/ {next}
+
+ $2 !~ /^ETH_/ &&
+ $2 !~ /^EPROC_/ &&
+ $2 !~ /^EQUIV_/ &&
+ $2 !~ /^EXPR_/ &&
+ $2 ~ /^E[A-Z0-9_]+$/ ||
+ $2 ~ /^B[0-9_]+$/ ||
+ $2 ~ /^V[A-Z0-9]+$/ ||
+ $2 ~ /^CS[A-Z0-9]/ ||
+ $2 ~ /^I(SIG|CANON|CRNL|EXTEN|MAXBEL|STRIP|UTF8)$/ ||
+ $2 ~ /^IGN/ ||
+ $2 ~ /^IX(ON|ANY|OFF)$/ ||
+ $2 ~ /^IN(LCR|PCK)$/ ||
+ $2 ~ /(^FLU?SH)|(FLU?SH$)/ ||
+ $2 ~ /^C(LOCAL|READ)$/ ||
+ $2 == "BRKINT" ||
+ $2 == "HUPCL" ||
+ $2 == "PENDIN" ||
+ $2 == "TOSTOP" ||
+ $2 ~ /^PAR/ ||
+ $2 ~ /^SIG[^_]/ ||
+ $2 ~ /^O[CNPFP][A-Z]+[^_][A-Z]+$/ ||
+ $2 ~ /^IN_/ ||
+ $2 ~ /^LOCK_(SH|EX|NB|UN)$/ ||
+ $2 ~ /^(AF|SOCK|SO|SOL|IPPROTO|IP|IPV6|ICMP6|TCP|EVFILT|NOTE|EV|SHUT|PROT|MAP|PACKET|MSG|SCM|MCL|DT|MADV|PR)_/ ||
+ $2 == "ICMPV6_FILTER" ||
+ $2 == "SOMAXCONN" ||
+ $2 == "NAME_MAX" ||
+ $2 == "IFNAMSIZ" ||
+ $2 ~ /^CTL_(MAXNAME|NET|QUERY)$/ ||
+ $2 ~ /^SYSCTL_VERS/ ||
+ $2 ~ /^(MS|MNT)_/ ||
+ $2 ~ /^TUN(SET|GET|ATTACH|DETACH)/ ||
+ $2 ~ /^(O|F|FD|NAME|S|PTRACE|PT)_/ ||
+ $2 ~ /^LINUX_REBOOT_CMD_/ ||
+ $2 ~ /^LINUX_REBOOT_MAGIC[12]$/ ||
+ $2 !~ "NLA_TYPE_MASK" &&
+ $2 ~ /^(NETLINK|NLM|NLMSG|NLA|IFA|IFAN|RT|RTCF|RTN|RTPROT|RTNH|ARPHRD|ETH_P)_/ ||
+ $2 ~ /^SIOC/ ||
+ $2 ~ /^TIOC/ ||
+ $2 !~ "RTF_BITS" &&
+ $2 ~ /^(IFF|IFT|NET_RT|RTM|RTF|RTV|RTA|RTAX)_/ ||
+ $2 ~ /^BIOC/ ||
+ $2 ~ /^RUSAGE_(SELF|CHILDREN|THREAD)/ ||
+ $2 ~ /^RLIMIT_(AS|CORE|CPU|DATA|FSIZE|NOFILE|STACK)|RLIM_INFINITY/ ||
+ $2 ~ /^PRIO_(PROCESS|PGRP|USER)/ ||
+ $2 ~ /^CLONE_[A-Z_]+/ ||
+ $2 !~ /^(BPF_TIMEVAL)$/ &&
+ $2 ~ /^(BPF|DLT)_/ ||
+ $2 !~ "WMESGLEN" &&
+ $2 ~ /^W[A-Z0-9]+$/ {printf("\t%s = C.%s\n", $2, $2)}
+ $2 ~ /^__WCOREFLAG$/ {next}
+ $2 ~ /^__W[A-Z0-9]+$/ {printf("\t%s = C.%s\n", substr($2,3), $2)}
+
+ {next}
+ ' | sort
+
+ echo ')'
+) >_const.go
+
+# Pull out the error names for later.
+errors=$(
+ echo '#include ' | $CC -x c - -E -dM $ccflags |
+ awk '$1=="#define" && $2 ~ /^E[A-Z0-9_]+$/ { print $2 }' |
+ sort
+)
+
+# Pull out the signal names for later.
+signals=$(
+ echo '#include ' | $CC -x c - -E -dM $ccflags |
+ awk '$1=="#define" && $2 ~ /^SIG[A-Z0-9]+$/ { print $2 }' |
+ egrep -v '(SIGSTKSIZE|SIGSTKSZ|SIGRT)' |
+ sort
+)
+
+# Again, writing regexps to a file.
+echo '#include ' | $CC -x c - -E -dM $ccflags |
+ awk '$1=="#define" && $2 ~ /^E[A-Z0-9_]+$/ { print "^\t" $2 "[ \t]*=" }' |
+ sort >_error.grep
+echo '#include ' | $CC -x c - -E -dM $ccflags |
+ awk '$1=="#define" && $2 ~ /^SIG[A-Z0-9]+$/ { print "^\t" $2 "[ \t]*=" }' |
+ egrep -v '(SIGSTKSIZE|SIGSTKSZ|SIGRT)' |
+ sort >_signal.grep
+
+echo '// mkerrors.sh' "$@"
+echo '// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT'
+echo
+go tool cgo -godefs -- "$@" _const.go >_error.out
+cat _error.out | grep -vf _error.grep | grep -vf _signal.grep
+echo
+echo '// Errors'
+echo 'const ('
+cat _error.out | grep -f _error.grep | sed 's/=\(.*\)/= Errno(\1)/'
+echo ')'
+
+echo
+echo '// Signals'
+echo 'const ('
+cat _error.out | grep -f _signal.grep | sed 's/=\(.*\)/= Signal(\1)/'
+echo ')'
+
+# Run C program to print error and syscall strings.
+(
+ echo -E "
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define nelem(x) (sizeof(x)/sizeof((x)[0]))
+
+enum { A = 'A', Z = 'Z', a = 'a', z = 'z' }; // avoid need for single quotes below
+
+int errors[] = {
+"
+ for i in $errors
+ do
+ echo -E ' '$i,
+ done
+
+ echo -E "
+};
+
+int signals[] = {
+"
+ for i in $signals
+ do
+ echo -E ' '$i,
+ done
+
+ # Use -E because on some systems bash builtin interprets \n itself.
+ echo -E '
+};
+
+static int
+intcmp(const void *a, const void *b)
+{
+ return *(int*)a - *(int*)b;
+}
+
+int
+main(void)
+{
+ int i, j, e;
+ char buf[1024], *p;
+
+ printf("\n\n// Error table\n");
+ printf("var errors = [...]string {\n");
+ qsort(errors, nelem(errors), sizeof errors[0], intcmp);
+ for(i=0; i 0 && errors[i-1] == e)
+ continue;
+ strcpy(buf, strerror(e));
+ // lowercase first letter: Bad -> bad, but STREAM -> STREAM.
+ if(A <= buf[0] && buf[0] <= Z && a <= buf[1] && buf[1] <= z)
+ buf[0] += a - A;
+ printf("\t%d: \"%s\",\n", e, buf);
+ }
+ printf("}\n\n");
+
+ printf("\n\n// Signal table\n");
+ printf("var signals = [...]string {\n");
+ qsort(signals, nelem(signals), sizeof signals[0], intcmp);
+ for(i=0; i 0 && signals[i-1] == e)
+ continue;
+ strcpy(buf, strsignal(e));
+ // lowercase first letter: Bad -> bad, but STREAM -> STREAM.
+ if(A <= buf[0] && buf[0] <= Z && a <= buf[1] && buf[1] <= z)
+ buf[0] += a - A;
+ // cut trailing : number.
+ p = strrchr(buf, ":"[0]);
+ if(p)
+ *p = '\0';
+ printf("\t%d: \"%s\",\n", e, buf);
+ }
+ printf("}\n\n");
+
+ return 0;
+}
+
+'
+) >_errors.c
+
+$CC $ccflags -o _errors _errors.c && $GORUN ./_errors && rm -f _errors.c _errors _const.go _error.grep _signal.grep _error.out
diff --git a/vendor/golang.org/x/sys/plan9/mksyscall.pl b/vendor/golang.org/x/sys/plan9/mksyscall.pl
new file mode 100755
index 0000000..ce8e1e4
--- /dev/null
+++ b/vendor/golang.org/x/sys/plan9/mksyscall.pl
@@ -0,0 +1,319 @@
+#!/usr/bin/env perl
+# Copyright 2009 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+# This program reads a file containing function prototypes
+# (like syscall_plan9.go) and generates system call bodies.
+# The prototypes are marked by lines beginning with "//sys"
+# and read like func declarations if //sys is replaced by func, but:
+# * The parameter lists must give a name for each argument.
+# This includes return parameters.
+# * The parameter lists must give a type for each argument:
+# the (x, y, z int) shorthand is not allowed.
+# * If the return parameter is an error number, it must be named errno.
+
+# A line beginning with //sysnb is like //sys, except that the
+# goroutine will not be suspended during the execution of the system
+# call. This must only be used for system calls which can never
+# block, as otherwise the system call could cause all goroutines to
+# hang.
+
+use strict;
+
+my $cmdline = "mksyscall.pl " . join(' ', @ARGV);
+my $errors = 0;
+my $_32bit = "";
+my $plan9 = 0;
+my $openbsd = 0;
+my $netbsd = 0;
+my $dragonfly = 0;
+my $nacl = 0;
+my $arm = 0; # 64-bit value should use (even, odd)-pair
+
+if($ARGV[0] eq "-b32") {
+ $_32bit = "big-endian";
+ shift;
+} elsif($ARGV[0] eq "-l32") {
+ $_32bit = "little-endian";
+ shift;
+}
+if($ARGV[0] eq "-plan9") {
+ $plan9 = 1;
+ shift;
+}
+if($ARGV[0] eq "-openbsd") {
+ $openbsd = 1;
+ shift;
+}
+if($ARGV[0] eq "-netbsd") {
+ $netbsd = 1;
+ shift;
+}
+if($ARGV[0] eq "-dragonfly") {
+ $dragonfly = 1;
+ shift;
+}
+if($ARGV[0] eq "-nacl") {
+ $nacl = 1;
+ shift;
+}
+if($ARGV[0] eq "-arm") {
+ $arm = 1;
+ shift;
+}
+
+if($ARGV[0] =~ /^-/) {
+ print STDERR "usage: mksyscall.pl [-b32 | -l32] [file ...]\n";
+ exit 1;
+}
+
+sub parseparamlist($) {
+ my ($list) = @_;
+ $list =~ s/^\s*//;
+ $list =~ s/\s*$//;
+ if($list eq "") {
+ return ();
+ }
+ return split(/\s*,\s*/, $list);
+}
+
+sub parseparam($) {
+ my ($p) = @_;
+ if($p !~ /^(\S*) (\S*)$/) {
+ print STDERR "$ARGV:$.: malformed parameter: $p\n";
+ $errors = 1;
+ return ("xx", "int");
+ }
+ return ($1, $2);
+}
+
+my $text = "";
+while(<>) {
+ chomp;
+ s/\s+/ /g;
+ s/^\s+//;
+ s/\s+$//;
+ my $nonblock = /^\/\/sysnb /;
+ next if !/^\/\/sys / && !$nonblock;
+
+ # Line must be of the form
+ # func Open(path string, mode int, perm int) (fd int, errno error)
+ # Split into name, in params, out params.
+ if(!/^\/\/sys(nb)? (\w+)\(([^()]*)\)\s*(?:\(([^()]+)\))?\s*(?:=\s*((?i)SYS_[A-Z0-9_]+))?$/) {
+ print STDERR "$ARGV:$.: malformed //sys declaration\n";
+ $errors = 1;
+ next;
+ }
+ my ($func, $in, $out, $sysname) = ($2, $3, $4, $5);
+
+ # Split argument lists on comma.
+ my @in = parseparamlist($in);
+ my @out = parseparamlist($out);
+
+ # Try in vain to keep people from editing this file.
+ # The theory is that they jump into the middle of the file
+ # without reading the header.
+ $text .= "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n";
+
+ # Go function header.
+ my $out_decl = @out ? sprintf(" (%s)", join(', ', @out)) : "";
+ $text .= sprintf "func %s(%s)%s {\n", $func, join(', ', @in), $out_decl;
+
+ # Check if err return available
+ my $errvar = "";
+ foreach my $p (@out) {
+ my ($name, $type) = parseparam($p);
+ if($type eq "error") {
+ $errvar = $name;
+ last;
+ }
+ }
+
+ # Prepare arguments to Syscall.
+ my @args = ();
+ my @uses = ();
+ my $n = 0;
+ foreach my $p (@in) {
+ my ($name, $type) = parseparam($p);
+ if($type =~ /^\*/) {
+ push @args, "uintptr(unsafe.Pointer($name))";
+ } elsif($type eq "string" && $errvar ne "") {
+ $text .= "\tvar _p$n *byte\n";
+ $text .= "\t_p$n, $errvar = BytePtrFromString($name)\n";
+ $text .= "\tif $errvar != nil {\n\t\treturn\n\t}\n";
+ push @args, "uintptr(unsafe.Pointer(_p$n))";
+ push @uses, "use(unsafe.Pointer(_p$n))";
+ $n++;
+ } elsif($type eq "string") {
+ print STDERR "$ARGV:$.: $func uses string arguments, but has no error return\n";
+ $text .= "\tvar _p$n *byte\n";
+ $text .= "\t_p$n, _ = BytePtrFromString($name)\n";
+ push @args, "uintptr(unsafe.Pointer(_p$n))";
+ push @uses, "use(unsafe.Pointer(_p$n))";
+ $n++;
+ } elsif($type =~ /^\[\](.*)/) {
+ # Convert slice into pointer, length.
+ # Have to be careful not to take address of &a[0] if len == 0:
+ # pass dummy pointer in that case.
+ # Used to pass nil, but some OSes or simulators reject write(fd, nil, 0).
+ $text .= "\tvar _p$n unsafe.Pointer\n";
+ $text .= "\tif len($name) > 0 {\n\t\t_p$n = unsafe.Pointer(\&${name}[0])\n\t}";
+ $text .= " else {\n\t\t_p$n = unsafe.Pointer(&_zero)\n\t}";
+ $text .= "\n";
+ push @args, "uintptr(_p$n)", "uintptr(len($name))";
+ $n++;
+ } elsif($type eq "int64" && ($openbsd || $netbsd)) {
+ push @args, "0";
+ if($_32bit eq "big-endian") {
+ push @args, "uintptr($name>>32)", "uintptr($name)";
+ } elsif($_32bit eq "little-endian") {
+ push @args, "uintptr($name)", "uintptr($name>>32)";
+ } else {
+ push @args, "uintptr($name)";
+ }
+ } elsif($type eq "int64" && $dragonfly) {
+ if ($func !~ /^extp(read|write)/i) {
+ push @args, "0";
+ }
+ if($_32bit eq "big-endian") {
+ push @args, "uintptr($name>>32)", "uintptr($name)";
+ } elsif($_32bit eq "little-endian") {
+ push @args, "uintptr($name)", "uintptr($name>>32)";
+ } else {
+ push @args, "uintptr($name)";
+ }
+ } elsif($type eq "int64" && $_32bit ne "") {
+ if(@args % 2 && $arm) {
+ # arm abi specifies 64-bit argument uses
+ # (even, odd) pair
+ push @args, "0"
+ }
+ if($_32bit eq "big-endian") {
+ push @args, "uintptr($name>>32)", "uintptr($name)";
+ } else {
+ push @args, "uintptr($name)", "uintptr($name>>32)";
+ }
+ } else {
+ push @args, "uintptr($name)";
+ }
+ }
+
+ # Determine which form to use; pad args with zeros.
+ my $asm = "Syscall";
+ if ($nonblock) {
+ $asm = "RawSyscall";
+ }
+ if(@args <= 3) {
+ while(@args < 3) {
+ push @args, "0";
+ }
+ } elsif(@args <= 6) {
+ $asm .= "6";
+ while(@args < 6) {
+ push @args, "0";
+ }
+ } elsif(@args <= 9) {
+ $asm .= "9";
+ while(@args < 9) {
+ push @args, "0";
+ }
+ } else {
+ print STDERR "$ARGV:$.: too many arguments to system call\n";
+ }
+
+ # System call number.
+ if($sysname eq "") {
+ $sysname = "SYS_$func";
+ $sysname =~ s/([a-z])([A-Z])/${1}_$2/g; # turn FooBar into Foo_Bar
+ $sysname =~ y/a-z/A-Z/;
+ if($nacl) {
+ $sysname =~ y/A-Z/a-z/;
+ }
+ }
+
+ # Actual call.
+ my $args = join(', ', @args);
+ my $call = "$asm($sysname, $args)";
+
+ # Assign return values.
+ my $body = "";
+ my @ret = ("_", "_", "_");
+ my $do_errno = 0;
+ for(my $i=0; $i<@out; $i++) {
+ my $p = $out[$i];
+ my ($name, $type) = parseparam($p);
+ my $reg = "";
+ if($name eq "err" && !$plan9) {
+ $reg = "e1";
+ $ret[2] = $reg;
+ $do_errno = 1;
+ } elsif($name eq "err" && $plan9) {
+ $ret[0] = "r0";
+ $ret[2] = "e1";
+ next;
+ } else {
+ $reg = sprintf("r%d", $i);
+ $ret[$i] = $reg;
+ }
+ if($type eq "bool") {
+ $reg = "$reg != 0";
+ }
+ if($type eq "int64" && $_32bit ne "") {
+ # 64-bit number in r1:r0 or r0:r1.
+ if($i+2 > @out) {
+ print STDERR "$ARGV:$.: not enough registers for int64 return\n";
+ }
+ if($_32bit eq "big-endian") {
+ $reg = sprintf("int64(r%d)<<32 | int64(r%d)", $i, $i+1);
+ } else {
+ $reg = sprintf("int64(r%d)<<32 | int64(r%d)", $i+1, $i);
+ }
+ $ret[$i] = sprintf("r%d", $i);
+ $ret[$i+1] = sprintf("r%d", $i+1);
+ }
+ if($reg ne "e1" || $plan9) {
+ $body .= "\t$name = $type($reg)\n";
+ }
+ }
+ if ($ret[0] eq "_" && $ret[1] eq "_" && $ret[2] eq "_") {
+ $text .= "\t$call\n";
+ } else {
+ $text .= "\t$ret[0], $ret[1], $ret[2] := $call\n";
+ }
+ foreach my $use (@uses) {
+ $text .= "\t$use\n";
+ }
+ $text .= $body;
+
+ if ($plan9 && $ret[2] eq "e1") {
+ $text .= "\tif int32(r0) == -1 {\n";
+ $text .= "\t\terr = e1\n";
+ $text .= "\t}\n";
+ } elsif ($do_errno) {
+ $text .= "\tif e1 != 0 {\n";
+ $text .= "\t\terr = e1\n";
+ $text .= "\t}\n";
+ }
+ $text .= "\treturn\n";
+ $text .= "}\n\n";
+}
+
+chomp $text;
+chomp $text;
+
+if($errors) {
+ exit 1;
+}
+
+print <= 10 {
+ buf[i] = byte(val%10 + '0')
+ i--
+ val /= 10
+ }
+ buf[i] = byte(val + '0')
+ return string(buf[i:])
+}
diff --git a/vendor/golang.org/x/sys/plan9/syscall.go b/vendor/golang.org/x/sys/plan9/syscall.go
new file mode 100644
index 0000000..df6f8c5
--- /dev/null
+++ b/vendor/golang.org/x/sys/plan9/syscall.go
@@ -0,0 +1,74 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build plan9
+
+// Package plan9 contains an interface to the low-level operating system
+// primitives. OS details vary depending on the underlying system, and
+// by default, godoc will display the OS-specific documentation for the current
+// system. If you want godoc to display documentation for another
+// system, set $GOOS and $GOARCH to the desired system. For example, if
+// you want to view documentation for freebsd/arm on linux/amd64, set $GOOS
+// to freebsd and $GOARCH to arm.
+// The primary use of this package is inside other packages that provide a more
+// portable interface to the system, such as "os", "time" and "net". Use
+// those packages rather than this one if you can.
+// For details of the functions and data types in this package consult
+// the manuals for the appropriate operating system.
+// These calls return err == nil to indicate success; otherwise
+// err represents an operating system error describing the failure and
+// holds a value of type syscall.ErrorString.
+package plan9 // import "golang.org/x/sys/plan9"
+
+import "unsafe"
+
+// ByteSliceFromString returns a NUL-terminated slice of bytes
+// containing the text of s. If s contains a NUL byte at any
+// location, it returns (nil, EINVAL).
+func ByteSliceFromString(s string) ([]byte, error) {
+ for i := 0; i < len(s); i++ {
+ if s[i] == 0 {
+ return nil, EINVAL
+ }
+ }
+ a := make([]byte, len(s)+1)
+ copy(a, s)
+ return a, nil
+}
+
+// BytePtrFromString returns a pointer to a NUL-terminated array of
+// bytes containing the text of s. If s contains a NUL byte at any
+// location, it returns (nil, EINVAL).
+func BytePtrFromString(s string) (*byte, error) {
+ a, err := ByteSliceFromString(s)
+ if err != nil {
+ return nil, err
+ }
+ return &a[0], nil
+}
+
+// Single-word zero for use when we need a valid pointer to 0 bytes.
+// See mksyscall.pl.
+var _zero uintptr
+
+func (ts *Timespec) Unix() (sec int64, nsec int64) {
+ return int64(ts.Sec), int64(ts.Nsec)
+}
+
+func (tv *Timeval) Unix() (sec int64, nsec int64) {
+ return int64(tv.Sec), int64(tv.Usec) * 1000
+}
+
+func (ts *Timespec) Nano() int64 {
+ return int64(ts.Sec)*1e9 + int64(ts.Nsec)
+}
+
+func (tv *Timeval) Nano() int64 {
+ return int64(tv.Sec)*1e9 + int64(tv.Usec)*1000
+}
+
+// use is a no-op, but the compiler cannot see that it is.
+// Calling use(p) ensures that p is kept live until that point.
+//go:noescape
+func use(p unsafe.Pointer)
diff --git a/vendor/golang.org/x/sys/plan9/syscall_plan9.go b/vendor/golang.org/x/sys/plan9/syscall_plan9.go
new file mode 100644
index 0000000..d39d07d
--- /dev/null
+++ b/vendor/golang.org/x/sys/plan9/syscall_plan9.go
@@ -0,0 +1,349 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Plan 9 system calls.
+// This file is compiled as ordinary Go code,
+// but it is also input to mksyscall,
+// which parses the //sys lines and generates system call stubs.
+// Note that sometimes we use a lowercase //sys name and
+// wrap it in our own nicer implementation.
+
+package plan9
+
+import (
+ "syscall"
+ "unsafe"
+)
+
+// A Note is a string describing a process note.
+// It implements the os.Signal interface.
+type Note string
+
+func (n Note) Signal() {}
+
+func (n Note) String() string {
+ return string(n)
+}
+
+var (
+ Stdin = 0
+ Stdout = 1
+ Stderr = 2
+)
+
+// For testing: clients can set this flag to force
+// creation of IPv6 sockets to return EAFNOSUPPORT.
+var SocketDisableIPv6 bool
+
+func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.ErrorString)
+func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err syscall.ErrorString)
+func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr)
+func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr)
+
+func atoi(b []byte) (n uint) {
+ n = 0
+ for i := 0; i < len(b); i++ {
+ n = n*10 + uint(b[i]-'0')
+ }
+ return
+}
+
+func cstring(s []byte) string {
+ for i := range s {
+ if s[i] == 0 {
+ return string(s[0:i])
+ }
+ }
+ return string(s)
+}
+
+func errstr() string {
+ var buf [ERRMAX]byte
+
+ RawSyscall(SYS_ERRSTR, uintptr(unsafe.Pointer(&buf[0])), uintptr(len(buf)), 0)
+
+ buf[len(buf)-1] = 0
+ return cstring(buf[:])
+}
+
+// Implemented in assembly to import from runtime.
+func exit(code int)
+
+func Exit(code int) { exit(code) }
+
+func readnum(path string) (uint, error) {
+ var b [12]byte
+
+ fd, e := Open(path, O_RDONLY)
+ if e != nil {
+ return 0, e
+ }
+ defer Close(fd)
+
+ n, e := Pread(fd, b[:], 0)
+
+ if e != nil {
+ return 0, e
+ }
+
+ m := 0
+ for ; m < n && b[m] == ' '; m++ {
+ }
+
+ return atoi(b[m : n-1]), nil
+}
+
+func Getpid() (pid int) {
+ n, _ := readnum("#c/pid")
+ return int(n)
+}
+
+func Getppid() (ppid int) {
+ n, _ := readnum("#c/ppid")
+ return int(n)
+}
+
+func Read(fd int, p []byte) (n int, err error) {
+ return Pread(fd, p, -1)
+}
+
+func Write(fd int, p []byte) (n int, err error) {
+ return Pwrite(fd, p, -1)
+}
+
+var ioSync int64
+
+//sys fd2path(fd int, buf []byte) (err error)
+func Fd2path(fd int) (path string, err error) {
+ var buf [512]byte
+
+ e := fd2path(fd, buf[:])
+ if e != nil {
+ return "", e
+ }
+ return cstring(buf[:]), nil
+}
+
+//sys pipe(p *[2]int32) (err error)
+func Pipe(p []int) (err error) {
+ if len(p) != 2 {
+ return syscall.ErrorString("bad arg in system call")
+ }
+ var pp [2]int32
+ err = pipe(&pp)
+ p[0] = int(pp[0])
+ p[1] = int(pp[1])
+ return
+}
+
+// Underlying system call writes to newoffset via pointer.
+// Implemented in assembly to avoid allocation.
+func seek(placeholder uintptr, fd int, offset int64, whence int) (newoffset int64, err string)
+
+func Seek(fd int, offset int64, whence int) (newoffset int64, err error) {
+ newoffset, e := seek(0, fd, offset, whence)
+
+ if newoffset == -1 {
+ err = syscall.ErrorString(e)
+ }
+ return
+}
+
+func Mkdir(path string, mode uint32) (err error) {
+ fd, err := Create(path, O_RDONLY, DMDIR|mode)
+
+ if fd != -1 {
+ Close(fd)
+ }
+
+ return
+}
+
+type Waitmsg struct {
+ Pid int
+ Time [3]uint32
+ Msg string
+}
+
+func (w Waitmsg) Exited() bool { return true }
+func (w Waitmsg) Signaled() bool { return false }
+
+func (w Waitmsg) ExitStatus() int {
+ if len(w.Msg) == 0 {
+ // a normal exit returns no message
+ return 0
+ }
+ return 1
+}
+
+//sys await(s []byte) (n int, err error)
+func Await(w *Waitmsg) (err error) {
+ var buf [512]byte
+ var f [5][]byte
+
+ n, err := await(buf[:])
+
+ if err != nil || w == nil {
+ return
+ }
+
+ nf := 0
+ p := 0
+ for i := 0; i < n && nf < len(f)-1; i++ {
+ if buf[i] == ' ' {
+ f[nf] = buf[p:i]
+ p = i + 1
+ nf++
+ }
+ }
+ f[nf] = buf[p:]
+ nf++
+
+ if nf != len(f) {
+ return syscall.ErrorString("invalid wait message")
+ }
+ w.Pid = int(atoi(f[0]))
+ w.Time[0] = uint32(atoi(f[1]))
+ w.Time[1] = uint32(atoi(f[2]))
+ w.Time[2] = uint32(atoi(f[3]))
+ w.Msg = cstring(f[4])
+ if w.Msg == "''" {
+ // await() returns '' for no error
+ w.Msg = ""
+ }
+ return
+}
+
+func Unmount(name, old string) (err error) {
+ fixwd()
+ oldp, err := BytePtrFromString(old)
+ if err != nil {
+ return err
+ }
+ oldptr := uintptr(unsafe.Pointer(oldp))
+
+ var r0 uintptr
+ var e syscall.ErrorString
+
+ // bind(2) man page: If name is zero, everything bound or mounted upon old is unbound or unmounted.
+ if name == "" {
+ r0, _, e = Syscall(SYS_UNMOUNT, _zero, oldptr, 0)
+ } else {
+ namep, err := BytePtrFromString(name)
+ if err != nil {
+ return err
+ }
+ r0, _, e = Syscall(SYS_UNMOUNT, uintptr(unsafe.Pointer(namep)), oldptr, 0)
+ }
+
+ if int32(r0) == -1 {
+ err = e
+ }
+ return
+}
+
+func Fchdir(fd int) (err error) {
+ path, err := Fd2path(fd)
+
+ if err != nil {
+ return
+ }
+
+ return Chdir(path)
+}
+
+type Timespec struct {
+ Sec int32
+ Nsec int32
+}
+
+type Timeval struct {
+ Sec int32
+ Usec int32
+}
+
+func NsecToTimeval(nsec int64) (tv Timeval) {
+ nsec += 999 // round up to microsecond
+ tv.Usec = int32(nsec % 1e9 / 1e3)
+ tv.Sec = int32(nsec / 1e9)
+ return
+}
+
+func nsec() int64 {
+ var scratch int64
+
+ r0, _, _ := Syscall(SYS_NSEC, uintptr(unsafe.Pointer(&scratch)), 0, 0)
+ // TODO(aram): remove hack after I fix _nsec in the pc64 kernel.
+ if r0 == 0 {
+ return scratch
+ }
+ return int64(r0)
+}
+
+func Gettimeofday(tv *Timeval) error {
+ nsec := nsec()
+ *tv = NsecToTimeval(nsec)
+ return nil
+}
+
+func Getpagesize() int { return 0x1000 }
+
+func Getegid() (egid int) { return -1 }
+func Geteuid() (euid int) { return -1 }
+func Getgid() (gid int) { return -1 }
+func Getuid() (uid int) { return -1 }
+
+func Getgroups() (gids []int, err error) {
+ return make([]int, 0), nil
+}
+
+//sys open(path string, mode int) (fd int, err error)
+func Open(path string, mode int) (fd int, err error) {
+ fixwd()
+ return open(path, mode)
+}
+
+//sys create(path string, mode int, perm uint32) (fd int, err error)
+func Create(path string, mode int, perm uint32) (fd int, err error) {
+ fixwd()
+ return create(path, mode, perm)
+}
+
+//sys remove(path string) (err error)
+func Remove(path string) error {
+ fixwd()
+ return remove(path)
+}
+
+//sys stat(path string, edir []byte) (n int, err error)
+func Stat(path string, edir []byte) (n int, err error) {
+ fixwd()
+ return stat(path, edir)
+}
+
+//sys bind(name string, old string, flag int) (err error)
+func Bind(name string, old string, flag int) (err error) {
+ fixwd()
+ return bind(name, old, flag)
+}
+
+//sys mount(fd int, afd int, old string, flag int, aname string) (err error)
+func Mount(fd int, afd int, old string, flag int, aname string) (err error) {
+ fixwd()
+ return mount(fd, afd, old, flag, aname)
+}
+
+//sys wstat(path string, edir []byte) (err error)
+func Wstat(path string, edir []byte) (err error) {
+ fixwd()
+ return wstat(path, edir)
+}
+
+//sys chdir(path string) (err error)
+//sys Dup(oldfd int, newfd int) (fd int, err error)
+//sys Pread(fd int, p []byte, offset int64) (n int, err error)
+//sys Pwrite(fd int, p []byte, offset int64) (n int, err error)
+//sys Close(fd int) (err error)
+//sys Fstat(fd int, edir []byte) (n int, err error)
+//sys Fwstat(fd int, edir []byte) (err error)
diff --git a/vendor/golang.org/x/sys/plan9/syscall_test.go b/vendor/golang.org/x/sys/plan9/syscall_test.go
new file mode 100644
index 0000000..8f829ba
--- /dev/null
+++ b/vendor/golang.org/x/sys/plan9/syscall_test.go
@@ -0,0 +1,33 @@
+// Copyright 2013 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 plan9
+
+package plan9_test
+
+import (
+ "testing"
+
+ "golang.org/x/sys/plan9"
+)
+
+func testSetGetenv(t *testing.T, key, value string) {
+ err := plan9.Setenv(key, value)
+ if err != nil {
+ t.Fatalf("Setenv failed to set %q: %v", value, err)
+ }
+ newvalue, found := plan9.Getenv(key)
+ if !found {
+ t.Fatalf("Getenv failed to find %v variable (want value %q)", key, value)
+ }
+ if newvalue != value {
+ t.Fatalf("Getenv(%v) = %q; want %q", key, newvalue, value)
+ }
+}
+
+func TestEnv(t *testing.T) {
+ testSetGetenv(t, "TESTENV", "AVALUE")
+ // make sure TESTENV gets set to "", not deleted
+ testSetGetenv(t, "TESTENV", "")
+}
diff --git a/vendor/golang.org/x/sys/plan9/zsyscall_plan9_386.go b/vendor/golang.org/x/sys/plan9/zsyscall_plan9_386.go
new file mode 100644
index 0000000..b35598a
--- /dev/null
+++ b/vendor/golang.org/x/sys/plan9/zsyscall_plan9_386.go
@@ -0,0 +1,292 @@
+// mksyscall.pl -l32 -plan9 syscall_plan9.go
+// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
+
+package plan9
+
+import "unsafe"
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func fd2path(fd int, buf []byte) (err error) {
+ var _p0 unsafe.Pointer
+ if len(buf) > 0 {
+ _p0 = unsafe.Pointer(&buf[0])
+ } else {
+ _p0 = unsafe.Pointer(&_zero)
+ }
+ r0, _, e1 := Syscall(SYS_FD2PATH, uintptr(fd), uintptr(_p0), uintptr(len(buf)))
+ if int32(r0) == -1 {
+ err = e1
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func pipe(p *[2]int32) (err error) {
+ r0, _, e1 := Syscall(SYS_PIPE, uintptr(unsafe.Pointer(p)), 0, 0)
+ if int32(r0) == -1 {
+ err = e1
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func await(s []byte) (n int, err error) {
+ var _p0 unsafe.Pointer
+ if len(s) > 0 {
+ _p0 = unsafe.Pointer(&s[0])
+ } else {
+ _p0 = unsafe.Pointer(&_zero)
+ }
+ r0, _, e1 := Syscall(SYS_AWAIT, uintptr(_p0), uintptr(len(s)), 0)
+ n = int(r0)
+ if int32(r0) == -1 {
+ err = e1
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func open(path string, mode int) (fd int, err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
+ use(unsafe.Pointer(_p0))
+ fd = int(r0)
+ if int32(r0) == -1 {
+ err = e1
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func create(path string, mode int, perm uint32) (fd int, err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ r0, _, e1 := Syscall(SYS_CREATE, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm))
+ use(unsafe.Pointer(_p0))
+ fd = int(r0)
+ if int32(r0) == -1 {
+ err = e1
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func remove(path string) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ r0, _, e1 := Syscall(SYS_REMOVE, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
+ if int32(r0) == -1 {
+ err = e1
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func stat(path string, edir []byte) (n int, err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ var _p1 unsafe.Pointer
+ if len(edir) > 0 {
+ _p1 = unsafe.Pointer(&edir[0])
+ } else {
+ _p1 = unsafe.Pointer(&_zero)
+ }
+ r0, _, e1 := Syscall(SYS_STAT, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(edir)))
+ use(unsafe.Pointer(_p0))
+ n = int(r0)
+ if int32(r0) == -1 {
+ err = e1
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func bind(name string, old string, flag int) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(name)
+ if err != nil {
+ return
+ }
+ var _p1 *byte
+ _p1, err = BytePtrFromString(old)
+ if err != nil {
+ return
+ }
+ r0, _, e1 := Syscall(SYS_BIND, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(flag))
+ use(unsafe.Pointer(_p0))
+ use(unsafe.Pointer(_p1))
+ if int32(r0) == -1 {
+ err = e1
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func mount(fd int, afd int, old string, flag int, aname string) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(old)
+ if err != nil {
+ return
+ }
+ var _p1 *byte
+ _p1, err = BytePtrFromString(aname)
+ if err != nil {
+ return
+ }
+ r0, _, e1 := Syscall6(SYS_MOUNT, uintptr(fd), uintptr(afd), uintptr(unsafe.Pointer(_p0)), uintptr(flag), uintptr(unsafe.Pointer(_p1)), 0)
+ use(unsafe.Pointer(_p0))
+ use(unsafe.Pointer(_p1))
+ if int32(r0) == -1 {
+ err = e1
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func wstat(path string, edir []byte) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ var _p1 unsafe.Pointer
+ if len(edir) > 0 {
+ _p1 = unsafe.Pointer(&edir[0])
+ } else {
+ _p1 = unsafe.Pointer(&_zero)
+ }
+ r0, _, e1 := Syscall(SYS_WSTAT, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(edir)))
+ use(unsafe.Pointer(_p0))
+ if int32(r0) == -1 {
+ err = e1
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func chdir(path string) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ r0, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
+ if int32(r0) == -1 {
+ err = e1
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Dup(oldfd int, newfd int) (fd int, err error) {
+ r0, _, e1 := Syscall(SYS_DUP, uintptr(oldfd), uintptr(newfd), 0)
+ fd = int(r0)
+ if int32(r0) == -1 {
+ err = e1
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Pread(fd int, p []byte, offset int64) (n int, err error) {
+ var _p0 unsafe.Pointer
+ if len(p) > 0 {
+ _p0 = unsafe.Pointer(&p[0])
+ } else {
+ _p0 = unsafe.Pointer(&_zero)
+ }
+ r0, _, e1 := Syscall6(SYS_PREAD, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), uintptr(offset>>32), 0)
+ n = int(r0)
+ if int32(r0) == -1 {
+ err = e1
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
+ var _p0 unsafe.Pointer
+ if len(p) > 0 {
+ _p0 = unsafe.Pointer(&p[0])
+ } else {
+ _p0 = unsafe.Pointer(&_zero)
+ }
+ r0, _, e1 := Syscall6(SYS_PWRITE, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), uintptr(offset>>32), 0)
+ n = int(r0)
+ if int32(r0) == -1 {
+ err = e1
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Close(fd int) (err error) {
+ r0, _, e1 := Syscall(SYS_CLOSE, uintptr(fd), 0, 0)
+ if int32(r0) == -1 {
+ err = e1
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Fstat(fd int, edir []byte) (n int, err error) {
+ var _p0 unsafe.Pointer
+ if len(edir) > 0 {
+ _p0 = unsafe.Pointer(&edir[0])
+ } else {
+ _p0 = unsafe.Pointer(&_zero)
+ }
+ r0, _, e1 := Syscall(SYS_FSTAT, uintptr(fd), uintptr(_p0), uintptr(len(edir)))
+ n = int(r0)
+ if int32(r0) == -1 {
+ err = e1
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Fwstat(fd int, edir []byte) (err error) {
+ var _p0 unsafe.Pointer
+ if len(edir) > 0 {
+ _p0 = unsafe.Pointer(&edir[0])
+ } else {
+ _p0 = unsafe.Pointer(&_zero)
+ }
+ r0, _, e1 := Syscall(SYS_FWSTAT, uintptr(fd), uintptr(_p0), uintptr(len(edir)))
+ if int32(r0) == -1 {
+ err = e1
+ }
+ return
+}
diff --git a/vendor/golang.org/x/sys/plan9/zsyscall_plan9_amd64.go b/vendor/golang.org/x/sys/plan9/zsyscall_plan9_amd64.go
new file mode 100644
index 0000000..b35598a
--- /dev/null
+++ b/vendor/golang.org/x/sys/plan9/zsyscall_plan9_amd64.go
@@ -0,0 +1,292 @@
+// mksyscall.pl -l32 -plan9 syscall_plan9.go
+// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
+
+package plan9
+
+import "unsafe"
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func fd2path(fd int, buf []byte) (err error) {
+ var _p0 unsafe.Pointer
+ if len(buf) > 0 {
+ _p0 = unsafe.Pointer(&buf[0])
+ } else {
+ _p0 = unsafe.Pointer(&_zero)
+ }
+ r0, _, e1 := Syscall(SYS_FD2PATH, uintptr(fd), uintptr(_p0), uintptr(len(buf)))
+ if int32(r0) == -1 {
+ err = e1
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func pipe(p *[2]int32) (err error) {
+ r0, _, e1 := Syscall(SYS_PIPE, uintptr(unsafe.Pointer(p)), 0, 0)
+ if int32(r0) == -1 {
+ err = e1
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func await(s []byte) (n int, err error) {
+ var _p0 unsafe.Pointer
+ if len(s) > 0 {
+ _p0 = unsafe.Pointer(&s[0])
+ } else {
+ _p0 = unsafe.Pointer(&_zero)
+ }
+ r0, _, e1 := Syscall(SYS_AWAIT, uintptr(_p0), uintptr(len(s)), 0)
+ n = int(r0)
+ if int32(r0) == -1 {
+ err = e1
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func open(path string, mode int) (fd int, err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
+ use(unsafe.Pointer(_p0))
+ fd = int(r0)
+ if int32(r0) == -1 {
+ err = e1
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func create(path string, mode int, perm uint32) (fd int, err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ r0, _, e1 := Syscall(SYS_CREATE, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm))
+ use(unsafe.Pointer(_p0))
+ fd = int(r0)
+ if int32(r0) == -1 {
+ err = e1
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func remove(path string) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ r0, _, e1 := Syscall(SYS_REMOVE, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
+ if int32(r0) == -1 {
+ err = e1
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func stat(path string, edir []byte) (n int, err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ var _p1 unsafe.Pointer
+ if len(edir) > 0 {
+ _p1 = unsafe.Pointer(&edir[0])
+ } else {
+ _p1 = unsafe.Pointer(&_zero)
+ }
+ r0, _, e1 := Syscall(SYS_STAT, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(edir)))
+ use(unsafe.Pointer(_p0))
+ n = int(r0)
+ if int32(r0) == -1 {
+ err = e1
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func bind(name string, old string, flag int) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(name)
+ if err != nil {
+ return
+ }
+ var _p1 *byte
+ _p1, err = BytePtrFromString(old)
+ if err != nil {
+ return
+ }
+ r0, _, e1 := Syscall(SYS_BIND, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(flag))
+ use(unsafe.Pointer(_p0))
+ use(unsafe.Pointer(_p1))
+ if int32(r0) == -1 {
+ err = e1
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func mount(fd int, afd int, old string, flag int, aname string) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(old)
+ if err != nil {
+ return
+ }
+ var _p1 *byte
+ _p1, err = BytePtrFromString(aname)
+ if err != nil {
+ return
+ }
+ r0, _, e1 := Syscall6(SYS_MOUNT, uintptr(fd), uintptr(afd), uintptr(unsafe.Pointer(_p0)), uintptr(flag), uintptr(unsafe.Pointer(_p1)), 0)
+ use(unsafe.Pointer(_p0))
+ use(unsafe.Pointer(_p1))
+ if int32(r0) == -1 {
+ err = e1
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func wstat(path string, edir []byte) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ var _p1 unsafe.Pointer
+ if len(edir) > 0 {
+ _p1 = unsafe.Pointer(&edir[0])
+ } else {
+ _p1 = unsafe.Pointer(&_zero)
+ }
+ r0, _, e1 := Syscall(SYS_WSTAT, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(edir)))
+ use(unsafe.Pointer(_p0))
+ if int32(r0) == -1 {
+ err = e1
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func chdir(path string) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ r0, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(_p0)), 0, 0)
+ use(unsafe.Pointer(_p0))
+ if int32(r0) == -1 {
+ err = e1
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Dup(oldfd int, newfd int) (fd int, err error) {
+ r0, _, e1 := Syscall(SYS_DUP, uintptr(oldfd), uintptr(newfd), 0)
+ fd = int(r0)
+ if int32(r0) == -1 {
+ err = e1
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Pread(fd int, p []byte, offset int64) (n int, err error) {
+ var _p0 unsafe.Pointer
+ if len(p) > 0 {
+ _p0 = unsafe.Pointer(&p[0])
+ } else {
+ _p0 = unsafe.Pointer(&_zero)
+ }
+ r0, _, e1 := Syscall6(SYS_PREAD, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), uintptr(offset>>32), 0)
+ n = int(r0)
+ if int32(r0) == -1 {
+ err = e1
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
+ var _p0 unsafe.Pointer
+ if len(p) > 0 {
+ _p0 = unsafe.Pointer(&p[0])
+ } else {
+ _p0 = unsafe.Pointer(&_zero)
+ }
+ r0, _, e1 := Syscall6(SYS_PWRITE, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), uintptr(offset>>32), 0)
+ n = int(r0)
+ if int32(r0) == -1 {
+ err = e1
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Close(fd int) (err error) {
+ r0, _, e1 := Syscall(SYS_CLOSE, uintptr(fd), 0, 0)
+ if int32(r0) == -1 {
+ err = e1
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Fstat(fd int, edir []byte) (n int, err error) {
+ var _p0 unsafe.Pointer
+ if len(edir) > 0 {
+ _p0 = unsafe.Pointer(&edir[0])
+ } else {
+ _p0 = unsafe.Pointer(&_zero)
+ }
+ r0, _, e1 := Syscall(SYS_FSTAT, uintptr(fd), uintptr(_p0), uintptr(len(edir)))
+ n = int(r0)
+ if int32(r0) == -1 {
+ err = e1
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Fwstat(fd int, edir []byte) (err error) {
+ var _p0 unsafe.Pointer
+ if len(edir) > 0 {
+ _p0 = unsafe.Pointer(&edir[0])
+ } else {
+ _p0 = unsafe.Pointer(&_zero)
+ }
+ r0, _, e1 := Syscall(SYS_FWSTAT, uintptr(fd), uintptr(_p0), uintptr(len(edir)))
+ if int32(r0) == -1 {
+ err = e1
+ }
+ return
+}
diff --git a/vendor/golang.org/x/sys/plan9/zsysnum_plan9.go b/vendor/golang.org/x/sys/plan9/zsysnum_plan9.go
new file mode 100644
index 0000000..22e8abd
--- /dev/null
+++ b/vendor/golang.org/x/sys/plan9/zsysnum_plan9.go
@@ -0,0 +1,49 @@
+// mksysnum_plan9.sh /opt/plan9/sys/src/libc/9syscall/sys.h
+// MACHINE GENERATED BY THE ABOVE COMMAND; DO NOT EDIT
+
+package plan9
+
+const (
+ SYS_SYSR1 = 0
+ SYS_BIND = 2
+ SYS_CHDIR = 3
+ SYS_CLOSE = 4
+ SYS_DUP = 5
+ SYS_ALARM = 6
+ SYS_EXEC = 7
+ SYS_EXITS = 8
+ SYS_FAUTH = 10
+ SYS_SEGBRK = 12
+ SYS_OPEN = 14
+ SYS_OSEEK = 16
+ SYS_SLEEP = 17
+ SYS_RFORK = 19
+ SYS_PIPE = 21
+ SYS_CREATE = 22
+ SYS_FD2PATH = 23
+ SYS_BRK_ = 24
+ SYS_REMOVE = 25
+ SYS_NOTIFY = 28
+ SYS_NOTED = 29
+ SYS_SEGATTACH = 30
+ SYS_SEGDETACH = 31
+ SYS_SEGFREE = 32
+ SYS_SEGFLUSH = 33
+ SYS_RENDEZVOUS = 34
+ SYS_UNMOUNT = 35
+ SYS_SEMACQUIRE = 37
+ SYS_SEMRELEASE = 38
+ SYS_SEEK = 39
+ SYS_FVERSION = 40
+ SYS_ERRSTR = 41
+ SYS_STAT = 42
+ SYS_FSTAT = 43
+ SYS_WSTAT = 44
+ SYS_FWSTAT = 45
+ SYS_MOUNT = 46
+ SYS_AWAIT = 47
+ SYS_PREAD = 50
+ SYS_PWRITE = 51
+ SYS_TSEMACQUIRE = 52
+ SYS_NSEC = 53
+)
diff --git a/vendor/golang.org/x/sys/unix/.gitignore b/vendor/golang.org/x/sys/unix/.gitignore
new file mode 100644
index 0000000..e482715
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/.gitignore
@@ -0,0 +1 @@
+_obj/
diff --git a/vendor/golang.org/x/sys/unix/README.md b/vendor/golang.org/x/sys/unix/README.md
new file mode 100644
index 0000000..bc6f603
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/README.md
@@ -0,0 +1,173 @@
+# Building `sys/unix`
+
+The sys/unix package provides access to the raw system call interface of the
+underlying operating system. See: https://godoc.org/golang.org/x/sys/unix
+
+Porting Go to a new architecture/OS combination or adding syscalls, types, or
+constants to an existing architecture/OS pair requires some manual effort;
+however, there are tools that automate much of the process.
+
+## Build Systems
+
+There are currently two ways we generate the necessary files. We are currently
+migrating the build system to use containers so the builds are reproducible.
+This is being done on an OS-by-OS basis. Please update this documentation as
+components of the build system change.
+
+### Old Build System (currently for `GOOS != "Linux" || GOARCH == "sparc64"`)
+
+The old build system generates the Go files based on the C header files
+present on your system. This means that files
+for a given GOOS/GOARCH pair must be generated on a system with that OS and
+architecture. This also means that the generated code can differ from system
+to system, based on differences in the header files.
+
+To avoid this, if you are using the old build system, only generate the Go
+files on an installation with unmodified header files. It is also important to
+keep track of which version of the OS the files were generated from (ex.
+Darwin 14 vs Darwin 15). This makes it easier to track the progress of changes
+and have each OS upgrade correspond to a single change.
+
+To build the files for your current OS and architecture, make sure GOOS and
+GOARCH are set correctly and run `mkall.sh`. This will generate the files for
+your specific system. Running `mkall.sh -n` shows the commands that will be run.
+
+Requirements: bash, perl, go
+
+### New Build System (currently for `GOOS == "Linux" && GOARCH != "sparc64"`)
+
+The new build system uses a Docker container to generate the go files directly
+from source checkouts of the kernel and various system libraries. This means
+that on any platform that supports Docker, all the files using the new build
+system can be generated at once, and generated files will not change based on
+what the person running the scripts has installed on their computer.
+
+The OS specific files for the new build system are located in the `${GOOS}`
+directory, and the build is coordinated by the `${GOOS}/mkall.go` program. When
+the kernel or system library updates, modify the Dockerfile at
+`${GOOS}/Dockerfile` to checkout the new release of the source.
+
+To build all the files under the new build system, you must be on an amd64/Linux
+system and have your GOOS and GOARCH set accordingly. Running `mkall.sh` will
+then generate all of the files for all of the GOOS/GOARCH pairs in the new build
+system. Running `mkall.sh -n` shows the commands that will be run.
+
+Requirements: bash, perl, go, docker
+
+## Component files
+
+This section describes the various files used in the code generation process.
+It also contains instructions on how to modify these files to add a new
+architecture/OS or to add additional syscalls, types, or constants. Note that
+if you are using the new build system, the scripts cannot be called normally.
+They must be called from within the docker container.
+
+### asm files
+
+The hand-written assembly file at `asm_${GOOS}_${GOARCH}.s` implements system
+call dispatch. There are three entry points:
+```
+ func Syscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr)
+ func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr)
+ func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr)
+```
+The first and second are the standard ones; they differ only in how many
+arguments can be passed to the kernel. The third is for low-level use by the
+ForkExec wrapper. Unlike the first two, it does not call into the scheduler to
+let it know that a system call is running.
+
+When porting Go to an new architecture/OS, this file must be implemented for
+each GOOS/GOARCH pair.
+
+### mksysnum
+
+Mksysnum is a script located at `${GOOS}/mksysnum.pl` (or `mksysnum_${GOOS}.pl`
+for the old system). This script takes in a list of header files containing the
+syscall number declarations and parses them to produce the corresponding list of
+Go numeric constants. See `zsysnum_${GOOS}_${GOARCH}.go` for the generated
+constants.
+
+Adding new syscall numbers is mostly done by running the build on a sufficiently
+new installation of the target OS (or updating the source checkouts for the
+new build system). However, depending on the OS, you make need to update the
+parsing in mksysnum.
+
+### mksyscall.pl
+
+The `syscall.go`, `syscall_${GOOS}.go`, `syscall_${GOOS}_${GOARCH}.go` are
+hand-written Go files which implement system calls (for unix, the specific OS,
+or the specific OS/Architecture pair respectively) that need special handling
+and list `//sys` comments giving prototypes for ones that can be generated.
+
+The mksyscall.pl script takes the `//sys` and `//sysnb` comments and converts
+them into syscalls. This requires the name of the prototype in the comment to
+match a syscall number in the `zsysnum_${GOOS}_${GOARCH}.go` file. The function
+prototype can be exported (capitalized) or not.
+
+Adding a new syscall often just requires adding a new `//sys` function prototype
+with the desired arguments and a capitalized name so it is exported. However, if
+you want the interface to the syscall to be different, often one will make an
+unexported `//sys` prototype, an then write a custom wrapper in
+`syscall_${GOOS}.go`.
+
+### types files
+
+For each OS, there is a hand-written Go file at `${GOOS}/types.go` (or
+`types_${GOOS}.go` on the old system). This file includes standard C headers and
+creates Go type aliases to the corresponding C types. The file is then fed
+through godef to get the Go compatible definitions. Finally, the generated code
+is fed though mkpost.go to format the code correctly and remove any hidden or
+private identifiers. This cleaned-up code is written to
+`ztypes_${GOOS}_${GOARCH}.go`.
+
+The hardest part about preparing this file is figuring out which headers to
+include and which symbols need to be `#define`d to get the actual data
+structures that pass through to the kernel system calls. Some C libraries
+preset alternate versions for binary compatibility and translate them on the
+way in and out of system calls, but there is almost always a `#define` that can
+get the real ones.
+See `types_darwin.go` and `linux/types.go` for examples.
+
+To add a new type, add in the necessary include statement at the top of the
+file (if it is not already there) and add in a type alias line. Note that if
+your type is significantly different on different architectures, you may need
+some `#if/#elif` macros in your include statements.
+
+### mkerrors.sh
+
+This script is used to generate the system's various constants. This doesn't
+just include the error numbers and error strings, but also the signal numbers
+an a wide variety of miscellaneous constants. The constants come from the list
+of include files in the `includes_${uname}` variable. A regex then picks out
+the desired `#define` statements, and generates the corresponding Go constants.
+The error numbers and strings are generated from `#include `, and the
+signal numbers and strings are generated from `#include `. All of
+these constants are written to `zerrors_${GOOS}_${GOARCH}.go` via a C program,
+`_errors.c`, which prints out all the constants.
+
+To add a constant, add the header that includes it to the appropriate variable.
+Then, edit the regex (if necessary) to match the desired constant. Avoid making
+the regex too broad to avoid matching unintended constants.
+
+
+## Generated files
+
+### `zerror_${GOOS}_${GOARCH}.go`
+
+A file containing all of the system's generated error numbers, error strings,
+signal numbers, and constants. Generated by `mkerrors.sh` (see above).
+
+### `zsyscall_${GOOS}_${GOARCH}.go`
+
+A file containing all the generated syscalls for a specific GOOS and GOARCH.
+Generated by `mksyscall.pl` (see above).
+
+### `zsysnum_${GOOS}_${GOARCH}.go`
+
+A list of numeric constants for all the syscall number of the specific GOOS
+and GOARCH. Generated by mksysnum (see above).
+
+### `ztypes_${GOOS}_${GOARCH}.go`
+
+A file containing Go types for passing into (or returning from) syscalls.
+Generated by godefs and the types file (see above).
diff --git a/vendor/golang.org/x/sys/unix/asm_darwin_386.s b/vendor/golang.org/x/sys/unix/asm_darwin_386.s
new file mode 100644
index 0000000..8a72783
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/asm_darwin_386.s
@@ -0,0 +1,29 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !gccgo
+
+#include "textflag.h"
+
+//
+// System call support for 386, Darwin
+//
+
+// Just jump to package syscall's implementation for all these functions.
+// The runtime may know about them.
+
+TEXT ·Syscall(SB),NOSPLIT,$0-28
+ JMP syscall·Syscall(SB)
+
+TEXT ·Syscall6(SB),NOSPLIT,$0-40
+ JMP syscall·Syscall6(SB)
+
+TEXT ·Syscall9(SB),NOSPLIT,$0-52
+ JMP syscall·Syscall9(SB)
+
+TEXT ·RawSyscall(SB),NOSPLIT,$0-28
+ JMP syscall·RawSyscall(SB)
+
+TEXT ·RawSyscall6(SB),NOSPLIT,$0-40
+ JMP syscall·RawSyscall6(SB)
diff --git a/vendor/golang.org/x/sys/unix/asm_darwin_amd64.s b/vendor/golang.org/x/sys/unix/asm_darwin_amd64.s
new file mode 100644
index 0000000..6321421
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/asm_darwin_amd64.s
@@ -0,0 +1,29 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !gccgo
+
+#include "textflag.h"
+
+//
+// System call support for AMD64, Darwin
+//
+
+// Just jump to package syscall's implementation for all these functions.
+// The runtime may know about them.
+
+TEXT ·Syscall(SB),NOSPLIT,$0-56
+ JMP syscall·Syscall(SB)
+
+TEXT ·Syscall6(SB),NOSPLIT,$0-80
+ JMP syscall·Syscall6(SB)
+
+TEXT ·Syscall9(SB),NOSPLIT,$0-104
+ JMP syscall·Syscall9(SB)
+
+TEXT ·RawSyscall(SB),NOSPLIT,$0-56
+ JMP syscall·RawSyscall(SB)
+
+TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
+ JMP syscall·RawSyscall6(SB)
diff --git a/vendor/golang.org/x/sys/unix/asm_darwin_arm.s b/vendor/golang.org/x/sys/unix/asm_darwin_arm.s
new file mode 100644
index 0000000..333242d
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/asm_darwin_arm.s
@@ -0,0 +1,30 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !gccgo
+// +build arm,darwin
+
+#include "textflag.h"
+
+//
+// System call support for ARM, Darwin
+//
+
+// Just jump to package syscall's implementation for all these functions.
+// The runtime may know about them.
+
+TEXT ·Syscall(SB),NOSPLIT,$0-28
+ B syscall·Syscall(SB)
+
+TEXT ·Syscall6(SB),NOSPLIT,$0-40
+ B syscall·Syscall6(SB)
+
+TEXT ·Syscall9(SB),NOSPLIT,$0-52
+ B syscall·Syscall9(SB)
+
+TEXT ·RawSyscall(SB),NOSPLIT,$0-28
+ B syscall·RawSyscall(SB)
+
+TEXT ·RawSyscall6(SB),NOSPLIT,$0-40
+ B syscall·RawSyscall6(SB)
diff --git a/vendor/golang.org/x/sys/unix/asm_darwin_arm64.s b/vendor/golang.org/x/sys/unix/asm_darwin_arm64.s
new file mode 100644
index 0000000..97e0174
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/asm_darwin_arm64.s
@@ -0,0 +1,30 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !gccgo
+// +build arm64,darwin
+
+#include "textflag.h"
+
+//
+// System call support for AMD64, Darwin
+//
+
+// Just jump to package syscall's implementation for all these functions.
+// The runtime may know about them.
+
+TEXT ·Syscall(SB),NOSPLIT,$0-56
+ B syscall·Syscall(SB)
+
+TEXT ·Syscall6(SB),NOSPLIT,$0-80
+ B syscall·Syscall6(SB)
+
+TEXT ·Syscall9(SB),NOSPLIT,$0-104
+ B syscall·Syscall9(SB)
+
+TEXT ·RawSyscall(SB),NOSPLIT,$0-56
+ B syscall·RawSyscall(SB)
+
+TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
+ B syscall·RawSyscall6(SB)
diff --git a/vendor/golang.org/x/sys/unix/asm_dragonfly_amd64.s b/vendor/golang.org/x/sys/unix/asm_dragonfly_amd64.s
new file mode 100644
index 0000000..d5ed672
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/asm_dragonfly_amd64.s
@@ -0,0 +1,29 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !gccgo
+
+#include "textflag.h"
+
+//
+// System call support for AMD64, DragonFly
+//
+
+// Just jump to package syscall's implementation for all these functions.
+// The runtime may know about them.
+
+TEXT ·Syscall(SB),NOSPLIT,$0-64
+ JMP syscall·Syscall(SB)
+
+TEXT ·Syscall6(SB),NOSPLIT,$0-88
+ JMP syscall·Syscall6(SB)
+
+TEXT ·Syscall9(SB),NOSPLIT,$0-112
+ JMP syscall·Syscall9(SB)
+
+TEXT ·RawSyscall(SB),NOSPLIT,$0-64
+ JMP syscall·RawSyscall(SB)
+
+TEXT ·RawSyscall6(SB),NOSPLIT,$0-88
+ JMP syscall·RawSyscall6(SB)
diff --git a/vendor/golang.org/x/sys/unix/asm_freebsd_386.s b/vendor/golang.org/x/sys/unix/asm_freebsd_386.s
new file mode 100644
index 0000000..c9a0a26
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/asm_freebsd_386.s
@@ -0,0 +1,29 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !gccgo
+
+#include "textflag.h"
+
+//
+// System call support for 386, FreeBSD
+//
+
+// Just jump to package syscall's implementation for all these functions.
+// The runtime may know about them.
+
+TEXT ·Syscall(SB),NOSPLIT,$0-28
+ JMP syscall·Syscall(SB)
+
+TEXT ·Syscall6(SB),NOSPLIT,$0-40
+ JMP syscall·Syscall6(SB)
+
+TEXT ·Syscall9(SB),NOSPLIT,$0-52
+ JMP syscall·Syscall9(SB)
+
+TEXT ·RawSyscall(SB),NOSPLIT,$0-28
+ JMP syscall·RawSyscall(SB)
+
+TEXT ·RawSyscall6(SB),NOSPLIT,$0-40
+ JMP syscall·RawSyscall6(SB)
diff --git a/vendor/golang.org/x/sys/unix/asm_freebsd_amd64.s b/vendor/golang.org/x/sys/unix/asm_freebsd_amd64.s
new file mode 100644
index 0000000..3517247
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/asm_freebsd_amd64.s
@@ -0,0 +1,29 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !gccgo
+
+#include "textflag.h"
+
+//
+// System call support for AMD64, FreeBSD
+//
+
+// Just jump to package syscall's implementation for all these functions.
+// The runtime may know about them.
+
+TEXT ·Syscall(SB),NOSPLIT,$0-56
+ JMP syscall·Syscall(SB)
+
+TEXT ·Syscall6(SB),NOSPLIT,$0-80
+ JMP syscall·Syscall6(SB)
+
+TEXT ·Syscall9(SB),NOSPLIT,$0-104
+ JMP syscall·Syscall9(SB)
+
+TEXT ·RawSyscall(SB),NOSPLIT,$0-56
+ JMP syscall·RawSyscall(SB)
+
+TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
+ JMP syscall·RawSyscall6(SB)
diff --git a/vendor/golang.org/x/sys/unix/asm_freebsd_arm.s b/vendor/golang.org/x/sys/unix/asm_freebsd_arm.s
new file mode 100644
index 0000000..9227c87
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/asm_freebsd_arm.s
@@ -0,0 +1,29 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !gccgo
+
+#include "textflag.h"
+
+//
+// System call support for ARM, FreeBSD
+//
+
+// Just jump to package syscall's implementation for all these functions.
+// The runtime may know about them.
+
+TEXT ·Syscall(SB),NOSPLIT,$0-28
+ B syscall·Syscall(SB)
+
+TEXT ·Syscall6(SB),NOSPLIT,$0-40
+ B syscall·Syscall6(SB)
+
+TEXT ·Syscall9(SB),NOSPLIT,$0-52
+ B syscall·Syscall9(SB)
+
+TEXT ·RawSyscall(SB),NOSPLIT,$0-28
+ B syscall·RawSyscall(SB)
+
+TEXT ·RawSyscall6(SB),NOSPLIT,$0-40
+ B syscall·RawSyscall6(SB)
diff --git a/vendor/golang.org/x/sys/unix/asm_linux_386.s b/vendor/golang.org/x/sys/unix/asm_linux_386.s
new file mode 100644
index 0000000..4db2909
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/asm_linux_386.s
@@ -0,0 +1,35 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !gccgo
+
+#include "textflag.h"
+
+//
+// System calls for 386, Linux
+//
+
+// Just jump to package syscall's implementation for all these functions.
+// The runtime may know about them.
+
+TEXT ·Syscall(SB),NOSPLIT,$0-28
+ JMP syscall·Syscall(SB)
+
+TEXT ·Syscall6(SB),NOSPLIT,$0-40
+ JMP syscall·Syscall6(SB)
+
+TEXT ·RawSyscall(SB),NOSPLIT,$0-28
+ JMP syscall·RawSyscall(SB)
+
+TEXT ·RawSyscall6(SB),NOSPLIT,$0-40
+ JMP syscall·RawSyscall6(SB)
+
+TEXT ·socketcall(SB),NOSPLIT,$0-36
+ JMP syscall·socketcall(SB)
+
+TEXT ·rawsocketcall(SB),NOSPLIT,$0-36
+ JMP syscall·rawsocketcall(SB)
+
+TEXT ·seek(SB),NOSPLIT,$0-28
+ JMP syscall·seek(SB)
diff --git a/vendor/golang.org/x/sys/unix/asm_linux_amd64.s b/vendor/golang.org/x/sys/unix/asm_linux_amd64.s
new file mode 100644
index 0000000..44e25c6
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/asm_linux_amd64.s
@@ -0,0 +1,29 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !gccgo
+
+#include "textflag.h"
+
+//
+// System calls for AMD64, Linux
+//
+
+// Just jump to package syscall's implementation for all these functions.
+// The runtime may know about them.
+
+TEXT ·Syscall(SB),NOSPLIT,$0-56
+ JMP syscall·Syscall(SB)
+
+TEXT ·Syscall6(SB),NOSPLIT,$0-80
+ JMP syscall·Syscall6(SB)
+
+TEXT ·RawSyscall(SB),NOSPLIT,$0-56
+ JMP syscall·RawSyscall(SB)
+
+TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
+ JMP syscall·RawSyscall6(SB)
+
+TEXT ·gettimeofday(SB),NOSPLIT,$0-16
+ JMP syscall·gettimeofday(SB)
diff --git a/vendor/golang.org/x/sys/unix/asm_linux_arm.s b/vendor/golang.org/x/sys/unix/asm_linux_arm.s
new file mode 100644
index 0000000..cf0b574
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/asm_linux_arm.s
@@ -0,0 +1,29 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !gccgo
+
+#include "textflag.h"
+
+//
+// System calls for arm, Linux
+//
+
+// Just jump to package syscall's implementation for all these functions.
+// The runtime may know about them.
+
+TEXT ·Syscall(SB),NOSPLIT,$0-28
+ B syscall·Syscall(SB)
+
+TEXT ·Syscall6(SB),NOSPLIT,$0-40
+ B syscall·Syscall6(SB)
+
+TEXT ·RawSyscall(SB),NOSPLIT,$0-28
+ B syscall·RawSyscall(SB)
+
+TEXT ·RawSyscall6(SB),NOSPLIT,$0-40
+ B syscall·RawSyscall6(SB)
+
+TEXT ·seek(SB),NOSPLIT,$0-32
+ B syscall·seek(SB)
diff --git a/vendor/golang.org/x/sys/unix/asm_linux_arm64.s b/vendor/golang.org/x/sys/unix/asm_linux_arm64.s
new file mode 100644
index 0000000..4be9bfe
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/asm_linux_arm64.s
@@ -0,0 +1,24 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build linux
+// +build arm64
+// +build !gccgo
+
+#include "textflag.h"
+
+// Just jump to package syscall's implementation for all these functions.
+// The runtime may know about them.
+
+TEXT ·Syscall(SB),NOSPLIT,$0-56
+ B syscall·Syscall(SB)
+
+TEXT ·Syscall6(SB),NOSPLIT,$0-80
+ B syscall·Syscall6(SB)
+
+TEXT ·RawSyscall(SB),NOSPLIT,$0-56
+ B syscall·RawSyscall(SB)
+
+TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
+ B syscall·RawSyscall6(SB)
diff --git a/vendor/golang.org/x/sys/unix/asm_linux_mips64x.s b/vendor/golang.org/x/sys/unix/asm_linux_mips64x.s
new file mode 100644
index 0000000..724e580
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/asm_linux_mips64x.s
@@ -0,0 +1,28 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build linux
+// +build mips64 mips64le
+// +build !gccgo
+
+#include "textflag.h"
+
+//
+// System calls for mips64, Linux
+//
+
+// Just jump to package syscall's implementation for all these functions.
+// The runtime may know about them.
+
+TEXT ·Syscall(SB),NOSPLIT,$0-56
+ JMP syscall·Syscall(SB)
+
+TEXT ·Syscall6(SB),NOSPLIT,$0-80
+ JMP syscall·Syscall6(SB)
+
+TEXT ·RawSyscall(SB),NOSPLIT,$0-56
+ JMP syscall·RawSyscall(SB)
+
+TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
+ JMP syscall·RawSyscall6(SB)
diff --git a/vendor/golang.org/x/sys/unix/asm_linux_mipsx.s b/vendor/golang.org/x/sys/unix/asm_linux_mipsx.s
new file mode 100644
index 0000000..2ea4257
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/asm_linux_mipsx.s
@@ -0,0 +1,31 @@
+// Copyright 2016 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 linux
+// +build mips mipsle
+// +build !gccgo
+
+#include "textflag.h"
+
+//
+// System calls for mips, Linux
+//
+
+// Just jump to package syscall's implementation for all these functions.
+// The runtime may know about them.
+
+TEXT ·Syscall(SB),NOSPLIT,$0-28
+ JMP syscall·Syscall(SB)
+
+TEXT ·Syscall6(SB),NOSPLIT,$0-40
+ JMP syscall·Syscall6(SB)
+
+TEXT ·Syscall9(SB),NOSPLIT,$0-52
+ JMP syscall·Syscall9(SB)
+
+TEXT ·RawSyscall(SB),NOSPLIT,$0-28
+ JMP syscall·RawSyscall(SB)
+
+TEXT ·RawSyscall6(SB),NOSPLIT,$0-40
+ JMP syscall·RawSyscall6(SB)
diff --git a/vendor/golang.org/x/sys/unix/asm_linux_ppc64x.s b/vendor/golang.org/x/sys/unix/asm_linux_ppc64x.s
new file mode 100644
index 0000000..8d231fe
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/asm_linux_ppc64x.s
@@ -0,0 +1,28 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build linux
+// +build ppc64 ppc64le
+// +build !gccgo
+
+#include "textflag.h"
+
+//
+// System calls for ppc64, Linux
+//
+
+// Just jump to package syscall's implementation for all these functions.
+// The runtime may know about them.
+
+TEXT ·Syscall(SB),NOSPLIT,$0-56
+ BR syscall·Syscall(SB)
+
+TEXT ·Syscall6(SB),NOSPLIT,$0-80
+ BR syscall·Syscall6(SB)
+
+TEXT ·RawSyscall(SB),NOSPLIT,$0-56
+ BR syscall·RawSyscall(SB)
+
+TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
+ BR syscall·RawSyscall6(SB)
diff --git a/vendor/golang.org/x/sys/unix/asm_linux_s390x.s b/vendor/golang.org/x/sys/unix/asm_linux_s390x.s
new file mode 100644
index 0000000..1188985
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/asm_linux_s390x.s
@@ -0,0 +1,28 @@
+// Copyright 2016 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 s390x
+// +build linux
+// +build !gccgo
+
+#include "textflag.h"
+
+//
+// System calls for s390x, Linux
+//
+
+// Just jump to package syscall's implementation for all these functions.
+// The runtime may know about them.
+
+TEXT ·Syscall(SB),NOSPLIT,$0-56
+ BR syscall·Syscall(SB)
+
+TEXT ·Syscall6(SB),NOSPLIT,$0-80
+ BR syscall·Syscall6(SB)
+
+TEXT ·RawSyscall(SB),NOSPLIT,$0-56
+ BR syscall·RawSyscall(SB)
+
+TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
+ BR syscall·RawSyscall6(SB)
diff --git a/vendor/golang.org/x/sys/unix/asm_netbsd_386.s b/vendor/golang.org/x/sys/unix/asm_netbsd_386.s
new file mode 100644
index 0000000..48bdcd7
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/asm_netbsd_386.s
@@ -0,0 +1,29 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !gccgo
+
+#include "textflag.h"
+
+//
+// System call support for 386, NetBSD
+//
+
+// Just jump to package syscall's implementation for all these functions.
+// The runtime may know about them.
+
+TEXT ·Syscall(SB),NOSPLIT,$0-28
+ JMP syscall·Syscall(SB)
+
+TEXT ·Syscall6(SB),NOSPLIT,$0-40
+ JMP syscall·Syscall6(SB)
+
+TEXT ·Syscall9(SB),NOSPLIT,$0-52
+ JMP syscall·Syscall9(SB)
+
+TEXT ·RawSyscall(SB),NOSPLIT,$0-28
+ JMP syscall·RawSyscall(SB)
+
+TEXT ·RawSyscall6(SB),NOSPLIT,$0-40
+ JMP syscall·RawSyscall6(SB)
diff --git a/vendor/golang.org/x/sys/unix/asm_netbsd_amd64.s b/vendor/golang.org/x/sys/unix/asm_netbsd_amd64.s
new file mode 100644
index 0000000..2ede05c
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/asm_netbsd_amd64.s
@@ -0,0 +1,29 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !gccgo
+
+#include "textflag.h"
+
+//
+// System call support for AMD64, NetBSD
+//
+
+// Just jump to package syscall's implementation for all these functions.
+// The runtime may know about them.
+
+TEXT ·Syscall(SB),NOSPLIT,$0-56
+ JMP syscall·Syscall(SB)
+
+TEXT ·Syscall6(SB),NOSPLIT,$0-80
+ JMP syscall·Syscall6(SB)
+
+TEXT ·Syscall9(SB),NOSPLIT,$0-104
+ JMP syscall·Syscall9(SB)
+
+TEXT ·RawSyscall(SB),NOSPLIT,$0-56
+ JMP syscall·RawSyscall(SB)
+
+TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
+ JMP syscall·RawSyscall6(SB)
diff --git a/vendor/golang.org/x/sys/unix/asm_netbsd_arm.s b/vendor/golang.org/x/sys/unix/asm_netbsd_arm.s
new file mode 100644
index 0000000..e892857
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/asm_netbsd_arm.s
@@ -0,0 +1,29 @@
+// Copyright 2013 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 !gccgo
+
+#include "textflag.h"
+
+//
+// System call support for ARM, NetBSD
+//
+
+// Just jump to package syscall's implementation for all these functions.
+// The runtime may know about them.
+
+TEXT ·Syscall(SB),NOSPLIT,$0-28
+ B syscall·Syscall(SB)
+
+TEXT ·Syscall6(SB),NOSPLIT,$0-40
+ B syscall·Syscall6(SB)
+
+TEXT ·Syscall9(SB),NOSPLIT,$0-52
+ B syscall·Syscall9(SB)
+
+TEXT ·RawSyscall(SB),NOSPLIT,$0-28
+ B syscall·RawSyscall(SB)
+
+TEXT ·RawSyscall6(SB),NOSPLIT,$0-40
+ B syscall·RawSyscall6(SB)
diff --git a/vendor/golang.org/x/sys/unix/asm_openbsd_386.s b/vendor/golang.org/x/sys/unix/asm_openbsd_386.s
new file mode 100644
index 0000000..00576f3
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/asm_openbsd_386.s
@@ -0,0 +1,29 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !gccgo
+
+#include "textflag.h"
+
+//
+// System call support for 386, OpenBSD
+//
+
+// Just jump to package syscall's implementation for all these functions.
+// The runtime may know about them.
+
+TEXT ·Syscall(SB),NOSPLIT,$0-28
+ JMP syscall·Syscall(SB)
+
+TEXT ·Syscall6(SB),NOSPLIT,$0-40
+ JMP syscall·Syscall6(SB)
+
+TEXT ·Syscall9(SB),NOSPLIT,$0-52
+ JMP syscall·Syscall9(SB)
+
+TEXT ·RawSyscall(SB),NOSPLIT,$0-28
+ JMP syscall·RawSyscall(SB)
+
+TEXT ·RawSyscall6(SB),NOSPLIT,$0-40
+ JMP syscall·RawSyscall6(SB)
diff --git a/vendor/golang.org/x/sys/unix/asm_openbsd_amd64.s b/vendor/golang.org/x/sys/unix/asm_openbsd_amd64.s
new file mode 100644
index 0000000..790ef77
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/asm_openbsd_amd64.s
@@ -0,0 +1,29 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !gccgo
+
+#include "textflag.h"
+
+//
+// System call support for AMD64, OpenBSD
+//
+
+// Just jump to package syscall's implementation for all these functions.
+// The runtime may know about them.
+
+TEXT ·Syscall(SB),NOSPLIT,$0-56
+ JMP syscall·Syscall(SB)
+
+TEXT ·Syscall6(SB),NOSPLIT,$0-80
+ JMP syscall·Syscall6(SB)
+
+TEXT ·Syscall9(SB),NOSPLIT,$0-104
+ JMP syscall·Syscall9(SB)
+
+TEXT ·RawSyscall(SB),NOSPLIT,$0-56
+ JMP syscall·RawSyscall(SB)
+
+TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
+ JMP syscall·RawSyscall6(SB)
diff --git a/vendor/golang.org/x/sys/unix/asm_solaris_amd64.s b/vendor/golang.org/x/sys/unix/asm_solaris_amd64.s
new file mode 100644
index 0000000..ded8260
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/asm_solaris_amd64.s
@@ -0,0 +1,17 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !gccgo
+
+#include "textflag.h"
+
+//
+// System calls for amd64, Solaris are implemented in runtime/syscall_solaris.go
+//
+
+TEXT ·sysvicall6(SB),NOSPLIT,$0-88
+ JMP syscall·sysvicall6(SB)
+
+TEXT ·rawSysvicall6(SB),NOSPLIT,$0-88
+ JMP syscall·rawSysvicall6(SB)
diff --git a/vendor/golang.org/x/sys/unix/bluetooth_linux.go b/vendor/golang.org/x/sys/unix/bluetooth_linux.go
new file mode 100644
index 0000000..6e32296
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/bluetooth_linux.go
@@ -0,0 +1,35 @@
+// Copyright 2016 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.
+
+// Bluetooth sockets and messages
+
+package unix
+
+// Bluetooth Protocols
+const (
+ BTPROTO_L2CAP = 0
+ BTPROTO_HCI = 1
+ BTPROTO_SCO = 2
+ BTPROTO_RFCOMM = 3
+ BTPROTO_BNEP = 4
+ BTPROTO_CMTP = 5
+ BTPROTO_HIDP = 6
+ BTPROTO_AVDTP = 7
+)
+
+const (
+ HCI_CHANNEL_RAW = 0
+ HCI_CHANNEL_USER = 1
+ HCI_CHANNEL_MONITOR = 2
+ HCI_CHANNEL_CONTROL = 3
+)
+
+// Socketoption Level
+const (
+ SOL_BLUETOOTH = 0x112
+ SOL_HCI = 0x0
+ SOL_L2CAP = 0x6
+ SOL_RFCOMM = 0x12
+ SOL_SCO = 0x11
+)
diff --git a/vendor/golang.org/x/sys/unix/constants.go b/vendor/golang.org/x/sys/unix/constants.go
new file mode 100644
index 0000000..a96f0eb
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/constants.go
@@ -0,0 +1,13 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build darwin dragonfly freebsd linux netbsd openbsd solaris
+
+package unix
+
+const (
+ R_OK = 0x4
+ W_OK = 0x2
+ X_OK = 0x1
+)
diff --git a/vendor/golang.org/x/sys/unix/creds_test.go b/vendor/golang.org/x/sys/unix/creds_test.go
new file mode 100644
index 0000000..eaae7c3
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/creds_test.go
@@ -0,0 +1,121 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build linux
+
+package unix_test
+
+import (
+ "bytes"
+ "net"
+ "os"
+ "syscall"
+ "testing"
+
+ "golang.org/x/sys/unix"
+)
+
+// TestSCMCredentials tests the sending and receiving of credentials
+// (PID, UID, GID) in an ancillary message between two UNIX
+// sockets. The SO_PASSCRED socket option is enabled on the sending
+// socket for this to work.
+func TestSCMCredentials(t *testing.T) {
+ fds, err := unix.Socketpair(unix.AF_LOCAL, unix.SOCK_STREAM, 0)
+ if err != nil {
+ t.Fatalf("Socketpair: %v", err)
+ }
+ defer unix.Close(fds[0])
+ defer unix.Close(fds[1])
+
+ err = unix.SetsockoptInt(fds[0], unix.SOL_SOCKET, unix.SO_PASSCRED, 1)
+ if err != nil {
+ t.Fatalf("SetsockoptInt: %v", err)
+ }
+
+ srvFile := os.NewFile(uintptr(fds[0]), "server")
+ defer srvFile.Close()
+ srv, err := net.FileConn(srvFile)
+ if err != nil {
+ t.Errorf("FileConn: %v", err)
+ return
+ }
+ defer srv.Close()
+
+ cliFile := os.NewFile(uintptr(fds[1]), "client")
+ defer cliFile.Close()
+ cli, err := net.FileConn(cliFile)
+ if err != nil {
+ t.Errorf("FileConn: %v", err)
+ return
+ }
+ defer cli.Close()
+
+ var ucred unix.Ucred
+ if os.Getuid() != 0 {
+ ucred.Pid = int32(os.Getpid())
+ ucred.Uid = 0
+ ucred.Gid = 0
+ oob := unix.UnixCredentials(&ucred)
+ _, _, err := cli.(*net.UnixConn).WriteMsgUnix(nil, oob, nil)
+ if op, ok := err.(*net.OpError); ok {
+ err = op.Err
+ }
+ if sys, ok := err.(*os.SyscallError); ok {
+ err = sys.Err
+ }
+ if err != syscall.EPERM {
+ t.Fatalf("WriteMsgUnix failed with %v, want EPERM", err)
+ }
+ }
+
+ ucred.Pid = int32(os.Getpid())
+ ucred.Uid = uint32(os.Getuid())
+ ucred.Gid = uint32(os.Getgid())
+ oob := unix.UnixCredentials(&ucred)
+
+ // this is going to send a dummy byte
+ n, oobn, err := cli.(*net.UnixConn).WriteMsgUnix(nil, oob, nil)
+ if err != nil {
+ t.Fatalf("WriteMsgUnix: %v", err)
+ }
+ if n != 0 {
+ t.Fatalf("WriteMsgUnix n = %d, want 0", n)
+ }
+ if oobn != len(oob) {
+ t.Fatalf("WriteMsgUnix oobn = %d, want %d", oobn, len(oob))
+ }
+
+ oob2 := make([]byte, 10*len(oob))
+ n, oobn2, flags, _, err := srv.(*net.UnixConn).ReadMsgUnix(nil, oob2)
+ if err != nil {
+ t.Fatalf("ReadMsgUnix: %v", err)
+ }
+ if flags != 0 {
+ t.Fatalf("ReadMsgUnix flags = 0x%x, want 0", flags)
+ }
+ if n != 1 {
+ t.Fatalf("ReadMsgUnix n = %d, want 1 (dummy byte)", n)
+ }
+ if oobn2 != oobn {
+ // without SO_PASSCRED set on the socket, ReadMsgUnix will
+ // return zero oob bytes
+ t.Fatalf("ReadMsgUnix oobn = %d, want %d", oobn2, oobn)
+ }
+ oob2 = oob2[:oobn2]
+ if !bytes.Equal(oob, oob2) {
+ t.Fatal("ReadMsgUnix oob bytes don't match")
+ }
+
+ scm, err := unix.ParseSocketControlMessage(oob2)
+ if err != nil {
+ t.Fatalf("ParseSocketControlMessage: %v", err)
+ }
+ newUcred, err := unix.ParseUnixCredentials(&scm[0])
+ if err != nil {
+ t.Fatalf("ParseUnixCredentials: %v", err)
+ }
+ if *newUcred != ucred {
+ t.Fatalf("ParseUnixCredentials = %+v, want %+v", newUcred, ucred)
+ }
+}
diff --git a/vendor/golang.org/x/sys/unix/dirent.go b/vendor/golang.org/x/sys/unix/dirent.go
new file mode 100644
index 0000000..bd47581
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/dirent.go
@@ -0,0 +1,102 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
+
+package unix
+
+import "unsafe"
+
+// readInt returns the size-bytes unsigned integer in native byte order at offset off.
+func readInt(b []byte, off, size uintptr) (u uint64, ok bool) {
+ if len(b) < int(off+size) {
+ return 0, false
+ }
+ if isBigEndian {
+ return readIntBE(b[off:], size), true
+ }
+ return readIntLE(b[off:], size), true
+}
+
+func readIntBE(b []byte, size uintptr) uint64 {
+ switch size {
+ case 1:
+ return uint64(b[0])
+ case 2:
+ _ = b[1] // bounds check hint to compiler; see golang.org/issue/14808
+ return uint64(b[1]) | uint64(b[0])<<8
+ case 4:
+ _ = b[3] // bounds check hint to compiler; see golang.org/issue/14808
+ return uint64(b[3]) | uint64(b[2])<<8 | uint64(b[1])<<16 | uint64(b[0])<<24
+ case 8:
+ _ = b[7] // bounds check hint to compiler; see golang.org/issue/14808
+ return uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 |
+ uint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56
+ default:
+ panic("syscall: readInt with unsupported size")
+ }
+}
+
+func readIntLE(b []byte, size uintptr) uint64 {
+ switch size {
+ case 1:
+ return uint64(b[0])
+ case 2:
+ _ = b[1] // bounds check hint to compiler; see golang.org/issue/14808
+ return uint64(b[0]) | uint64(b[1])<<8
+ case 4:
+ _ = b[3] // bounds check hint to compiler; see golang.org/issue/14808
+ return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24
+ case 8:
+ _ = b[7] // bounds check hint to compiler; see golang.org/issue/14808
+ return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 |
+ uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56
+ default:
+ panic("syscall: readInt with unsupported size")
+ }
+}
+
+// ParseDirent parses up to max directory entries in buf,
+// appending the names to names. It returns the number of
+// bytes consumed from buf, the number of entries added
+// to names, and the new names slice.
+func ParseDirent(buf []byte, max int, names []string) (consumed int, count int, newnames []string) {
+ origlen := len(buf)
+ count = 0
+ for max != 0 && len(buf) > 0 {
+ reclen, ok := direntReclen(buf)
+ if !ok || reclen > uint64(len(buf)) {
+ return origlen, count, names
+ }
+ rec := buf[:reclen]
+ buf = buf[reclen:]
+ ino, ok := direntIno(rec)
+ if !ok {
+ break
+ }
+ if ino == 0 { // File absent in directory.
+ continue
+ }
+ const namoff = uint64(unsafe.Offsetof(Dirent{}.Name))
+ namlen, ok := direntNamlen(rec)
+ if !ok || namoff+namlen > uint64(len(rec)) {
+ break
+ }
+ name := rec[namoff : namoff+namlen]
+ for i, c := range name {
+ if c == 0 {
+ name = name[:i]
+ break
+ }
+ }
+ // Check for useless names before allocating a string.
+ if string(name) == "." || string(name) == ".." {
+ continue
+ }
+ max--
+ count++
+ names = append(names, string(name))
+ }
+ return origlen - len(buf), count, names
+}
diff --git a/vendor/golang.org/x/sys/unix/endian_big.go b/vendor/golang.org/x/sys/unix/endian_big.go
new file mode 100644
index 0000000..5e92690
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/endian_big.go
@@ -0,0 +1,9 @@
+// Copyright 2016 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 ppc64 s390x mips mips64
+
+package unix
+
+const isBigEndian = true
diff --git a/vendor/golang.org/x/sys/unix/endian_little.go b/vendor/golang.org/x/sys/unix/endian_little.go
new file mode 100644
index 0000000..085df2d
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/endian_little.go
@@ -0,0 +1,9 @@
+// Copyright 2016 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 386 amd64 amd64p32 arm arm64 ppc64le mipsle mips64le
+
+package unix
+
+const isBigEndian = false
diff --git a/vendor/golang.org/x/sys/unix/env_unix.go b/vendor/golang.org/x/sys/unix/env_unix.go
new file mode 100644
index 0000000..45e281a
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/env_unix.go
@@ -0,0 +1,27 @@
+// Copyright 2010 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 darwin dragonfly freebsd linux netbsd openbsd solaris
+
+// Unix environment variables.
+
+package unix
+
+import "syscall"
+
+func Getenv(key string) (value string, found bool) {
+ return syscall.Getenv(key)
+}
+
+func Setenv(key, value string) error {
+ return syscall.Setenv(key, value)
+}
+
+func Clearenv() {
+ syscall.Clearenv()
+}
+
+func Environ() []string {
+ return syscall.Environ()
+}
diff --git a/vendor/golang.org/x/sys/unix/env_unset.go b/vendor/golang.org/x/sys/unix/env_unset.go
new file mode 100644
index 0000000..9222262
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/env_unset.go
@@ -0,0 +1,14 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build go1.4
+
+package unix
+
+import "syscall"
+
+func Unsetenv(key string) error {
+ // This was added in Go 1.4.
+ return syscall.Unsetenv(key)
+}
diff --git a/vendor/golang.org/x/sys/unix/export_test.go b/vendor/golang.org/x/sys/unix/export_test.go
new file mode 100644
index 0000000..b4fdd97
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/export_test.go
@@ -0,0 +1,9 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build darwin dragonfly freebsd linux netbsd openbsd solaris
+
+package unix
+
+var Itoa = itoa
diff --git a/vendor/golang.org/x/sys/unix/flock.go b/vendor/golang.org/x/sys/unix/flock.go
new file mode 100644
index 0000000..ce67a59
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/flock.go
@@ -0,0 +1,24 @@
+// +build linux darwin freebsd openbsd netbsd dragonfly
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build darwin dragonfly freebsd linux netbsd openbsd
+
+package unix
+
+import "unsafe"
+
+// fcntl64Syscall is usually SYS_FCNTL, but is overridden on 32-bit Linux
+// systems by flock_linux_32bit.go to be SYS_FCNTL64.
+var fcntl64Syscall uintptr = SYS_FCNTL
+
+// FcntlFlock performs a fcntl syscall for the F_GETLK, F_SETLK or F_SETLKW command.
+func FcntlFlock(fd uintptr, cmd int, lk *Flock_t) error {
+ _, _, errno := Syscall(fcntl64Syscall, fd, uintptr(cmd), uintptr(unsafe.Pointer(lk)))
+ if errno == 0 {
+ return nil
+ }
+ return errno
+}
diff --git a/vendor/golang.org/x/sys/unix/flock_linux_32bit.go b/vendor/golang.org/x/sys/unix/flock_linux_32bit.go
new file mode 100644
index 0000000..fc0e50e
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/flock_linux_32bit.go
@@ -0,0 +1,13 @@
+// +build linux,386 linux,arm linux,mips linux,mipsle
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package unix
+
+func init() {
+ // On 32-bit Linux systems, the fcntl syscall that matches Go's
+ // Flock_t type is SYS_FCNTL64, not SYS_FCNTL.
+ fcntl64Syscall = SYS_FCNTL64
+}
diff --git a/vendor/golang.org/x/sys/unix/gccgo.go b/vendor/golang.org/x/sys/unix/gccgo.go
new file mode 100644
index 0000000..94c8232
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/gccgo.go
@@ -0,0 +1,46 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build gccgo
+
+package unix
+
+import "syscall"
+
+// We can't use the gc-syntax .s files for gccgo. On the plus side
+// much of the functionality can be written directly in Go.
+
+//extern gccgoRealSyscall
+func realSyscall(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r, errno uintptr)
+
+func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno) {
+ syscall.Entersyscall()
+ r, errno := realSyscall(trap, a1, a2, a3, 0, 0, 0, 0, 0, 0)
+ syscall.Exitsyscall()
+ return r, 0, syscall.Errno(errno)
+}
+
+func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err syscall.Errno) {
+ syscall.Entersyscall()
+ r, errno := realSyscall(trap, a1, a2, a3, a4, a5, a6, 0, 0, 0)
+ syscall.Exitsyscall()
+ return r, 0, syscall.Errno(errno)
+}
+
+func Syscall9(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno) {
+ syscall.Entersyscall()
+ r, errno := realSyscall(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9)
+ syscall.Exitsyscall()
+ return r, 0, syscall.Errno(errno)
+}
+
+func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno) {
+ r, errno := realSyscall(trap, a1, a2, a3, 0, 0, 0, 0, 0, 0)
+ return r, 0, syscall.Errno(errno)
+}
+
+func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err syscall.Errno) {
+ r, errno := realSyscall(trap, a1, a2, a3, a4, a5, a6, 0, 0, 0)
+ return r, 0, syscall.Errno(errno)
+}
diff --git a/vendor/golang.org/x/sys/unix/gccgo_c.c b/vendor/golang.org/x/sys/unix/gccgo_c.c
new file mode 100644
index 0000000..07f6be0
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/gccgo_c.c
@@ -0,0 +1,41 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build gccgo
+
+#include
+#include
+#include
+
+#define _STRINGIFY2_(x) #x
+#define _STRINGIFY_(x) _STRINGIFY2_(x)
+#define GOSYM_PREFIX _STRINGIFY_(__USER_LABEL_PREFIX__)
+
+// Call syscall from C code because the gccgo support for calling from
+// Go to C does not support varargs functions.
+
+struct ret {
+ uintptr_t r;
+ uintptr_t err;
+};
+
+struct ret
+gccgoRealSyscall(uintptr_t trap, uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t a6, uintptr_t a7, uintptr_t a8, uintptr_t a9)
+{
+ struct ret r;
+
+ errno = 0;
+ r.r = syscall(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+ r.err = errno;
+ return r;
+}
+
+// Define the use function in C so that it is not inlined.
+
+extern void use(void *) __asm__ (GOSYM_PREFIX GOPKGPATH ".use") __attribute__((noinline));
+
+void
+use(void *p __attribute__ ((unused)))
+{
+}
diff --git a/vendor/golang.org/x/sys/unix/gccgo_linux_amd64.go b/vendor/golang.org/x/sys/unix/gccgo_linux_amd64.go
new file mode 100644
index 0000000..bffe1a7
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/gccgo_linux_amd64.go
@@ -0,0 +1,20 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build gccgo,linux,amd64
+
+package unix
+
+import "syscall"
+
+//extern gettimeofday
+func realGettimeofday(*Timeval, *byte) int32
+
+func gettimeofday(tv *Timeval) (err syscall.Errno) {
+ r := realGettimeofday(tv, nil)
+ if r < 0 {
+ return syscall.GetErrno()
+ }
+ return 0
+}
diff --git a/vendor/golang.org/x/sys/unix/gccgo_linux_sparc64.go b/vendor/golang.org/x/sys/unix/gccgo_linux_sparc64.go
new file mode 100644
index 0000000..5633269
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/gccgo_linux_sparc64.go
@@ -0,0 +1,20 @@
+// Copyright 2016 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 gccgo,linux,sparc64
+
+package unix
+
+import "syscall"
+
+//extern sysconf
+func realSysconf(name int) int64
+
+func sysconf(name int) (n int64, err syscall.Errno) {
+ r := realSysconf(name)
+ if r < 0 {
+ return 0, syscall.GetErrno()
+ }
+ return r, 0
+}
diff --git a/vendor/golang.org/x/sys/unix/linux/Dockerfile b/vendor/golang.org/x/sys/unix/linux/Dockerfile
new file mode 100644
index 0000000..4397143
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/linux/Dockerfile
@@ -0,0 +1,48 @@
+FROM ubuntu:16.04
+
+# Dependencies to get the git sources and go binaries
+RUN apt-get update && apt-get install -y \
+ curl \
+ git \
+ && rm -rf /var/lib/apt/lists/*
+
+# Get the git sources. If not cached, this takes O(5 minutes).
+WORKDIR /git
+RUN git config --global advice.detachedHead false
+# Linux Kernel: Released 19 Feb 2017
+RUN git clone --branch v4.10 --depth 1 https://kernel.googlesource.com/pub/scm/linux/kernel/git/torvalds/linux
+# GNU C library: Released 05 Feb 2017 (we should try to get a secure way to clone this)
+RUN git clone --branch glibc-2.25 --depth 1 git://sourceware.org/git/glibc.git
+
+# Get Go 1.8 (https://github.com/docker-library/golang/blob/master/1.8/Dockerfile)
+ENV GOLANG_VERSION 1.8
+ENV GOLANG_DOWNLOAD_URL https://golang.org/dl/go$GOLANG_VERSION.linux-amd64.tar.gz
+ENV GOLANG_DOWNLOAD_SHA256 53ab94104ee3923e228a2cb2116e5e462ad3ebaeea06ff04463479d7f12d27ca
+
+RUN curl -fsSL "$GOLANG_DOWNLOAD_URL" -o golang.tar.gz \
+ && echo "$GOLANG_DOWNLOAD_SHA256 golang.tar.gz" | sha256sum -c - \
+ && tar -C /usr/local -xzf golang.tar.gz \
+ && rm golang.tar.gz
+
+ENV PATH /usr/local/go/bin:$PATH
+
+# Linux and Glibc build dependencies
+RUN apt-get update && apt-get install -y \
+ gawk make python \
+ gcc gcc-multilib \
+ gettext texinfo \
+ && rm -rf /var/lib/apt/lists/*
+# Emulator and cross compilers
+RUN apt-get update && apt-get install -y \
+ qemu \
+ gcc-aarch64-linux-gnu gcc-arm-linux-gnueabi \
+ gcc-mips-linux-gnu gcc-mips64-linux-gnuabi64 \
+ gcc-mips64el-linux-gnuabi64 gcc-mipsel-linux-gnu \
+ gcc-powerpc64-linux-gnu gcc-powerpc64le-linux-gnu \
+ gcc-s390x-linux-gnu gcc-sparc64-linux-gnu \
+ && rm -rf /var/lib/apt/lists/*
+
+# Let the scripts know they are in the docker environment
+ENV GOLANG_SYS_BUILD docker
+WORKDIR /build
+ENTRYPOINT ["go", "run", "linux/mkall.go", "/git/linux", "/git/glibc"]
diff --git a/vendor/golang.org/x/sys/unix/linux/mkall.go b/vendor/golang.org/x/sys/unix/linux/mkall.go
new file mode 100644
index 0000000..429754f
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/linux/mkall.go
@@ -0,0 +1,379 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// linux/mkall.go - Generates all Linux zsysnum, zsyscall, zerror, and ztype
+// files for all 11 linux architectures supported by the go compiler. See
+// README.md for more information about the build system.
+
+// To run it you must have a git checkout of the Linux kernel and glibc. Once
+// the appropriate sources are ready, the program is run as:
+// go run linux/mkall.go
+
+// +build ignore
+
+package main
+
+import (
+ "fmt"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "runtime"
+ "strings"
+)
+
+// These will be paths to the appropriate source directories.
+var LinuxDir string
+var GlibcDir string
+
+const TempDir = "/tmp"
+const IncludeDir = TempDir + "/include" // To hold our C headers
+const BuildDir = TempDir + "/build" // To hold intermediate build files
+
+const GOOS = "linux" // Only for Linux targets
+const BuildArch = "amd64" // Must be built on this architecture
+const MinKernel = "2.6.23" // https://golang.org/doc/install#requirements
+
+type target struct {
+ GoArch string // Architecture name according to Go
+ LinuxArch string // Architecture name according to the Linux Kernel
+ GNUArch string // Architecture name according to GNU tools (https://wiki.debian.org/Multiarch/Tuples)
+ BigEndian bool // Default Little Endian
+ SignedChar bool // Is -fsigned-char needed (default no)
+ Bits int
+}
+
+// List of the 11 Linux targets supported by the go compiler. sparc64 is not
+// currently supported, though a port is in progress.
+var targets = []target{
+ {
+ GoArch: "386",
+ LinuxArch: "x86",
+ GNUArch: "i686-linux-gnu", // Note "i686" not "i386"
+ Bits: 32,
+ },
+ {
+ GoArch: "amd64",
+ LinuxArch: "x86",
+ GNUArch: "x86_64-linux-gnu",
+ Bits: 64,
+ },
+ {
+ GoArch: "arm64",
+ LinuxArch: "arm64",
+ GNUArch: "aarch64-linux-gnu",
+ SignedChar: true,
+ Bits: 64,
+ },
+ {
+ GoArch: "arm",
+ LinuxArch: "arm",
+ GNUArch: "arm-linux-gnueabi",
+ Bits: 32,
+ },
+ {
+ GoArch: "mips",
+ LinuxArch: "mips",
+ GNUArch: "mips-linux-gnu",
+ BigEndian: true,
+ Bits: 32,
+ },
+ {
+ GoArch: "mipsle",
+ LinuxArch: "mips",
+ GNUArch: "mipsel-linux-gnu",
+ Bits: 32,
+ },
+ {
+ GoArch: "mips64",
+ LinuxArch: "mips",
+ GNUArch: "mips64-linux-gnuabi64",
+ BigEndian: true,
+ Bits: 64,
+ },
+ {
+ GoArch: "mips64le",
+ LinuxArch: "mips",
+ GNUArch: "mips64el-linux-gnuabi64",
+ Bits: 64,
+ },
+ {
+ GoArch: "ppc64",
+ LinuxArch: "powerpc",
+ GNUArch: "powerpc64-linux-gnu",
+ BigEndian: true,
+ Bits: 64,
+ },
+ {
+ GoArch: "ppc64le",
+ LinuxArch: "powerpc",
+ GNUArch: "powerpc64le-linux-gnu",
+ Bits: 64,
+ },
+ {
+ GoArch: "s390x",
+ LinuxArch: "s390",
+ GNUArch: "s390x-linux-gnu",
+ BigEndian: true,
+ SignedChar: true,
+ Bits: 64,
+ },
+ // {
+ // GoArch: "sparc64",
+ // LinuxArch: "sparc",
+ // GNUArch: "sparc64-linux-gnu",
+ // BigEndian: true,
+ // Bits: 64,
+ // },
+}
+
+func main() {
+ if runtime.GOOS != GOOS || runtime.GOARCH != BuildArch {
+ fmt.Printf("Build system has GOOS_GOARCH = %s_%s, need %s_%s\n",
+ runtime.GOOS, runtime.GOARCH, GOOS, BuildArch)
+ return
+ }
+
+ // Check that we are using the new build system if we should
+ if os.Getenv("GOLANG_SYS_BUILD") != "docker" {
+ fmt.Println("In the new build system, mkall.go should not be called directly.")
+ fmt.Println("See README.md")
+ return
+ }
+
+ // Parse the command line options
+ if len(os.Args) != 3 {
+ fmt.Println("USAGE: go run linux/mkall.go ")
+ return
+ }
+ LinuxDir = os.Args[1]
+ GlibcDir = os.Args[2]
+
+ for _, t := range targets {
+ fmt.Printf("----- GENERATING: %s -----\n", t.GoArch)
+ if err := t.generateFiles(); err != nil {
+ fmt.Printf("%v\n***** FAILURE: %s *****\n\n", err, t.GoArch)
+ } else {
+ fmt.Printf("----- SUCCESS: %s -----\n\n", t.GoArch)
+ }
+ }
+}
+
+// Makes an exec.Cmd with Stderr attached to os.Stderr
+func makeCommand(name string, args ...string) *exec.Cmd {
+ cmd := exec.Command(name, args...)
+ cmd.Stderr = os.Stderr
+ return cmd
+}
+
+// Runs the command, pipes output to a formatter, pipes that to an output file.
+func (t *target) commandFormatOutput(formatter string, outputFile string,
+ name string, args ...string) (err error) {
+ mainCmd := makeCommand(name, args...)
+
+ fmtCmd := makeCommand(formatter)
+ if formatter == "mkpost" {
+ fmtCmd = makeCommand("go", "run", "mkpost.go")
+ // Set GOARCH_TARGET so mkpost knows what GOARCH is..
+ fmtCmd.Env = append(os.Environ(), "GOARCH_TARGET="+t.GoArch)
+ // Set GOARCH to host arch for mkpost, so it can run natively.
+ for i, s := range fmtCmd.Env {
+ if strings.HasPrefix(s, "GOARCH=") {
+ fmtCmd.Env[i] = "GOARCH=" + BuildArch
+ }
+ }
+ }
+
+ // mainCmd | fmtCmd > outputFile
+ if fmtCmd.Stdin, err = mainCmd.StdoutPipe(); err != nil {
+ return
+ }
+ if fmtCmd.Stdout, err = os.Create(outputFile); err != nil {
+ return
+ }
+
+ // Make sure the formatter eventually closes
+ if err = fmtCmd.Start(); err != nil {
+ return
+ }
+ defer func() {
+ fmtErr := fmtCmd.Wait()
+ if err == nil {
+ err = fmtErr
+ }
+ }()
+
+ return mainCmd.Run()
+}
+
+// Generates all the files for a Linux target
+func (t *target) generateFiles() error {
+ // Setup environment variables
+ os.Setenv("GOOS", GOOS)
+ os.Setenv("GOARCH", t.GoArch)
+
+ // Get appropriate compiler and emulator (unless on x86)
+ if t.LinuxArch != "x86" {
+ // Check/Setup cross compiler
+ compiler := t.GNUArch + "-gcc"
+ if _, err := exec.LookPath(compiler); err != nil {
+ return err
+ }
+ os.Setenv("CC", compiler)
+
+ // Check/Setup emulator (usually first component of GNUArch)
+ qemuArchName := t.GNUArch[:strings.Index(t.GNUArch, "-")]
+ if t.LinuxArch == "powerpc" {
+ qemuArchName = t.GoArch
+ }
+ os.Setenv("GORUN", "qemu-"+qemuArchName)
+ } else {
+ os.Setenv("CC", "gcc")
+ }
+
+ // Make the include directory and fill it with headers
+ if err := os.MkdirAll(IncludeDir, os.ModePerm); err != nil {
+ return err
+ }
+ defer os.RemoveAll(IncludeDir)
+ if err := t.makeHeaders(); err != nil {
+ return fmt.Errorf("could not make header files: %v", err)
+ }
+ fmt.Println("header files generated")
+
+ // Make each of the four files
+ if err := t.makeZSysnumFile(); err != nil {
+ return fmt.Errorf("could not make zsysnum file: %v", err)
+ }
+ fmt.Println("zsysnum file generated")
+
+ if err := t.makeZSyscallFile(); err != nil {
+ return fmt.Errorf("could not make zsyscall file: %v", err)
+ }
+ fmt.Println("zsyscall file generated")
+
+ if err := t.makeZTypesFile(); err != nil {
+ return fmt.Errorf("could not make ztypes file: %v", err)
+ }
+ fmt.Println("ztypes file generated")
+
+ if err := t.makeZErrorsFile(); err != nil {
+ return fmt.Errorf("could not make zerrors file: %v", err)
+ }
+ fmt.Println("zerrors file generated")
+
+ return nil
+}
+
+// Create the Linux and glibc headers in the include directory.
+func (t *target) makeHeaders() error {
+ // Make the Linux headers we need for this architecture
+ linuxMake := makeCommand("make", "headers_install", "ARCH="+t.LinuxArch, "INSTALL_HDR_PATH="+TempDir)
+ linuxMake.Dir = LinuxDir
+ if err := linuxMake.Run(); err != nil {
+ return err
+ }
+
+ // A Temporary build directory for glibc
+ if err := os.MkdirAll(BuildDir, os.ModePerm); err != nil {
+ return err
+ }
+ defer os.RemoveAll(BuildDir)
+
+ // Make the glibc headers we need for this architecture
+ confScript := filepath.Join(GlibcDir, "configure")
+ glibcConf := makeCommand(confScript, "--prefix="+TempDir, "--host="+t.GNUArch, "--enable-kernel="+MinKernel)
+ glibcConf.Dir = BuildDir
+ if err := glibcConf.Run(); err != nil {
+ return err
+ }
+ glibcMake := makeCommand("make", "install-headers")
+ glibcMake.Dir = BuildDir
+ if err := glibcMake.Run(); err != nil {
+ return err
+ }
+ // We only need an empty stubs file
+ stubsFile := filepath.Join(IncludeDir, "gnu/stubs.h")
+ if file, err := os.Create(stubsFile); err != nil {
+ return err
+ } else {
+ file.Close()
+ }
+
+ return nil
+}
+
+// makes the zsysnum_linux_$GOARCH.go file
+func (t *target) makeZSysnumFile() error {
+ zsysnumFile := fmt.Sprintf("zsysnum_linux_%s.go", t.GoArch)
+ unistdFile := filepath.Join(IncludeDir, "asm/unistd.h")
+
+ args := append(t.cFlags(), unistdFile)
+ return t.commandFormatOutput("gofmt", zsysnumFile, "linux/mksysnum.pl", args...)
+}
+
+// makes the zsyscall_linux_$GOARCH.go file
+func (t *target) makeZSyscallFile() error {
+ zsyscallFile := fmt.Sprintf("zsyscall_linux_%s.go", t.GoArch)
+ // Find the correct architecture syscall file (might end with x.go)
+ archSyscallFile := fmt.Sprintf("syscall_linux_%s.go", t.GoArch)
+ if _, err := os.Stat(archSyscallFile); os.IsNotExist(err) {
+ shortArch := strings.TrimSuffix(t.GoArch, "le")
+ archSyscallFile = fmt.Sprintf("syscall_linux_%sx.go", shortArch)
+ }
+
+ args := append(t.mksyscallFlags(), "-tags", "linux,"+t.GoArch,
+ "syscall_linux.go", archSyscallFile)
+ return t.commandFormatOutput("gofmt", zsyscallFile, "./mksyscall.pl", args...)
+}
+
+// makes the zerrors_linux_$GOARCH.go file
+func (t *target) makeZErrorsFile() error {
+ zerrorsFile := fmt.Sprintf("zerrors_linux_%s.go", t.GoArch)
+
+ return t.commandFormatOutput("gofmt", zerrorsFile, "./mkerrors.sh", t.cFlags()...)
+}
+
+// makes the ztypes_linux_$GOARCH.go file
+func (t *target) makeZTypesFile() error {
+ ztypesFile := fmt.Sprintf("ztypes_linux_%s.go", t.GoArch)
+
+ args := []string{"tool", "cgo", "-godefs", "--"}
+ args = append(args, t.cFlags()...)
+ args = append(args, "linux/types.go")
+ return t.commandFormatOutput("mkpost", ztypesFile, "go", args...)
+}
+
+// Flags that should be given to gcc and cgo for this target
+func (t *target) cFlags() []string {
+ // Compile statically to avoid cross-architecture dynamic linking.
+ flags := []string{"-Wall", "-Werror", "-static", "-I" + IncludeDir}
+
+ // Architecture-specific flags
+ if t.SignedChar {
+ flags = append(flags, "-fsigned-char")
+ }
+ if t.LinuxArch == "x86" {
+ flags = append(flags, fmt.Sprintf("-m%d", t.Bits))
+ }
+
+ return flags
+}
+
+// Flags that should be given to mksyscall for this target
+func (t *target) mksyscallFlags() (flags []string) {
+ if t.Bits == 32 {
+ if t.BigEndian {
+ flags = append(flags, "-b32")
+ } else {
+ flags = append(flags, "-l32")
+ }
+ }
+
+ // This flag menas a 64-bit value should use (even, odd)-pair.
+ if t.GoArch == "arm" || (t.LinuxArch == "mips" && t.Bits == 32) {
+ flags = append(flags, "-arm")
+ }
+ return
+}
diff --git a/vendor/golang.org/x/sys/unix/linux/mksysnum.pl b/vendor/golang.org/x/sys/unix/linux/mksysnum.pl
new file mode 100755
index 0000000..63fd800
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/linux/mksysnum.pl
@@ -0,0 +1,85 @@
+#!/usr/bin/env perl
+# Copyright 2009 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+use strict;
+
+if($ENV{'GOARCH'} eq "" || $ENV{'GOOS'} eq "") {
+ print STDERR "GOARCH or GOOS not defined in environment\n";
+ exit 1;
+}
+
+# Check that we are using the new build system if we should
+if($ENV{'GOLANG_SYS_BUILD'} ne "docker") {
+ print STDERR "In the new build system, mksysnum should not be called directly.\n";
+ print STDERR "See README.md\n";
+ exit 1;
+}
+
+my $command = "$0 ". join(' ', @ARGV);
+
+print < 999){
+ # ignore deprecated syscalls that are no longer implemented
+ # https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/include/uapi/asm-generic/unistd.h?id=refs/heads/master#n716
+ return;
+ }
+ $name =~ y/a-z/A-Z/;
+ $num = $num + $offset;
+ print " SYS_$name = $num;\n";
+}
+
+my $prev;
+open(CC, "$ENV{'CC'} -E -dD @ARGV |") || die "can't run $ENV{'CC'}";
+while(){
+ if(/^#define __NR_Linux\s+([0-9]+)/){
+ # mips/mips64: extract offset
+ $offset = $1;
+ }
+ elsif(/^#define __NR(\w*)_SYSCALL_BASE\s+([0-9]+)/){
+ # arm: extract offset
+ $offset = $1;
+ }
+ elsif(/^#define __NR_syscalls\s+/) {
+ # ignore redefinitions of __NR_syscalls
+ }
+ elsif(/^#define __NR_(\w*)Linux_syscalls\s+/) {
+ # mips/mips64: ignore definitions about the number of syscalls
+ }
+ elsif(/^#define __NR_(\w+)\s+([0-9]+)/){
+ $prev = $2;
+ fmt($1, $2);
+ }
+ elsif(/^#define __NR3264_(\w+)\s+([0-9]+)/){
+ $prev = $2;
+ fmt($1, $2);
+ }
+ elsif(/^#define __NR_(\w+)\s+\(\w+\+\s*([0-9]+)\)/){
+ fmt($1, $prev+$2)
+ }
+ elsif(/^#define __NR_(\w+)\s+\(__NR_Linux \+ ([0-9]+)/){
+ fmt($1, $2);
+ }
+ elsif(/^#define __NR_(\w+)\s+\(__NR_SYSCALL_BASE \+ ([0-9]+)/){
+ fmt($1, $2);
+ }
+}
+
+print <
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+// On mips64, the glibc stat and kernel stat do not agree
+#if (defined(__mips__) && _MIPS_SIM == _MIPS_SIM_ABI64)
+
+// Use the stat defined by the kernel with a few modifications. These are:
+// * The time fields (like st_atime and st_atimensec) use the timespec
+// struct (like st_atim) for consitancy with the glibc fields.
+// * The padding fields get different names to not break compatibility.
+// * st_blocks is signed, again for compatibility.
+struct stat {
+ unsigned int st_dev;
+ unsigned int st_pad1[3]; // Reserved for st_dev expansion
+
+ unsigned long st_ino;
+
+ mode_t st_mode;
+ __u32 st_nlink;
+
+ uid_t st_uid;
+ gid_t st_gid;
+
+ unsigned int st_rdev;
+ unsigned int st_pad2[3]; // Reserved for st_rdev expansion
+
+ off_t st_size;
+
+ // These are declared as speperate fields in the kernel. Here we use
+ // the timespec struct for consistancy with the other stat structs.
+ struct timespec st_atim;
+ struct timespec st_mtim;
+ struct timespec st_ctim;
+
+ unsigned int st_blksize;
+ unsigned int st_pad4;
+
+ long st_blocks;
+};
+
+// These are needed because we do not include fcntl.h or sys/types.h
+#include
+#include
+
+#else
+
+// Use the stat defined by glibc
+#include
+#include
+
+#endif
+
+// Certain constants and structs are missing from the fs/crypto UAPI
+#define FS_MAX_KEY_SIZE 64
+struct fscrypt_key {
+ __u32 mode;
+ __u8 raw[FS_MAX_KEY_SIZE];
+ __u32 size;
+};
+
+#ifdef TCSETS2
+// On systems that have "struct termios2" use this as type Termios.
+typedef struct termios2 termios_t;
+#else
+typedef struct termios termios_t;
+#endif
+
+enum {
+ sizeofPtr = sizeof(void*),
+};
+
+union sockaddr_all {
+ struct sockaddr s1; // this one gets used for fields
+ struct sockaddr_in s2; // these pad it out
+ struct sockaddr_in6 s3;
+ struct sockaddr_un s4;
+ struct sockaddr_ll s5;
+ struct sockaddr_nl s6;
+};
+
+struct sockaddr_any {
+ struct sockaddr addr;
+ char pad[sizeof(union sockaddr_all) - sizeof(struct sockaddr)];
+};
+
+// copied from /usr/include/bluetooth/hci.h
+struct sockaddr_hci {
+ sa_family_t hci_family;
+ unsigned short hci_dev;
+ unsigned short hci_channel;
+};;
+
+// copied from /usr/include/linux/un.h
+struct my_sockaddr_un {
+ sa_family_t sun_family;
+#if defined(__ARM_EABI__) || defined(__powerpc64__)
+ // on ARM char is by default unsigned
+ signed char sun_path[108];
+#else
+ char sun_path[108];
+#endif
+};
+
+#ifdef __ARM_EABI__
+typedef struct user_regs PtraceRegs;
+#elif defined(__aarch64__)
+typedef struct user_pt_regs PtraceRegs;
+#elif defined(__mips__) || defined(__powerpc64__)
+typedef struct pt_regs PtraceRegs;
+#elif defined(__s390x__)
+typedef struct _user_regs_struct PtraceRegs;
+#elif defined(__sparc__)
+#include
+typedef struct pt_regs PtraceRegs;
+#else
+typedef struct user_regs_struct PtraceRegs;
+#endif
+
+#if defined(__s390x__)
+typedef struct _user_psw_struct ptracePsw;
+typedef struct _user_fpregs_struct ptraceFpregs;
+typedef struct _user_per_struct ptracePer;
+#else
+typedef struct {} ptracePsw;
+typedef struct {} ptraceFpregs;
+typedef struct {} ptracePer;
+#endif
+
+// The real epoll_event is a union, and godefs doesn't handle it well.
+struct my_epoll_event {
+ uint32_t events;
+#if defined(__ARM_EABI__) || defined(__aarch64__) || (defined(__mips__) && _MIPS_SIM == _ABIO32)
+ // padding is not specified in linux/eventpoll.h but added to conform to the
+ // alignment requirements of EABI
+ int32_t padFd;
+#elif defined(__powerpc64__) || defined(__s390x__) || defined(__sparc__)
+ int32_t _padFd;
+#endif
+ int32_t fd;
+ int32_t pad;
+};
+
+*/
+import "C"
+
+// Machine characteristics; for internal use.
+
+const (
+ sizeofPtr = C.sizeofPtr
+ sizeofShort = C.sizeof_short
+ sizeofInt = C.sizeof_int
+ sizeofLong = C.sizeof_long
+ sizeofLongLong = C.sizeof_longlong
+ PathMax = C.PATH_MAX
+)
+
+// Basic types
+
+type (
+ _C_short C.short
+ _C_int C.int
+ _C_long C.long
+ _C_long_long C.longlong
+)
+
+// Time
+
+type Timespec C.struct_timespec
+
+type Timeval C.struct_timeval
+
+type Timex C.struct_timex
+
+type Time_t C.time_t
+
+type Tms C.struct_tms
+
+type Utimbuf C.struct_utimbuf
+
+// Processes
+
+type Rusage C.struct_rusage
+
+type Rlimit C.struct_rlimit
+
+type _Gid_t C.gid_t
+
+// Files
+
+type Stat_t C.struct_stat
+
+type Statfs_t C.struct_statfs
+
+type Dirent C.struct_dirent
+
+type Fsid C.fsid_t
+
+type Flock_t C.struct_flock
+
+// Filesystem Encryption
+
+type FscryptPolicy C.struct_fscrypt_policy
+
+type FscryptKey C.struct_fscrypt_key
+
+// Structure for Keyctl
+
+type KeyctlDHParams C.struct_keyctl_dh_params
+
+// Advice to Fadvise
+
+const (
+ FADV_NORMAL = C.POSIX_FADV_NORMAL
+ FADV_RANDOM = C.POSIX_FADV_RANDOM
+ FADV_SEQUENTIAL = C.POSIX_FADV_SEQUENTIAL
+ FADV_WILLNEED = C.POSIX_FADV_WILLNEED
+ FADV_DONTNEED = C.POSIX_FADV_DONTNEED
+ FADV_NOREUSE = C.POSIX_FADV_NOREUSE
+)
+
+// Sockets
+
+type RawSockaddrInet4 C.struct_sockaddr_in
+
+type RawSockaddrInet6 C.struct_sockaddr_in6
+
+type RawSockaddrUnix C.struct_my_sockaddr_un
+
+type RawSockaddrLinklayer C.struct_sockaddr_ll
+
+type RawSockaddrNetlink C.struct_sockaddr_nl
+
+type RawSockaddrHCI C.struct_sockaddr_hci
+
+type RawSockaddrCAN C.struct_sockaddr_can
+
+type RawSockaddrALG C.struct_sockaddr_alg
+
+type RawSockaddrVM C.struct_sockaddr_vm
+
+type RawSockaddr C.struct_sockaddr
+
+type RawSockaddrAny C.struct_sockaddr_any
+
+type _Socklen C.socklen_t
+
+type Linger C.struct_linger
+
+type Iovec C.struct_iovec
+
+type IPMreq C.struct_ip_mreq
+
+type IPMreqn C.struct_ip_mreqn
+
+type IPv6Mreq C.struct_ipv6_mreq
+
+type Msghdr C.struct_msghdr
+
+type Cmsghdr C.struct_cmsghdr
+
+type Inet4Pktinfo C.struct_in_pktinfo
+
+type Inet6Pktinfo C.struct_in6_pktinfo
+
+type IPv6MTUInfo C.struct_ip6_mtuinfo
+
+type ICMPv6Filter C.struct_icmp6_filter
+
+type Ucred C.struct_ucred
+
+type TCPInfo C.struct_tcp_info
+
+const (
+ SizeofSockaddrInet4 = C.sizeof_struct_sockaddr_in
+ SizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
+ SizeofSockaddrAny = C.sizeof_struct_sockaddr_any
+ SizeofSockaddrUnix = C.sizeof_struct_sockaddr_un
+ SizeofSockaddrLinklayer = C.sizeof_struct_sockaddr_ll
+ SizeofSockaddrNetlink = C.sizeof_struct_sockaddr_nl
+ SizeofSockaddrHCI = C.sizeof_struct_sockaddr_hci
+ SizeofSockaddrCAN = C.sizeof_struct_sockaddr_can
+ SizeofSockaddrALG = C.sizeof_struct_sockaddr_alg
+ SizeofSockaddrVM = C.sizeof_struct_sockaddr_vm
+ SizeofLinger = C.sizeof_struct_linger
+ SizeofIPMreq = C.sizeof_struct_ip_mreq
+ SizeofIPMreqn = C.sizeof_struct_ip_mreqn
+ SizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq
+ SizeofMsghdr = C.sizeof_struct_msghdr
+ SizeofCmsghdr = C.sizeof_struct_cmsghdr
+ SizeofInet4Pktinfo = C.sizeof_struct_in_pktinfo
+ SizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo
+ SizeofIPv6MTUInfo = C.sizeof_struct_ip6_mtuinfo
+ SizeofICMPv6Filter = C.sizeof_struct_icmp6_filter
+ SizeofUcred = C.sizeof_struct_ucred
+ SizeofTCPInfo = C.sizeof_struct_tcp_info
+)
+
+// Netlink routing and interface messages
+
+const (
+ IFA_UNSPEC = C.IFA_UNSPEC
+ IFA_ADDRESS = C.IFA_ADDRESS
+ IFA_LOCAL = C.IFA_LOCAL
+ IFA_LABEL = C.IFA_LABEL
+ IFA_BROADCAST = C.IFA_BROADCAST
+ IFA_ANYCAST = C.IFA_ANYCAST
+ IFA_CACHEINFO = C.IFA_CACHEINFO
+ IFA_MULTICAST = C.IFA_MULTICAST
+ IFLA_UNSPEC = C.IFLA_UNSPEC
+ IFLA_ADDRESS = C.IFLA_ADDRESS
+ IFLA_BROADCAST = C.IFLA_BROADCAST
+ IFLA_IFNAME = C.IFLA_IFNAME
+ IFLA_MTU = C.IFLA_MTU
+ IFLA_LINK = C.IFLA_LINK
+ IFLA_QDISC = C.IFLA_QDISC
+ IFLA_STATS = C.IFLA_STATS
+ IFLA_COST = C.IFLA_COST
+ IFLA_PRIORITY = C.IFLA_PRIORITY
+ IFLA_MASTER = C.IFLA_MASTER
+ IFLA_WIRELESS = C.IFLA_WIRELESS
+ IFLA_PROTINFO = C.IFLA_PROTINFO
+ IFLA_TXQLEN = C.IFLA_TXQLEN
+ IFLA_MAP = C.IFLA_MAP
+ IFLA_WEIGHT = C.IFLA_WEIGHT
+ IFLA_OPERSTATE = C.IFLA_OPERSTATE
+ IFLA_LINKMODE = C.IFLA_LINKMODE
+ IFLA_LINKINFO = C.IFLA_LINKINFO
+ IFLA_NET_NS_PID = C.IFLA_NET_NS_PID
+ IFLA_IFALIAS = C.IFLA_IFALIAS
+ IFLA_MAX = C.IFLA_MAX
+ RT_SCOPE_UNIVERSE = C.RT_SCOPE_UNIVERSE
+ RT_SCOPE_SITE = C.RT_SCOPE_SITE
+ RT_SCOPE_LINK = C.RT_SCOPE_LINK
+ RT_SCOPE_HOST = C.RT_SCOPE_HOST
+ RT_SCOPE_NOWHERE = C.RT_SCOPE_NOWHERE
+ RT_TABLE_UNSPEC = C.RT_TABLE_UNSPEC
+ RT_TABLE_COMPAT = C.RT_TABLE_COMPAT
+ RT_TABLE_DEFAULT = C.RT_TABLE_DEFAULT
+ RT_TABLE_MAIN = C.RT_TABLE_MAIN
+ RT_TABLE_LOCAL = C.RT_TABLE_LOCAL
+ RT_TABLE_MAX = C.RT_TABLE_MAX
+ RTA_UNSPEC = C.RTA_UNSPEC
+ RTA_DST = C.RTA_DST
+ RTA_SRC = C.RTA_SRC
+ RTA_IIF = C.RTA_IIF
+ RTA_OIF = C.RTA_OIF
+ RTA_GATEWAY = C.RTA_GATEWAY
+ RTA_PRIORITY = C.RTA_PRIORITY
+ RTA_PREFSRC = C.RTA_PREFSRC
+ RTA_METRICS = C.RTA_METRICS
+ RTA_MULTIPATH = C.RTA_MULTIPATH
+ RTA_FLOW = C.RTA_FLOW
+ RTA_CACHEINFO = C.RTA_CACHEINFO
+ RTA_TABLE = C.RTA_TABLE
+ RTN_UNSPEC = C.RTN_UNSPEC
+ RTN_UNICAST = C.RTN_UNICAST
+ RTN_LOCAL = C.RTN_LOCAL
+ RTN_BROADCAST = C.RTN_BROADCAST
+ RTN_ANYCAST = C.RTN_ANYCAST
+ RTN_MULTICAST = C.RTN_MULTICAST
+ RTN_BLACKHOLE = C.RTN_BLACKHOLE
+ RTN_UNREACHABLE = C.RTN_UNREACHABLE
+ RTN_PROHIBIT = C.RTN_PROHIBIT
+ RTN_THROW = C.RTN_THROW
+ RTN_NAT = C.RTN_NAT
+ RTN_XRESOLVE = C.RTN_XRESOLVE
+ RTNLGRP_NONE = C.RTNLGRP_NONE
+ RTNLGRP_LINK = C.RTNLGRP_LINK
+ RTNLGRP_NOTIFY = C.RTNLGRP_NOTIFY
+ RTNLGRP_NEIGH = C.RTNLGRP_NEIGH
+ RTNLGRP_TC = C.RTNLGRP_TC
+ RTNLGRP_IPV4_IFADDR = C.RTNLGRP_IPV4_IFADDR
+ RTNLGRP_IPV4_MROUTE = C.RTNLGRP_IPV4_MROUTE
+ RTNLGRP_IPV4_ROUTE = C.RTNLGRP_IPV4_ROUTE
+ RTNLGRP_IPV4_RULE = C.RTNLGRP_IPV4_RULE
+ RTNLGRP_IPV6_IFADDR = C.RTNLGRP_IPV6_IFADDR
+ RTNLGRP_IPV6_MROUTE = C.RTNLGRP_IPV6_MROUTE
+ RTNLGRP_IPV6_ROUTE = C.RTNLGRP_IPV6_ROUTE
+ RTNLGRP_IPV6_IFINFO = C.RTNLGRP_IPV6_IFINFO
+ RTNLGRP_IPV6_PREFIX = C.RTNLGRP_IPV6_PREFIX
+ RTNLGRP_IPV6_RULE = C.RTNLGRP_IPV6_RULE
+ RTNLGRP_ND_USEROPT = C.RTNLGRP_ND_USEROPT
+ SizeofNlMsghdr = C.sizeof_struct_nlmsghdr
+ SizeofNlMsgerr = C.sizeof_struct_nlmsgerr
+ SizeofRtGenmsg = C.sizeof_struct_rtgenmsg
+ SizeofNlAttr = C.sizeof_struct_nlattr
+ SizeofRtAttr = C.sizeof_struct_rtattr
+ SizeofIfInfomsg = C.sizeof_struct_ifinfomsg
+ SizeofIfAddrmsg = C.sizeof_struct_ifaddrmsg
+ SizeofRtMsg = C.sizeof_struct_rtmsg
+ SizeofRtNexthop = C.sizeof_struct_rtnexthop
+)
+
+type NlMsghdr C.struct_nlmsghdr
+
+type NlMsgerr C.struct_nlmsgerr
+
+type RtGenmsg C.struct_rtgenmsg
+
+type NlAttr C.struct_nlattr
+
+type RtAttr C.struct_rtattr
+
+type IfInfomsg C.struct_ifinfomsg
+
+type IfAddrmsg C.struct_ifaddrmsg
+
+type RtMsg C.struct_rtmsg
+
+type RtNexthop C.struct_rtnexthop
+
+// Linux socket filter
+
+const (
+ SizeofSockFilter = C.sizeof_struct_sock_filter
+ SizeofSockFprog = C.sizeof_struct_sock_fprog
+)
+
+type SockFilter C.struct_sock_filter
+
+type SockFprog C.struct_sock_fprog
+
+// Inotify
+
+type InotifyEvent C.struct_inotify_event
+
+const SizeofInotifyEvent = C.sizeof_struct_inotify_event
+
+// Ptrace
+
+// Register structures
+type PtraceRegs C.PtraceRegs
+
+// Structures contained in PtraceRegs on s390x (exported by mkpost.go)
+type PtracePsw C.ptracePsw
+
+type PtraceFpregs C.ptraceFpregs
+
+type PtracePer C.ptracePer
+
+// Misc
+
+type FdSet C.fd_set
+
+type Sysinfo_t C.struct_sysinfo
+
+type Utsname C.struct_utsname
+
+type Ustat_t C.struct_ustat
+
+type EpollEvent C.struct_my_epoll_event
+
+const (
+ AT_FDCWD = C.AT_FDCWD
+ AT_REMOVEDIR = C.AT_REMOVEDIR
+ AT_SYMLINK_FOLLOW = C.AT_SYMLINK_FOLLOW
+ AT_SYMLINK_NOFOLLOW = C.AT_SYMLINK_NOFOLLOW
+)
+
+type PollFd C.struct_pollfd
+
+const (
+ POLLIN = C.POLLIN
+ POLLPRI = C.POLLPRI
+ POLLOUT = C.POLLOUT
+ POLLRDHUP = C.POLLRDHUP
+ POLLERR = C.POLLERR
+ POLLHUP = C.POLLHUP
+ POLLNVAL = C.POLLNVAL
+)
+
+type Sigset_t C.sigset_t
+
+const RNDGETENTCNT = C.RNDGETENTCNT
+
+// sysconf information
+
+const _SC_PAGESIZE = C._SC_PAGESIZE
+
+// Terminal handling
+
+type Termios C.termios_t
diff --git a/vendor/golang.org/x/sys/unix/mkall.sh b/vendor/golang.org/x/sys/unix/mkall.sh
new file mode 100755
index 0000000..f0d6566
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/mkall.sh
@@ -0,0 +1,179 @@
+#!/usr/bin/env bash
+# Copyright 2009 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+# This script runs or (given -n) prints suggested commands to generate files for
+# the Architecture/OS specified by the GOARCH and GOOS environment variables.
+# See README.md for more information about how the build system works.
+
+GOOSARCH="${GOOS}_${GOARCH}"
+
+# defaults
+mksyscall="./mksyscall.pl"
+mkerrors="./mkerrors.sh"
+zerrors="zerrors_$GOOSARCH.go"
+mksysctl=""
+zsysctl="zsysctl_$GOOSARCH.go"
+mksysnum=
+mktypes=
+run="sh"
+cmd=""
+
+case "$1" in
+-syscalls)
+ for i in zsyscall*go
+ do
+ # Run the command line that appears in the first line
+ # of the generated file to regenerate it.
+ sed 1q $i | sed 's;^// ;;' | sh > _$i && gofmt < _$i > $i
+ rm _$i
+ done
+ exit 0
+ ;;
+-n)
+ run="cat"
+ cmd="echo"
+ shift
+esac
+
+case "$#" in
+0)
+ ;;
+*)
+ echo 'usage: mkall.sh [-n]' 1>&2
+ exit 2
+esac
+
+if [[ "$GOOS" = "linux" ]] && [[ "$GOARCH" != "sparc64" ]]; then
+ # Use then new build system
+ # Files generated through docker (use $cmd so you can Ctl-C the build or run)
+ $cmd docker build --tag generate:$GOOS $GOOS
+ $cmd docker run --interactive --tty --volume $(dirname "$(readlink -f "$0")"):/build generate:$GOOS
+ exit
+fi
+
+GOOSARCH_in=syscall_$GOOSARCH.go
+case "$GOOSARCH" in
+_* | *_ | _)
+ echo 'undefined $GOOS_$GOARCH:' "$GOOSARCH" 1>&2
+ exit 1
+ ;;
+darwin_386)
+ mkerrors="$mkerrors -m32"
+ mksyscall="./mksyscall.pl -l32"
+ mksysnum="./mksysnum_darwin.pl $(xcrun --show-sdk-path --sdk macosx)/usr/include/sys/syscall.h"
+ mktypes="GOARCH=$GOARCH go tool cgo -godefs"
+ ;;
+darwin_amd64)
+ mkerrors="$mkerrors -m64"
+ mksysnum="./mksysnum_darwin.pl $(xcrun --show-sdk-path --sdk macosx)/usr/include/sys/syscall.h"
+ mktypes="GOARCH=$GOARCH go tool cgo -godefs"
+ ;;
+darwin_arm)
+ mkerrors="$mkerrors"
+ mksysnum="./mksysnum_darwin.pl /usr/include/sys/syscall.h"
+ mktypes="GOARCH=$GOARCH go tool cgo -godefs"
+ ;;
+darwin_arm64)
+ mkerrors="$mkerrors -m64"
+ mksysnum="./mksysnum_darwin.pl $(xcrun --show-sdk-path --sdk iphoneos)/usr/include/sys/syscall.h"
+ mktypes="GOARCH=$GOARCH go tool cgo -godefs"
+ ;;
+dragonfly_386)
+ mkerrors="$mkerrors -m32"
+ mksyscall="./mksyscall.pl -l32 -dragonfly"
+ mksysnum="curl -s 'http://gitweb.dragonflybsd.org/dragonfly.git/blob_plain/HEAD:/sys/kern/syscalls.master' | ./mksysnum_dragonfly.pl"
+ mktypes="GOARCH=$GOARCH go tool cgo -godefs"
+ ;;
+dragonfly_amd64)
+ mkerrors="$mkerrors -m64"
+ mksyscall="./mksyscall.pl -dragonfly"
+ mksysnum="curl -s 'http://gitweb.dragonflybsd.org/dragonfly.git/blob_plain/HEAD:/sys/kern/syscalls.master' | ./mksysnum_dragonfly.pl"
+ mktypes="GOARCH=$GOARCH go tool cgo -godefs"
+ ;;
+freebsd_386)
+ mkerrors="$mkerrors -m32"
+ mksyscall="./mksyscall.pl -l32"
+ mksysnum="curl -s 'http://svn.freebsd.org/base/stable/10/sys/kern/syscalls.master' | ./mksysnum_freebsd.pl"
+ mktypes="GOARCH=$GOARCH go tool cgo -godefs"
+ ;;
+freebsd_amd64)
+ mkerrors="$mkerrors -m64"
+ mksysnum="curl -s 'http://svn.freebsd.org/base/stable/10/sys/kern/syscalls.master' | ./mksysnum_freebsd.pl"
+ mktypes="GOARCH=$GOARCH go tool cgo -godefs"
+ ;;
+freebsd_arm)
+ mkerrors="$mkerrors"
+ mksyscall="./mksyscall.pl -l32 -arm"
+ mksysnum="curl -s 'http://svn.freebsd.org/base/stable/10/sys/kern/syscalls.master' | ./mksysnum_freebsd.pl"
+ # Let the type of C char be signed for making the bare syscall
+ # API consistent across over platforms.
+ mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char"
+ ;;
+linux_sparc64)
+ GOOSARCH_in=syscall_linux_sparc64.go
+ unistd_h=/usr/include/sparc64-linux-gnu/asm/unistd.h
+ mkerrors="$mkerrors -m64"
+ mksysnum="./mksysnum_linux.pl $unistd_h"
+ mktypes="GOARCH=$GOARCH go tool cgo -godefs"
+ ;;
+netbsd_386)
+ mkerrors="$mkerrors -m32"
+ mksyscall="./mksyscall.pl -l32 -netbsd"
+ mksysnum="curl -s 'http://cvsweb.netbsd.org/bsdweb.cgi/~checkout~/src/sys/kern/syscalls.master' | ./mksysnum_netbsd.pl"
+ mktypes="GOARCH=$GOARCH go tool cgo -godefs"
+ ;;
+netbsd_amd64)
+ mkerrors="$mkerrors -m64"
+ mksyscall="./mksyscall.pl -netbsd"
+ mksysnum="curl -s 'http://cvsweb.netbsd.org/bsdweb.cgi/~checkout~/src/sys/kern/syscalls.master' | ./mksysnum_netbsd.pl"
+ mktypes="GOARCH=$GOARCH go tool cgo -godefs"
+ ;;
+openbsd_386)
+ mkerrors="$mkerrors -m32"
+ mksyscall="./mksyscall.pl -l32 -openbsd"
+ mksysctl="./mksysctl_openbsd.pl"
+ zsysctl="zsysctl_openbsd.go"
+ mksysnum="curl -s 'http://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/src/sys/kern/syscalls.master' | ./mksysnum_openbsd.pl"
+ mktypes="GOARCH=$GOARCH go tool cgo -godefs"
+ ;;
+openbsd_amd64)
+ mkerrors="$mkerrors -m64"
+ mksyscall="./mksyscall.pl -openbsd"
+ mksysctl="./mksysctl_openbsd.pl"
+ zsysctl="zsysctl_openbsd.go"
+ mksysnum="curl -s 'http://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/src/sys/kern/syscalls.master' | ./mksysnum_openbsd.pl"
+ mktypes="GOARCH=$GOARCH go tool cgo -godefs"
+ ;;
+solaris_amd64)
+ mksyscall="./mksyscall_solaris.pl"
+ mkerrors="$mkerrors -m64"
+ mksysnum=
+ mktypes="GOARCH=$GOARCH go tool cgo -godefs"
+ ;;
+*)
+ echo 'unrecognized $GOOS_$GOARCH: ' "$GOOSARCH" 1>&2
+ exit 1
+ ;;
+esac
+
+(
+ if [ -n "$mkerrors" ]; then echo "$mkerrors |gofmt >$zerrors"; fi
+ case "$GOOS" in
+ *)
+ syscall_goos="syscall_$GOOS.go"
+ case "$GOOS" in
+ darwin | dragonfly | freebsd | netbsd | openbsd)
+ syscall_goos="syscall_bsd.go $syscall_goos"
+ ;;
+ esac
+ if [ -n "$mksyscall" ]; then echo "$mksyscall -tags $GOOS,$GOARCH $syscall_goos $GOOSARCH_in |gofmt >zsyscall_$GOOSARCH.go"; fi
+ ;;
+ esac
+ if [ -n "$mksysctl" ]; then echo "$mksysctl |gofmt >$zsysctl"; fi
+ if [ -n "$mksysnum" ]; then echo "$mksysnum |gofmt >zsysnum_$GOOSARCH.go"; fi
+ if [ -n "$mktypes" ]; then
+ echo "$mktypes types_$GOOS.go | go run mkpost.go > ztypes_$GOOSARCH.go";
+ fi
+) | $run
diff --git a/vendor/golang.org/x/sys/unix/mkerrors.sh b/vendor/golang.org/x/sys/unix/mkerrors.sh
new file mode 100755
index 0000000..d56eb43
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/mkerrors.sh
@@ -0,0 +1,549 @@
+#!/usr/bin/env bash
+# Copyright 2009 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+# Generate Go code listing errors and other #defined constant
+# values (ENAMETOOLONG etc.), by asking the preprocessor
+# about the definitions.
+
+unset LANG
+export LC_ALL=C
+export LC_CTYPE=C
+
+if test -z "$GOARCH" -o -z "$GOOS"; then
+ echo 1>&2 "GOARCH or GOOS not defined in environment"
+ exit 1
+fi
+
+# Check that we are using the new build system if we should
+if [[ "$GOOS" -eq "linux" ]] && [[ "$GOARCH" != "sparc64" ]]; then
+ if [[ "$GOLANG_SYS_BUILD" -ne "docker" ]]; then
+ echo 1>&2 "In the new build system, mkerrors should not be called directly."
+ echo 1>&2 "See README.md"
+ exit 1
+ fi
+fi
+
+CC=${CC:-cc}
+
+if [[ "$GOOS" -eq "solaris" ]]; then
+ # Assumes GNU versions of utilities in PATH.
+ export PATH=/usr/gnu/bin:$PATH
+fi
+
+uname=$(uname)
+
+includes_Darwin='
+#define _DARWIN_C_SOURCE
+#define KERNEL
+#define _DARWIN_USE_64_BIT_INODE
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+'
+
+includes_DragonFly='
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+'
+
+includes_FreeBSD='
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#if __FreeBSD__ >= 10
+#define IFT_CARP 0xf8 // IFT_CARP is deprecated in FreeBSD 10
+#undef SIOCAIFADDR
+#define SIOCAIFADDR _IOW(105, 26, struct oifaliasreq) // ifaliasreq contains if_data
+#undef SIOCSIFPHYADDR
+#define SIOCSIFPHYADDR _IOW(105, 70, struct oifaliasreq) // ifaliasreq contains if_data
+#endif
+'
+
+includes_Linux='
+#define _LARGEFILE_SOURCE
+#define _LARGEFILE64_SOURCE
+#ifndef __LP64__
+#define _FILE_OFFSET_BITS 64
+#endif
+#define _GNU_SOURCE
+
+// is broken on powerpc64, as it fails to include definitions of
+// these structures. We just include them copied from .
+#if defined(__powerpc__)
+struct sgttyb {
+ char sg_ispeed;
+ char sg_ospeed;
+ char sg_erase;
+ char sg_kill;
+ short sg_flags;
+};
+
+struct tchars {
+ char t_intrc;
+ char t_quitc;
+ char t_startc;
+ char t_stopc;
+ char t_eofc;
+ char t_brkc;
+};
+
+struct ltchars {
+ char t_suspc;
+ char t_dsuspc;
+ char t_rprntc;
+ char t_flushc;
+ char t_werasc;
+ char t_lnextc;
+};
+#endif
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#ifndef MSG_FASTOPEN
+#define MSG_FASTOPEN 0x20000000
+#endif
+
+#ifndef PTRACE_GETREGS
+#define PTRACE_GETREGS 0xc
+#endif
+
+#ifndef PTRACE_SETREGS
+#define PTRACE_SETREGS 0xd
+#endif
+
+#ifndef SOL_NETLINK
+#define SOL_NETLINK 270
+#endif
+
+#ifdef SOL_BLUETOOTH
+// SPARC includes this in /usr/include/sparc64-linux-gnu/bits/socket.h
+// but it is already in bluetooth_linux.go
+#undef SOL_BLUETOOTH
+#endif
+
+// Certain constants are missing from the fs/crypto UAPI
+#define FS_KEY_DESC_PREFIX "fscrypt:"
+#define FS_KEY_DESC_PREFIX_SIZE 8
+#define FS_MAX_KEY_SIZE 64
+'
+
+includes_NetBSD='
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+// Needed since refers to it...
+#define schedppq 1
+'
+
+includes_OpenBSD='
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+// We keep some constants not supported in OpenBSD 5.5 and beyond for
+// the promise of compatibility.
+#define EMUL_ENABLED 0x1
+#define EMUL_NATIVE 0x2
+#define IPV6_FAITH 0x1d
+#define IPV6_OPTIONS 0x1
+#define IPV6_RTHDR_STRICT 0x1
+#define IPV6_SOCKOPT_RESERVED1 0x3
+#define SIOCGIFGENERIC 0xc020693a
+#define SIOCSIFGENERIC 0x80206939
+#define WALTSIG 0x4
+'
+
+includes_SunOS='
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+'
+
+
+includes='
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+'
+ccflags="$@"
+
+# Write go tool cgo -godefs input.
+(
+ echo package unix
+ echo
+ echo '/*'
+ indirect="includes_$(uname)"
+ echo "${!indirect} $includes"
+ echo '*/'
+ echo 'import "C"'
+ echo 'import "syscall"'
+ echo
+ echo 'const ('
+
+ # The gcc command line prints all the #defines
+ # it encounters while processing the input
+ echo "${!indirect} $includes" | $CC -x c - -E -dM $ccflags |
+ awk '
+ $1 != "#define" || $2 ~ /\(/ || $3 == "" {next}
+
+ $2 ~ /^E([ABCD]X|[BIS]P|[SD]I|S|FL)$/ {next} # 386 registers
+ $2 ~ /^(SIGEV_|SIGSTKSZ|SIGRT(MIN|MAX))/ {next}
+ $2 ~ /^(SCM_SRCRT)$/ {next}
+ $2 ~ /^(MAP_FAILED)$/ {next}
+ $2 ~ /^ELF_.*$/ {next}# contains ELF_ARCH, etc.
+
+ $2 ~ /^EXTATTR_NAMESPACE_NAMES/ ||
+ $2 ~ /^EXTATTR_NAMESPACE_[A-Z]+_STRING/ {next}
+
+ $2 !~ /^ETH_/ &&
+ $2 !~ /^EPROC_/ &&
+ $2 !~ /^EQUIV_/ &&
+ $2 !~ /^EXPR_/ &&
+ $2 ~ /^E[A-Z0-9_]+$/ ||
+ $2 ~ /^B[0-9_]+$/ ||
+ $2 == "BOTHER" ||
+ $2 ~ /^CI?BAUD(EX)?$/ ||
+ $2 == "IBSHIFT" ||
+ $2 ~ /^V[A-Z0-9]+$/ ||
+ $2 ~ /^CS[A-Z0-9]/ ||
+ $2 ~ /^I(SIG|CANON|CRNL|UCLC|EXTEN|MAXBEL|STRIP|UTF8)$/ ||
+ $2 ~ /^IGN/ ||
+ $2 ~ /^IX(ON|ANY|OFF)$/ ||
+ $2 ~ /^IN(LCR|PCK)$/ ||
+ $2 ~ /(^FLU?SH)|(FLU?SH$)/ ||
+ $2 ~ /^C(LOCAL|READ|MSPAR|RTSCTS)$/ ||
+ $2 == "BRKINT" ||
+ $2 == "HUPCL" ||
+ $2 == "PENDIN" ||
+ $2 == "TOSTOP" ||
+ $2 == "XCASE" ||
+ $2 == "ALTWERASE" ||
+ $2 == "NOKERNINFO" ||
+ $2 ~ /^PAR/ ||
+ $2 ~ /^SIG[^_]/ ||
+ $2 ~ /^O[CNPFPL][A-Z]+[^_][A-Z]+$/ ||
+ $2 ~ /^(NL|CR|TAB|BS|VT|FF)DLY$/ ||
+ $2 ~ /^(NL|CR|TAB|BS|VT|FF)[0-9]$/ ||
+ $2 ~ /^O?XTABS$/ ||
+ $2 ~ /^TC[IO](ON|OFF)$/ ||
+ $2 ~ /^IN_/ ||
+ $2 ~ /^LOCK_(SH|EX|NB|UN)$/ ||
+ $2 ~ /^(AF|SOCK|SO|SOL|IPPROTO|IP|IPV6|ICMP6|TCP|EVFILT|NOTE|EV|SHUT|PROT|MAP|PACKET|MSG|SCM|MCL|DT|MADV|PR)_/ ||
+ $2 ~ /^FALLOC_/ ||
+ $2 == "ICMPV6_FILTER" ||
+ $2 == "SOMAXCONN" ||
+ $2 == "NAME_MAX" ||
+ $2 == "IFNAMSIZ" ||
+ $2 ~ /^CTL_(MAXNAME|NET|QUERY)$/ ||
+ $2 ~ /^SYSCTL_VERS/ ||
+ $2 ~ /^(MS|MNT)_/ ||
+ $2 ~ /^TUN(SET|GET|ATTACH|DETACH)/ ||
+ $2 ~ /^(O|F|E?FD|NAME|S|PTRACE|PT)_/ ||
+ $2 ~ /^LINUX_REBOOT_CMD_/ ||
+ $2 ~ /^LINUX_REBOOT_MAGIC[12]$/ ||
+ $2 !~ "NLA_TYPE_MASK" &&
+ $2 ~ /^(NETLINK|NLM|NLMSG|NLA|IFA|IFAN|RT|RTCF|RTN|RTPROT|RTNH|ARPHRD|ETH_P)_/ ||
+ $2 ~ /^SIOC/ ||
+ $2 ~ /^TIOC/ ||
+ $2 ~ /^TCGET/ ||
+ $2 ~ /^TCSET/ ||
+ $2 ~ /^TC(FLSH|SBRKP?|XONC)$/ ||
+ $2 !~ "RTF_BITS" &&
+ $2 ~ /^(IFF|IFT|NET_RT|RTM|RTF|RTV|RTA|RTAX)_/ ||
+ $2 ~ /^BIOC/ ||
+ $2 ~ /^RUSAGE_(SELF|CHILDREN|THREAD)/ ||
+ $2 ~ /^RLIMIT_(AS|CORE|CPU|DATA|FSIZE|LOCKS|MEMLOCK|MSGQUEUE|NICE|NOFILE|NPROC|RSS|RTPRIO|RTTIME|SIGPENDING|STACK)|RLIM_INFINITY/ ||
+ $2 ~ /^PRIO_(PROCESS|PGRP|USER)/ ||
+ $2 ~ /^CLONE_[A-Z_]+/ ||
+ $2 !~ /^(BPF_TIMEVAL)$/ &&
+ $2 ~ /^(BPF|DLT)_/ ||
+ $2 ~ /^CLOCK_/ ||
+ $2 ~ /^CAN_/ ||
+ $2 ~ /^ALG_/ ||
+ $2 ~ /^FS_(POLICY_FLAGS|KEY_DESC|ENCRYPTION_MODE|[A-Z0-9_]+_KEY_SIZE|IOC_(GET|SET)_ENCRYPTION)/ ||
+ $2 ~ /^GRND_/ ||
+ $2 ~ /^KEY_(SPEC|REQKEY_DEFL)_/ ||
+ $2 ~ /^KEYCTL_/ ||
+ $2 ~ /^SPLICE_/ ||
+ $2 ~ /^(VM|VMADDR)_/ ||
+ $2 !~ "WMESGLEN" &&
+ $2 ~ /^W[A-Z0-9]+$/ ||
+ $2 ~ /^BLK[A-Z]*(GET$|SET$|BUF$|PART$|SIZE)/ {printf("\t%s = C.%s\n", $2, $2)}
+ $2 ~ /^__WCOREFLAG$/ {next}
+ $2 ~ /^__W[A-Z0-9]+$/ {printf("\t%s = C.%s\n", substr($2,3), $2)}
+
+ {next}
+ ' | sort
+
+ echo ')'
+) >_const.go
+
+# Pull out the error names for later.
+errors=$(
+ echo '#include ' | $CC -x c - -E -dM $ccflags |
+ awk '$1=="#define" && $2 ~ /^E[A-Z0-9_]+$/ { print $2 }' |
+ sort
+)
+
+# Pull out the signal names for later.
+signals=$(
+ echo '#include ' | $CC -x c - -E -dM $ccflags |
+ awk '$1=="#define" && $2 ~ /^SIG[A-Z0-9]+$/ { print $2 }' |
+ egrep -v '(SIGSTKSIZE|SIGSTKSZ|SIGRT)' |
+ sort
+)
+
+# Again, writing regexps to a file.
+echo '#include ' | $CC -x c - -E -dM $ccflags |
+ awk '$1=="#define" && $2 ~ /^E[A-Z0-9_]+$/ { print "^\t" $2 "[ \t]*=" }' |
+ sort >_error.grep
+echo '#include ' | $CC -x c - -E -dM $ccflags |
+ awk '$1=="#define" && $2 ~ /^SIG[A-Z0-9]+$/ { print "^\t" $2 "[ \t]*=" }' |
+ egrep -v '(SIGSTKSIZE|SIGSTKSZ|SIGRT)' |
+ sort >_signal.grep
+
+echo '// mkerrors.sh' "$@"
+echo '// Code generated by the command above; see README.md. DO NOT EDIT.'
+echo
+echo "// +build ${GOARCH},${GOOS}"
+echo
+go tool cgo -godefs -- "$@" _const.go >_error.out
+cat _error.out | grep -vf _error.grep | grep -vf _signal.grep
+echo
+echo '// Errors'
+echo 'const ('
+cat _error.out | grep -f _error.grep | sed 's/=\(.*\)/= syscall.Errno(\1)/'
+echo ')'
+
+echo
+echo '// Signals'
+echo 'const ('
+cat _error.out | grep -f _signal.grep | sed 's/=\(.*\)/= syscall.Signal(\1)/'
+echo ')'
+
+# Run C program to print error and syscall strings.
+(
+ echo -E "
+#include