├── .gitignore
├── Godeps
├── Godeps.json
├── Readme
└── _workspace
│ ├── .gitignore
│ └── src
│ ├── github.com
│ └── Sirupsen
│ │ └── logrus
│ │ ├── .gitignore
│ │ ├── .travis.yml
│ │ ├── LICENSE
│ │ ├── README.md
│ │ ├── entry.go
│ │ ├── entry_test.go
│ │ ├── examples
│ │ ├── basic
│ │ │ └── basic.go
│ │ └── hook
│ │ │ └── hook.go
│ │ ├── exported.go
│ │ ├── formatter.go
│ │ ├── formatter_bench_test.go
│ │ ├── hook_test.go
│ │ ├── hooks.go
│ │ ├── hooks
│ │ ├── airbrake
│ │ │ ├── airbrake.go
│ │ │ └── airbrake_test.go
│ │ ├── papertrail
│ │ │ ├── README.md
│ │ │ ├── papertrail.go
│ │ │ └── papertrail_test.go
│ │ ├── sentry
│ │ │ ├── README.md
│ │ │ ├── sentry.go
│ │ │ └── sentry_test.go
│ │ └── syslog
│ │ │ ├── README.md
│ │ │ ├── syslog.go
│ │ │ └── syslog_test.go
│ │ ├── json_formatter.go
│ │ ├── json_formatter_test.go
│ │ ├── logger.go
│ │ ├── logrus.go
│ │ ├── logrus_test.go
│ │ ├── terminal_darwin.go
│ │ ├── terminal_freebsd.go
│ │ ├── terminal_linux.go
│ │ ├── terminal_notwindows.go
│ │ ├── terminal_openbsd.go
│ │ ├── terminal_windows.go
│ │ ├── text_formatter.go
│ │ ├── text_formatter_test.go
│ │ └── writer.go
│ └── golang.org
│ └── x
│ └── crypto
│ └── ssh
│ ├── agent
│ ├── client.go
│ ├── client_test.go
│ ├── forward.go
│ ├── keyring.go
│ ├── server.go
│ ├── server_test.go
│ └── testdata_test.go
│ ├── benchmark_test.go
│ ├── buffer.go
│ ├── buffer_test.go
│ ├── certs.go
│ ├── certs_test.go
│ ├── channel.go
│ ├── cipher.go
│ ├── cipher_test.go
│ ├── client.go
│ ├── client_auth.go
│ ├── client_auth_test.go
│ ├── client_test.go
│ ├── common.go
│ ├── connection.go
│ ├── doc.go
│ ├── example_test.go
│ ├── handshake.go
│ ├── handshake_test.go
│ ├── kex.go
│ ├── kex_test.go
│ ├── keys.go
│ ├── keys_test.go
│ ├── mac.go
│ ├── mempipe_test.go
│ ├── messages.go
│ ├── messages_test.go
│ ├── mux.go
│ ├── mux_test.go
│ ├── server.go
│ ├── session.go
│ ├── session_test.go
│ ├── tcpip.go
│ ├── tcpip_test.go
│ ├── terminal
│ ├── terminal.go
│ ├── terminal_test.go
│ ├── util.go
│ ├── util_bsd.go
│ ├── util_linux.go
│ └── util_windows.go
│ ├── test
│ ├── agent_unix_test.go
│ ├── cert_test.go
│ ├── doc.go
│ ├── forward_unix_test.go
│ ├── session_test.go
│ ├── tcpip_test.go
│ ├── test_unix_test.go
│ └── testdata_test.go
│ ├── testdata
│ ├── doc.go
│ └── keys.go
│ ├── testdata_test.go
│ ├── transport.go
│ └── transport_test.go
├── LICENSE
├── README.md
├── blacklist.go
├── blacklist
├── dsa-1024
├── rsa-1023
├── rsa-1024
├── rsa-2047
├── rsa-2048
├── rsa-4096
└── rsa-8192
├── key.go
├── main.go
└── server.go
/.gitignore:
--------------------------------------------------------------------------------
1 | checkmysshkey
2 |
--------------------------------------------------------------------------------
/Godeps/Godeps.json:
--------------------------------------------------------------------------------
1 | {
2 | "ImportPath": "github.com/mattbostock/sshkeycheck",
3 | "GoVersion": "go1.4.2",
4 | "Deps": [
5 | {
6 | "ImportPath": "github.com/Sirupsen/logrus",
7 | "Comment": "v0.6.6-5-gecc16b3",
8 | "Rev": "ecc16b3b2a583f3d5308ed4a3a4ce5cf45dbc68b"
9 | },
10 | {
11 | "ImportPath": "golang.org/x/crypto/ssh",
12 | "Rev": "1351f936d976c60a0a48d728281922cf63eafb8d"
13 | }
14 | ]
15 | }
16 |
--------------------------------------------------------------------------------
/Godeps/Readme:
--------------------------------------------------------------------------------
1 | This directory tree is generated automatically by godep.
2 |
3 | Please do not edit.
4 |
5 | See https://github.com/tools/godep for more information.
6 |
--------------------------------------------------------------------------------
/Godeps/_workspace/.gitignore:
--------------------------------------------------------------------------------
1 | /pkg
2 | /bin
3 |
--------------------------------------------------------------------------------
/Godeps/_workspace/src/github.com/Sirupsen/logrus/.gitignore:
--------------------------------------------------------------------------------
1 | logrus
2 |
--------------------------------------------------------------------------------
/Godeps/_workspace/src/github.com/Sirupsen/logrus/.travis.yml:
--------------------------------------------------------------------------------
1 | language: go
2 | go:
3 | - 1.2
4 | - 1.3
5 | - 1.4
6 | - tip
7 | install:
8 | - go get -t ./...
9 |
--------------------------------------------------------------------------------
/Godeps/_workspace/src/github.com/Sirupsen/logrus/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014 Simon Eskildsen
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Godeps/_workspace/src/github.com/Sirupsen/logrus/entry.go:
--------------------------------------------------------------------------------
1 | package logrus
2 |
3 | import (
4 | "bytes"
5 | "fmt"
6 | "io"
7 | "os"
8 | "time"
9 | )
10 |
11 | // An entry is the final or intermediate Logrus logging entry. It contains all
12 | // the fields passed with WithField{,s}. It's finally logged when Debug, Info,
13 | // Warn, Error, Fatal or Panic is called on it. These objects can be reused and
14 | // passed around as much as you wish to avoid field duplication.
15 | type Entry struct {
16 | Logger *Logger
17 |
18 | // Contains all the fields set by the user.
19 | Data Fields
20 |
21 | // Time at which the log entry was created
22 | Time time.Time
23 |
24 | // Level the log entry was logged at: Debug, Info, Warn, Error, Fatal or Panic
25 | Level Level
26 |
27 | // Message passed to Debug, Info, Warn, Error, Fatal or Panic
28 | Message string
29 | }
30 |
31 | func NewEntry(logger *Logger) *Entry {
32 | return &Entry{
33 | Logger: logger,
34 | // Default is three fields, give a little extra room
35 | Data: make(Fields, 5),
36 | }
37 | }
38 |
39 | // Returns a reader for the entry, which is a proxy to the formatter.
40 | func (entry *Entry) Reader() (*bytes.Buffer, error) {
41 | serialized, err := entry.Logger.Formatter.Format(entry)
42 | return bytes.NewBuffer(serialized), err
43 | }
44 |
45 | // Returns the string representation from the reader and ultimately the
46 | // formatter.
47 | func (entry *Entry) String() (string, error) {
48 | reader, err := entry.Reader()
49 | if err != nil {
50 | return "", err
51 | }
52 |
53 | return reader.String(), err
54 | }
55 |
56 | // Add a single field to the Entry.
57 | func (entry *Entry) WithField(key string, value interface{}) *Entry {
58 | return entry.WithFields(Fields{key: value})
59 | }
60 |
61 | // Add a map of fields to the Entry.
62 | func (entry *Entry) WithFields(fields Fields) *Entry {
63 | data := Fields{}
64 | for k, v := range entry.Data {
65 | data[k] = v
66 | }
67 | for k, v := range fields {
68 | data[k] = v
69 | }
70 | return &Entry{Logger: entry.Logger, Data: data}
71 | }
72 |
73 | func (entry *Entry) log(level Level, msg string) {
74 | entry.Time = time.Now()
75 | entry.Level = level
76 | entry.Message = msg
77 |
78 | if err := entry.Logger.Hooks.Fire(level, entry); err != nil {
79 | entry.Logger.mu.Lock()
80 | fmt.Fprintf(os.Stderr, "Failed to fire hook: %v\n", err)
81 | entry.Logger.mu.Unlock()
82 | }
83 |
84 | reader, err := entry.Reader()
85 | if err != nil {
86 | entry.Logger.mu.Lock()
87 | fmt.Fprintf(os.Stderr, "Failed to obtain reader, %v\n", err)
88 | entry.Logger.mu.Unlock()
89 | }
90 |
91 | entry.Logger.mu.Lock()
92 | defer entry.Logger.mu.Unlock()
93 |
94 | _, err = io.Copy(entry.Logger.Out, reader)
95 | if err != nil {
96 | fmt.Fprintf(os.Stderr, "Failed to write to log, %v\n", err)
97 | }
98 |
99 | // To avoid Entry#log() returning a value that only would make sense for
100 | // panic() to use in Entry#Panic(), we avoid the allocation by checking
101 | // directly here.
102 | if level <= PanicLevel {
103 | panic(entry)
104 | }
105 | }
106 |
107 | func (entry *Entry) Debug(args ...interface{}) {
108 | if entry.Logger.Level >= DebugLevel {
109 | entry.log(DebugLevel, fmt.Sprint(args...))
110 | }
111 | }
112 |
113 | func (entry *Entry) Print(args ...interface{}) {
114 | entry.Info(args...)
115 | }
116 |
117 | func (entry *Entry) Info(args ...interface{}) {
118 | if entry.Logger.Level >= InfoLevel {
119 | entry.log(InfoLevel, fmt.Sprint(args...))
120 | }
121 | }
122 |
123 | func (entry *Entry) Warn(args ...interface{}) {
124 | if entry.Logger.Level >= WarnLevel {
125 | entry.log(WarnLevel, fmt.Sprint(args...))
126 | }
127 | }
128 |
129 | func (entry *Entry) Warning(args ...interface{}) {
130 | entry.Warn(args...)
131 | }
132 |
133 | func (entry *Entry) Error(args ...interface{}) {
134 | if entry.Logger.Level >= ErrorLevel {
135 | entry.log(ErrorLevel, fmt.Sprint(args...))
136 | }
137 | }
138 |
139 | func (entry *Entry) Fatal(args ...interface{}) {
140 | if entry.Logger.Level >= FatalLevel {
141 | entry.log(FatalLevel, fmt.Sprint(args...))
142 | }
143 | os.Exit(1)
144 | }
145 |
146 | func (entry *Entry) Panic(args ...interface{}) {
147 | if entry.Logger.Level >= PanicLevel {
148 | entry.log(PanicLevel, fmt.Sprint(args...))
149 | }
150 | panic(fmt.Sprint(args...))
151 | }
152 |
153 | // Entry Printf family functions
154 |
155 | func (entry *Entry) Debugf(format string, args ...interface{}) {
156 | if entry.Logger.Level >= DebugLevel {
157 | entry.Debug(fmt.Sprintf(format, args...))
158 | }
159 | }
160 |
161 | func (entry *Entry) Infof(format string, args ...interface{}) {
162 | if entry.Logger.Level >= InfoLevel {
163 | entry.Info(fmt.Sprintf(format, args...))
164 | }
165 | }
166 |
167 | func (entry *Entry) Printf(format string, args ...interface{}) {
168 | entry.Infof(format, args...)
169 | }
170 |
171 | func (entry *Entry) Warnf(format string, args ...interface{}) {
172 | if entry.Logger.Level >= WarnLevel {
173 | entry.Warn(fmt.Sprintf(format, args...))
174 | }
175 | }
176 |
177 | func (entry *Entry) Warningf(format string, args ...interface{}) {
178 | entry.Warnf(format, args...)
179 | }
180 |
181 | func (entry *Entry) Errorf(format string, args ...interface{}) {
182 | if entry.Logger.Level >= ErrorLevel {
183 | entry.Error(fmt.Sprintf(format, args...))
184 | }
185 | }
186 |
187 | func (entry *Entry) Fatalf(format string, args ...interface{}) {
188 | if entry.Logger.Level >= FatalLevel {
189 | entry.Fatal(fmt.Sprintf(format, args...))
190 | }
191 | }
192 |
193 | func (entry *Entry) Panicf(format string, args ...interface{}) {
194 | if entry.Logger.Level >= PanicLevel {
195 | entry.Panic(fmt.Sprintf(format, args...))
196 | }
197 | }
198 |
199 | // Entry Println family functions
200 |
201 | func (entry *Entry) Debugln(args ...interface{}) {
202 | if entry.Logger.Level >= DebugLevel {
203 | entry.Debug(entry.sprintlnn(args...))
204 | }
205 | }
206 |
207 | func (entry *Entry) Infoln(args ...interface{}) {
208 | if entry.Logger.Level >= InfoLevel {
209 | entry.Info(entry.sprintlnn(args...))
210 | }
211 | }
212 |
213 | func (entry *Entry) Println(args ...interface{}) {
214 | entry.Infoln(args...)
215 | }
216 |
217 | func (entry *Entry) Warnln(args ...interface{}) {
218 | if entry.Logger.Level >= WarnLevel {
219 | entry.Warn(entry.sprintlnn(args...))
220 | }
221 | }
222 |
223 | func (entry *Entry) Warningln(args ...interface{}) {
224 | entry.Warnln(args...)
225 | }
226 |
227 | func (entry *Entry) Errorln(args ...interface{}) {
228 | if entry.Logger.Level >= ErrorLevel {
229 | entry.Error(entry.sprintlnn(args...))
230 | }
231 | }
232 |
233 | func (entry *Entry) Fatalln(args ...interface{}) {
234 | if entry.Logger.Level >= FatalLevel {
235 | entry.Fatal(entry.sprintlnn(args...))
236 | }
237 | }
238 |
239 | func (entry *Entry) Panicln(args ...interface{}) {
240 | if entry.Logger.Level >= PanicLevel {
241 | entry.Panic(entry.sprintlnn(args...))
242 | }
243 | }
244 |
245 | // Sprintlnn => Sprint no newline. This is to get the behavior of how
246 | // fmt.Sprintln where spaces are always added between operands, regardless of
247 | // their type. Instead of vendoring the Sprintln implementation to spare a
248 | // string allocation, we do the simplest thing.
249 | func (entry *Entry) sprintlnn(args ...interface{}) string {
250 | msg := fmt.Sprintln(args...)
251 | return msg[:len(msg)-1]
252 | }
253 |
--------------------------------------------------------------------------------
/Godeps/_workspace/src/github.com/Sirupsen/logrus/entry_test.go:
--------------------------------------------------------------------------------
1 | package logrus
2 |
3 | import (
4 | "bytes"
5 | "fmt"
6 | "testing"
7 |
8 | "github.com/stretchr/testify/assert"
9 | )
10 |
11 | func TestEntryPanicln(t *testing.T) {
12 | errBoom := fmt.Errorf("boom time")
13 |
14 | defer func() {
15 | p := recover()
16 | assert.NotNil(t, p)
17 |
18 | switch pVal := p.(type) {
19 | case *Entry:
20 | assert.Equal(t, "kaboom", pVal.Message)
21 | assert.Equal(t, errBoom, pVal.Data["err"])
22 | default:
23 | t.Fatalf("want type *Entry, got %T: %#v", pVal, pVal)
24 | }
25 | }()
26 |
27 | logger := New()
28 | logger.Out = &bytes.Buffer{}
29 | entry := NewEntry(logger)
30 | entry.WithField("err", errBoom).Panicln("kaboom")
31 | }
32 |
33 | func TestEntryPanicf(t *testing.T) {
34 | errBoom := fmt.Errorf("boom again")
35 |
36 | defer func() {
37 | p := recover()
38 | assert.NotNil(t, p)
39 |
40 | switch pVal := p.(type) {
41 | case *Entry:
42 | assert.Equal(t, "kaboom true", pVal.Message)
43 | assert.Equal(t, errBoom, pVal.Data["err"])
44 | default:
45 | t.Fatalf("want type *Entry, got %T: %#v", pVal, pVal)
46 | }
47 | }()
48 |
49 | logger := New()
50 | logger.Out = &bytes.Buffer{}
51 | entry := NewEntry(logger)
52 | entry.WithField("err", errBoom).Panicf("kaboom %v", true)
53 | }
54 |
--------------------------------------------------------------------------------
/Godeps/_workspace/src/github.com/Sirupsen/logrus/examples/basic/basic.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "github.com/Sirupsen/logrus"
5 | )
6 |
7 | var log = logrus.New()
8 |
9 | func init() {
10 | log.Formatter = new(logrus.JSONFormatter)
11 | log.Formatter = new(logrus.TextFormatter) // default
12 | log.Level = logrus.DebugLevel
13 | }
14 |
15 | func main() {
16 | defer func() {
17 | err := recover()
18 | if err != nil {
19 | log.WithFields(logrus.Fields{
20 | "omg": true,
21 | "err": err,
22 | "number": 100,
23 | }).Fatal("The ice breaks!")
24 | }
25 | }()
26 |
27 | log.WithFields(logrus.Fields{
28 | "animal": "walrus",
29 | "number": 8,
30 | }).Debug("Started observing beach")
31 |
32 | log.WithFields(logrus.Fields{
33 | "animal": "walrus",
34 | "size": 10,
35 | }).Info("A group of walrus emerges from the ocean")
36 |
37 | log.WithFields(logrus.Fields{
38 | "omg": true,
39 | "number": 122,
40 | }).Warn("The group's number increased tremendously!")
41 |
42 | log.WithFields(logrus.Fields{
43 | "temperature": -4,
44 | }).Debug("Temperature changes")
45 |
46 | log.WithFields(logrus.Fields{
47 | "animal": "orca",
48 | "size": 9009,
49 | }).Panic("It's over 9000!")
50 | }
51 |
--------------------------------------------------------------------------------
/Godeps/_workspace/src/github.com/Sirupsen/logrus/examples/hook/hook.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "github.com/Sirupsen/logrus"
5 | "github.com/Sirupsen/logrus/hooks/airbrake"
6 | )
7 |
8 | var log = logrus.New()
9 |
10 | func init() {
11 | log.Formatter = new(logrus.TextFormatter) // default
12 | log.Hooks.Add(airbrake.NewHook("https://example.com", "xyz", "development"))
13 | }
14 |
15 | func main() {
16 | log.WithFields(logrus.Fields{
17 | "animal": "walrus",
18 | "size": 10,
19 | }).Info("A group of walrus emerges from the ocean")
20 |
21 | log.WithFields(logrus.Fields{
22 | "omg": true,
23 | "number": 122,
24 | }).Warn("The group's number increased tremendously!")
25 |
26 | log.WithFields(logrus.Fields{
27 | "omg": true,
28 | "number": 100,
29 | }).Fatal("The ice breaks!")
30 | }
31 |
--------------------------------------------------------------------------------
/Godeps/_workspace/src/github.com/Sirupsen/logrus/exported.go:
--------------------------------------------------------------------------------
1 | package logrus
2 |
3 | import (
4 | "io"
5 | )
6 |
7 | var (
8 | // std is the name of the standard logger in stdlib `log`
9 | std = New()
10 | )
11 |
12 | func StandardLogger() *Logger {
13 | return std
14 | }
15 |
16 | // SetOutput sets the standard logger output.
17 | func SetOutput(out io.Writer) {
18 | std.mu.Lock()
19 | defer std.mu.Unlock()
20 | std.Out = out
21 | }
22 |
23 | // SetFormatter sets the standard logger formatter.
24 | func SetFormatter(formatter Formatter) {
25 | std.mu.Lock()
26 | defer std.mu.Unlock()
27 | std.Formatter = formatter
28 | }
29 |
30 | // SetLevel sets the standard logger level.
31 | func SetLevel(level Level) {
32 | std.mu.Lock()
33 | defer std.mu.Unlock()
34 | std.Level = level
35 | }
36 |
37 | // GetLevel returns the standard logger level.
38 | func GetLevel() Level {
39 | std.mu.Lock()
40 | defer std.mu.Unlock()
41 | return std.Level
42 | }
43 |
44 | // AddHook adds a hook to the standard logger hooks.
45 | func AddHook(hook Hook) {
46 | std.mu.Lock()
47 | defer std.mu.Unlock()
48 | std.Hooks.Add(hook)
49 | }
50 |
51 | // WithField creates an entry from the standard logger and adds a field to
52 | // it. If you want multiple fields, use `WithFields`.
53 | //
54 | // Note that it doesn't log until you call Debug, Print, Info, Warn, Fatal
55 | // or Panic on the Entry it returns.
56 | func WithField(key string, value interface{}) *Entry {
57 | return std.WithField(key, value)
58 | }
59 |
60 | // WithFields creates an entry from the standard logger and adds multiple
61 | // fields to it. This is simply a helper for `WithField`, invoking it
62 | // once for each field.
63 | //
64 | // Note that it doesn't log until you call Debug, Print, Info, Warn, Fatal
65 | // or Panic on the Entry it returns.
66 | func WithFields(fields Fields) *Entry {
67 | return std.WithFields(fields)
68 | }
69 |
70 | // Debug logs a message at level Debug on the standard logger.
71 | func Debug(args ...interface{}) {
72 | std.Debug(args...)
73 | }
74 |
75 | // Print logs a message at level Info on the standard logger.
76 | func Print(args ...interface{}) {
77 | std.Print(args...)
78 | }
79 |
80 | // Info logs a message at level Info on the standard logger.
81 | func Info(args ...interface{}) {
82 | std.Info(args...)
83 | }
84 |
85 | // Warn logs a message at level Warn on the standard logger.
86 | func Warn(args ...interface{}) {
87 | std.Warn(args...)
88 | }
89 |
90 | // Warning logs a message at level Warn on the standard logger.
91 | func Warning(args ...interface{}) {
92 | std.Warning(args...)
93 | }
94 |
95 | // Error logs a message at level Error on the standard logger.
96 | func Error(args ...interface{}) {
97 | std.Error(args...)
98 | }
99 |
100 | // Panic logs a message at level Panic on the standard logger.
101 | func Panic(args ...interface{}) {
102 | std.Panic(args...)
103 | }
104 |
105 | // Fatal logs a message at level Fatal on the standard logger.
106 | func Fatal(args ...interface{}) {
107 | std.Fatal(args...)
108 | }
109 |
110 | // Debugf logs a message at level Debug on the standard logger.
111 | func Debugf(format string, args ...interface{}) {
112 | std.Debugf(format, args...)
113 | }
114 |
115 | // Printf logs a message at level Info on the standard logger.
116 | func Printf(format string, args ...interface{}) {
117 | std.Printf(format, args...)
118 | }
119 |
120 | // Infof logs a message at level Info on the standard logger.
121 | func Infof(format string, args ...interface{}) {
122 | std.Infof(format, args...)
123 | }
124 |
125 | // Warnf logs a message at level Warn on the standard logger.
126 | func Warnf(format string, args ...interface{}) {
127 | std.Warnf(format, args...)
128 | }
129 |
130 | // Warningf logs a message at level Warn on the standard logger.
131 | func Warningf(format string, args ...interface{}) {
132 | std.Warningf(format, args...)
133 | }
134 |
135 | // Errorf logs a message at level Error on the standard logger.
136 | func Errorf(format string, args ...interface{}) {
137 | std.Errorf(format, args...)
138 | }
139 |
140 | // Panicf logs a message at level Panic on the standard logger.
141 | func Panicf(format string, args ...interface{}) {
142 | std.Panicf(format, args...)
143 | }
144 |
145 | // Fatalf logs a message at level Fatal on the standard logger.
146 | func Fatalf(format string, args ...interface{}) {
147 | std.Fatalf(format, args...)
148 | }
149 |
150 | // Debugln logs a message at level Debug on the standard logger.
151 | func Debugln(args ...interface{}) {
152 | std.Debugln(args...)
153 | }
154 |
155 | // Println logs a message at level Info on the standard logger.
156 | func Println(args ...interface{}) {
157 | std.Println(args...)
158 | }
159 |
160 | // Infoln logs a message at level Info on the standard logger.
161 | func Infoln(args ...interface{}) {
162 | std.Infoln(args...)
163 | }
164 |
165 | // Warnln logs a message at level Warn on the standard logger.
166 | func Warnln(args ...interface{}) {
167 | std.Warnln(args...)
168 | }
169 |
170 | // Warningln logs a message at level Warn on the standard logger.
171 | func Warningln(args ...interface{}) {
172 | std.Warningln(args...)
173 | }
174 |
175 | // Errorln logs a message at level Error on the standard logger.
176 | func Errorln(args ...interface{}) {
177 | std.Errorln(args...)
178 | }
179 |
180 | // Panicln logs a message at level Panic on the standard logger.
181 | func Panicln(args ...interface{}) {
182 | std.Panicln(args...)
183 | }
184 |
185 | // Fatalln logs a message at level Fatal on the standard logger.
186 | func Fatalln(args ...interface{}) {
187 | std.Fatalln(args...)
188 | }
189 |
--------------------------------------------------------------------------------
/Godeps/_workspace/src/github.com/Sirupsen/logrus/formatter.go:
--------------------------------------------------------------------------------
1 | package logrus
2 |
3 | // The Formatter interface is used to implement a custom Formatter. It takes an
4 | // `Entry`. It exposes all the fields, including the default ones:
5 | //
6 | // * `entry.Data["msg"]`. The message passed from Info, Warn, Error ..
7 | // * `entry.Data["time"]`. The timestamp.
8 | // * `entry.Data["level"]. The level the entry was logged at.
9 | //
10 | // Any additional fields added with `WithField` or `WithFields` are also in
11 | // `entry.Data`. Format is expected to return an array of bytes which are then
12 | // logged to `logger.Out`.
13 | type Formatter interface {
14 | Format(*Entry) ([]byte, error)
15 | }
16 |
17 | // This is to not silently overwrite `time`, `msg` and `level` fields when
18 | // dumping it. If this code wasn't there doing:
19 | //
20 | // logrus.WithField("level", 1).Info("hello")
21 | //
22 | // Would just silently drop the user provided level. Instead with this code
23 | // it'll logged as:
24 | //
25 | // {"level": "info", "fields.level": 1, "msg": "hello", "time": "..."}
26 | //
27 | // It's not exported because it's still using Data in an opinionated way. It's to
28 | // avoid code duplication between the two default formatters.
29 | func prefixFieldClashes(data Fields) {
30 | _, ok := data["time"]
31 | if ok {
32 | data["fields.time"] = data["time"]
33 | }
34 |
35 | _, ok = data["msg"]
36 | if ok {
37 | data["fields.msg"] = data["msg"]
38 | }
39 |
40 | _, ok = data["level"]
41 | if ok {
42 | data["fields.level"] = data["level"]
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/Godeps/_workspace/src/github.com/Sirupsen/logrus/formatter_bench_test.go:
--------------------------------------------------------------------------------
1 | package logrus
2 |
3 | import (
4 | "testing"
5 | "time"
6 | )
7 |
8 | // smallFields is a small size data set for benchmarking
9 | var smallFields = Fields{
10 | "foo": "bar",
11 | "baz": "qux",
12 | "one": "two",
13 | "three": "four",
14 | }
15 |
16 | // largeFields is a large size data set for benchmarking
17 | var largeFields = Fields{
18 | "foo": "bar",
19 | "baz": "qux",
20 | "one": "two",
21 | "three": "four",
22 | "five": "six",
23 | "seven": "eight",
24 | "nine": "ten",
25 | "eleven": "twelve",
26 | "thirteen": "fourteen",
27 | "fifteen": "sixteen",
28 | "seventeen": "eighteen",
29 | "nineteen": "twenty",
30 | "a": "b",
31 | "c": "d",
32 | "e": "f",
33 | "g": "h",
34 | "i": "j",
35 | "k": "l",
36 | "m": "n",
37 | "o": "p",
38 | "q": "r",
39 | "s": "t",
40 | "u": "v",
41 | "w": "x",
42 | "y": "z",
43 | "this": "will",
44 | "make": "thirty",
45 | "entries": "yeah",
46 | }
47 |
48 | func BenchmarkSmallTextFormatter(b *testing.B) {
49 | doBenchmark(b, &TextFormatter{DisableColors: true}, smallFields)
50 | }
51 |
52 | func BenchmarkLargeTextFormatter(b *testing.B) {
53 | doBenchmark(b, &TextFormatter{DisableColors: true}, largeFields)
54 | }
55 |
56 | func BenchmarkSmallColoredTextFormatter(b *testing.B) {
57 | doBenchmark(b, &TextFormatter{ForceColors: true}, smallFields)
58 | }
59 |
60 | func BenchmarkLargeColoredTextFormatter(b *testing.B) {
61 | doBenchmark(b, &TextFormatter{ForceColors: true}, largeFields)
62 | }
63 |
64 | func BenchmarkSmallJSONFormatter(b *testing.B) {
65 | doBenchmark(b, &JSONFormatter{}, smallFields)
66 | }
67 |
68 | func BenchmarkLargeJSONFormatter(b *testing.B) {
69 | doBenchmark(b, &JSONFormatter{}, largeFields)
70 | }
71 |
72 | func doBenchmark(b *testing.B, formatter Formatter, fields Fields) {
73 | entry := &Entry{
74 | Time: time.Time{},
75 | Level: InfoLevel,
76 | Message: "message",
77 | Data: fields,
78 | }
79 | var d []byte
80 | var err error
81 | for i := 0; i < b.N; i++ {
82 | d, err = formatter.Format(entry)
83 | if err != nil {
84 | b.Fatal(err)
85 | }
86 | b.SetBytes(int64(len(d)))
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/Godeps/_workspace/src/github.com/Sirupsen/logrus/hook_test.go:
--------------------------------------------------------------------------------
1 | package logrus
2 |
3 | import (
4 | "testing"
5 |
6 | "github.com/stretchr/testify/assert"
7 | )
8 |
9 | type TestHook struct {
10 | Fired bool
11 | }
12 |
13 | func (hook *TestHook) Fire(entry *Entry) error {
14 | hook.Fired = true
15 | return nil
16 | }
17 |
18 | func (hook *TestHook) Levels() []Level {
19 | return []Level{
20 | DebugLevel,
21 | InfoLevel,
22 | WarnLevel,
23 | ErrorLevel,
24 | FatalLevel,
25 | PanicLevel,
26 | }
27 | }
28 |
29 | func TestHookFires(t *testing.T) {
30 | hook := new(TestHook)
31 |
32 | LogAndAssertJSON(t, func(log *Logger) {
33 | log.Hooks.Add(hook)
34 | assert.Equal(t, hook.Fired, false)
35 |
36 | log.Print("test")
37 | }, func(fields Fields) {
38 | assert.Equal(t, hook.Fired, true)
39 | })
40 | }
41 |
42 | type ModifyHook struct {
43 | }
44 |
45 | func (hook *ModifyHook) Fire(entry *Entry) error {
46 | entry.Data["wow"] = "whale"
47 | return nil
48 | }
49 |
50 | func (hook *ModifyHook) Levels() []Level {
51 | return []Level{
52 | DebugLevel,
53 | InfoLevel,
54 | WarnLevel,
55 | ErrorLevel,
56 | FatalLevel,
57 | PanicLevel,
58 | }
59 | }
60 |
61 | func TestHookCanModifyEntry(t *testing.T) {
62 | hook := new(ModifyHook)
63 |
64 | LogAndAssertJSON(t, func(log *Logger) {
65 | log.Hooks.Add(hook)
66 | log.WithField("wow", "elephant").Print("test")
67 | }, func(fields Fields) {
68 | assert.Equal(t, fields["wow"], "whale")
69 | })
70 | }
71 |
72 | func TestCanFireMultipleHooks(t *testing.T) {
73 | hook1 := new(ModifyHook)
74 | hook2 := new(TestHook)
75 |
76 | LogAndAssertJSON(t, func(log *Logger) {
77 | log.Hooks.Add(hook1)
78 | log.Hooks.Add(hook2)
79 |
80 | log.WithField("wow", "elephant").Print("test")
81 | }, func(fields Fields) {
82 | assert.Equal(t, fields["wow"], "whale")
83 | assert.Equal(t, hook2.Fired, true)
84 | })
85 | }
86 |
87 | type ErrorHook struct {
88 | Fired bool
89 | }
90 |
91 | func (hook *ErrorHook) Fire(entry *Entry) error {
92 | hook.Fired = true
93 | return nil
94 | }
95 |
96 | func (hook *ErrorHook) Levels() []Level {
97 | return []Level{
98 | ErrorLevel,
99 | }
100 | }
101 |
102 | func TestErrorHookShouldntFireOnInfo(t *testing.T) {
103 | hook := new(ErrorHook)
104 |
105 | LogAndAssertJSON(t, func(log *Logger) {
106 | log.Hooks.Add(hook)
107 | log.Info("test")
108 | }, func(fields Fields) {
109 | assert.Equal(t, hook.Fired, false)
110 | })
111 | }
112 |
113 | func TestErrorHookShouldFireOnError(t *testing.T) {
114 | hook := new(ErrorHook)
115 |
116 | LogAndAssertJSON(t, func(log *Logger) {
117 | log.Hooks.Add(hook)
118 | log.Error("test")
119 | }, func(fields Fields) {
120 | assert.Equal(t, hook.Fired, true)
121 | })
122 | }
123 |
--------------------------------------------------------------------------------
/Godeps/_workspace/src/github.com/Sirupsen/logrus/hooks.go:
--------------------------------------------------------------------------------
1 | package logrus
2 |
3 | // A hook to be fired when logging on the logging levels returned from
4 | // `Levels()` on your implementation of the interface. Note that this is not
5 | // fired in a goroutine or a channel with workers, you should handle such
6 | // functionality yourself if your call is non-blocking and you don't wish for
7 | // the logging calls for levels returned from `Levels()` to block.
8 | type Hook interface {
9 | Levels() []Level
10 | Fire(*Entry) error
11 | }
12 |
13 | // Internal type for storing the hooks on a logger instance.
14 | type levelHooks map[Level][]Hook
15 |
16 | // Add a hook to an instance of logger. This is called with
17 | // `log.Hooks.Add(new(MyHook))` where `MyHook` implements the `Hook` interface.
18 | func (hooks levelHooks) Add(hook Hook) {
19 | for _, level := range hook.Levels() {
20 | hooks[level] = append(hooks[level], hook)
21 | }
22 | }
23 |
24 | // Fire all the hooks for the passed level. Used by `entry.log` to fire
25 | // appropriate hooks for a log entry.
26 | func (hooks levelHooks) Fire(level Level, entry *Entry) error {
27 | for _, hook := range hooks[level] {
28 | if err := hook.Fire(entry); err != nil {
29 | return err
30 | }
31 | }
32 |
33 | return nil
34 | }
35 |
--------------------------------------------------------------------------------
/Godeps/_workspace/src/github.com/Sirupsen/logrus/hooks/airbrake/airbrake.go:
--------------------------------------------------------------------------------
1 | package airbrake
2 |
3 | import (
4 | "errors"
5 | "fmt"
6 |
7 | "github.com/Sirupsen/logrus"
8 | "github.com/tobi/airbrake-go"
9 | )
10 |
11 | // AirbrakeHook to send exceptions to an exception-tracking service compatible
12 | // with the Airbrake API.
13 | type airbrakeHook struct {
14 | APIKey string
15 | Endpoint string
16 | Environment string
17 | }
18 |
19 | func NewHook(endpoint, apiKey, env string) *airbrakeHook {
20 | return &airbrakeHook{
21 | APIKey: apiKey,
22 | Endpoint: endpoint,
23 | Environment: env,
24 | }
25 | }
26 |
27 | func (hook *airbrakeHook) Fire(entry *logrus.Entry) error {
28 | airbrake.ApiKey = hook.APIKey
29 | airbrake.Endpoint = hook.Endpoint
30 | airbrake.Environment = hook.Environment
31 |
32 | var notifyErr error
33 | err, ok := entry.Data["error"].(error)
34 | if ok {
35 | notifyErr = err
36 | } else {
37 | notifyErr = errors.New(entry.Message)
38 | }
39 |
40 | airErr := airbrake.Notify(notifyErr)
41 | if airErr != nil {
42 | return fmt.Errorf("Failed to send error to Airbrake: %s", airErr)
43 | }
44 |
45 | return nil
46 | }
47 |
48 | func (hook *airbrakeHook) Levels() []logrus.Level {
49 | return []logrus.Level{
50 | logrus.ErrorLevel,
51 | logrus.FatalLevel,
52 | logrus.PanicLevel,
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/Godeps/_workspace/src/github.com/Sirupsen/logrus/hooks/airbrake/airbrake_test.go:
--------------------------------------------------------------------------------
1 | package airbrake
2 |
3 | import (
4 | "encoding/xml"
5 | "net/http"
6 | "net/http/httptest"
7 | "testing"
8 | "time"
9 |
10 | "github.com/Sirupsen/logrus"
11 | )
12 |
13 | type notice struct {
14 | Error NoticeError `xml:"error"`
15 | }
16 | type NoticeError struct {
17 | Class string `xml:"class"`
18 | Message string `xml:"message"`
19 | }
20 |
21 | type customErr struct {
22 | msg string
23 | }
24 |
25 | func (e *customErr) Error() string {
26 | return e.msg
27 | }
28 |
29 | const (
30 | testAPIKey = "abcxyz"
31 | testEnv = "development"
32 | expectedClass = "*airbrake.customErr"
33 | expectedMsg = "foo"
34 | unintendedMsg = "Airbrake will not see this string"
35 | )
36 |
37 | var (
38 | noticeError = make(chan NoticeError, 1)
39 | )
40 |
41 | // TestLogEntryMessageReceived checks if invoking Logrus' log.Error
42 | // method causes an XML payload containing the log entry message is received
43 | // by a HTTP server emulating an Airbrake-compatible endpoint.
44 | func TestLogEntryMessageReceived(t *testing.T) {
45 | log := logrus.New()
46 | ts := startAirbrakeServer(t)
47 | defer ts.Close()
48 |
49 | hook := NewHook(ts.URL, testAPIKey, "production")
50 | log.Hooks.Add(hook)
51 |
52 | log.Error(expectedMsg)
53 |
54 | select {
55 | case received := <-noticeError:
56 | if received.Message != expectedMsg {
57 | t.Errorf("Unexpected message received: %s", received.Message)
58 | }
59 | case <-time.After(time.Second):
60 | t.Error("Timed out; no notice received by Airbrake API")
61 | }
62 | }
63 |
64 | // TestLogEntryMessageReceived confirms that, when passing an error type using
65 | // logrus.Fields, a HTTP server emulating an Airbrake endpoint receives the
66 | // error message returned by the Error() method on the error interface
67 | // rather than the logrus.Entry.Message string.
68 | func TestLogEntryWithErrorReceived(t *testing.T) {
69 | log := logrus.New()
70 | ts := startAirbrakeServer(t)
71 | defer ts.Close()
72 |
73 | hook := NewHook(ts.URL, testAPIKey, "production")
74 | log.Hooks.Add(hook)
75 |
76 | log.WithFields(logrus.Fields{
77 | "error": &customErr{expectedMsg},
78 | }).Error(unintendedMsg)
79 |
80 | select {
81 | case received := <-noticeError:
82 | if received.Message != expectedMsg {
83 | t.Errorf("Unexpected message received: %s", received.Message)
84 | }
85 | if received.Class != expectedClass {
86 | t.Errorf("Unexpected error class: %s", received.Class)
87 | }
88 | case <-time.After(time.Second):
89 | t.Error("Timed out; no notice received by Airbrake API")
90 | }
91 | }
92 |
93 | // TestLogEntryWithNonErrorTypeNotReceived confirms that, when passing a
94 | // non-error type using logrus.Fields, a HTTP server emulating an Airbrake
95 | // endpoint receives the logrus.Entry.Message string.
96 | //
97 | // Only error types are supported when setting the 'error' field using
98 | // logrus.WithFields().
99 | func TestLogEntryWithNonErrorTypeNotReceived(t *testing.T) {
100 | log := logrus.New()
101 | ts := startAirbrakeServer(t)
102 | defer ts.Close()
103 |
104 | hook := NewHook(ts.URL, testAPIKey, "production")
105 | log.Hooks.Add(hook)
106 |
107 | log.WithFields(logrus.Fields{
108 | "error": expectedMsg,
109 | }).Error(unintendedMsg)
110 |
111 | select {
112 | case received := <-noticeError:
113 | if received.Message != unintendedMsg {
114 | t.Errorf("Unexpected message received: %s", received.Message)
115 | }
116 | case <-time.After(time.Second):
117 | t.Error("Timed out; no notice received by Airbrake API")
118 | }
119 | }
120 |
121 | func startAirbrakeServer(t *testing.T) *httptest.Server {
122 | ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
123 | var notice notice
124 | if err := xml.NewDecoder(r.Body).Decode(¬ice); err != nil {
125 | t.Error(err)
126 | }
127 | r.Body.Close()
128 |
129 | noticeError <- notice.Error
130 | }))
131 |
132 | return ts
133 | }
134 |
--------------------------------------------------------------------------------
/Godeps/_workspace/src/github.com/Sirupsen/logrus/hooks/papertrail/README.md:
--------------------------------------------------------------------------------
1 | # Papertrail Hook for Logrus
2 |
3 | [Papertrail](https://papertrailapp.com) provides hosted log management. Once stored in Papertrail, you can [group](http://help.papertrailapp.com/kb/how-it-works/groups/) your logs on various dimensions, [search](http://help.papertrailapp.com/kb/how-it-works/search-syntax) them, and trigger [alerts](http://help.papertrailapp.com/kb/how-it-works/alerts).
4 |
5 | In most deployments, you'll want to send logs to Papertrail via their [remote_syslog](http://help.papertrailapp.com/kb/configuration/configuring-centralized-logging-from-text-log-files-in-unix/) daemon, which requires no application-specific configuration. This hook is intended for relatively low-volume logging, likely in managed cloud hosting deployments where installing `remote_syslog` is not possible.
6 |
7 | ## Usage
8 |
9 | You can find your Papertrail UDP port on your [Papertrail account page](https://papertrailapp.com/account/destinations). Substitute it below for `YOUR_PAPERTRAIL_UDP_PORT`.
10 |
11 | For `YOUR_APP_NAME`, substitute a short string that will readily identify your application or service in the logs.
12 |
13 | ```go
14 | import (
15 | "log/syslog"
16 | "github.com/Sirupsen/logrus"
17 | "github.com/Sirupsen/logrus/hooks/papertrail"
18 | )
19 |
20 | func main() {
21 | log := logrus.New()
22 | hook, err := logrus_papertrail.NewPapertrailHook("logs.papertrailapp.com", YOUR_PAPERTRAIL_UDP_PORT, YOUR_APP_NAME)
23 |
24 | if err == nil {
25 | log.Hooks.Add(hook)
26 | }
27 | }
28 | ```
29 |
--------------------------------------------------------------------------------
/Godeps/_workspace/src/github.com/Sirupsen/logrus/hooks/papertrail/papertrail.go:
--------------------------------------------------------------------------------
1 | package logrus_papertrail
2 |
3 | import (
4 | "fmt"
5 | "net"
6 | "os"
7 | "time"
8 |
9 | "github.com/Sirupsen/logrus"
10 | )
11 |
12 | const (
13 | format = "Jan 2 15:04:05"
14 | )
15 |
16 | // PapertrailHook to send logs to a logging service compatible with the Papertrail API.
17 | type PapertrailHook struct {
18 | Host string
19 | Port int
20 | AppName string
21 | UDPConn net.Conn
22 | }
23 |
24 | // NewPapertrailHook creates a hook to be added to an instance of logger.
25 | func NewPapertrailHook(host string, port int, appName string) (*PapertrailHook, error) {
26 | conn, err := net.Dial("udp", fmt.Sprintf("%s:%d", host, port))
27 | return &PapertrailHook{host, port, appName, conn}, err
28 | }
29 |
30 | // Fire is called when a log event is fired.
31 | func (hook *PapertrailHook) Fire(entry *logrus.Entry) error {
32 | date := time.Now().Format(format)
33 | msg, _ := entry.String()
34 | payload := fmt.Sprintf("<22> %s %s: %s", date, hook.AppName, msg)
35 |
36 | bytesWritten, err := hook.UDPConn.Write([]byte(payload))
37 | if err != nil {
38 | fmt.Fprintf(os.Stderr, "Unable to send log line to Papertrail via UDP. Wrote %d bytes before error: %v", bytesWritten, err)
39 | return err
40 | }
41 |
42 | return nil
43 | }
44 |
45 | // Levels returns the available logging levels.
46 | func (hook *PapertrailHook) Levels() []logrus.Level {
47 | return []logrus.Level{
48 | logrus.PanicLevel,
49 | logrus.FatalLevel,
50 | logrus.ErrorLevel,
51 | logrus.WarnLevel,
52 | logrus.InfoLevel,
53 | logrus.DebugLevel,
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/Godeps/_workspace/src/github.com/Sirupsen/logrus/hooks/papertrail/papertrail_test.go:
--------------------------------------------------------------------------------
1 | package logrus_papertrail
2 |
3 | import (
4 | "fmt"
5 | "testing"
6 |
7 | "github.com/Sirupsen/logrus"
8 | "github.com/stvp/go-udp-testing"
9 | )
10 |
11 | func TestWritingToUDP(t *testing.T) {
12 | port := 16661
13 | udp.SetAddr(fmt.Sprintf(":%d", port))
14 |
15 | hook, err := NewPapertrailHook("localhost", port, "test")
16 | if err != nil {
17 | t.Errorf("Unable to connect to local UDP server.")
18 | }
19 |
20 | log := logrus.New()
21 | log.Hooks.Add(hook)
22 |
23 | udp.ShouldReceive(t, "foo", func() {
24 | log.Info("foo")
25 | })
26 | }
27 |
--------------------------------------------------------------------------------
/Godeps/_workspace/src/github.com/Sirupsen/logrus/hooks/sentry/README.md:
--------------------------------------------------------------------------------
1 | # Sentry Hook for Logrus
2 |
3 | [Sentry](https://getsentry.com) provides both self-hosted and hosted
4 | solutions for exception tracking.
5 | Both client and server are
6 | [open source](https://github.com/getsentry/sentry).
7 |
8 | ## Usage
9 |
10 | Every sentry application defined on the server gets a different
11 | [DSN](https://www.getsentry.com/docs/). In the example below replace
12 | `YOUR_DSN` with the one created for your application.
13 |
14 | ```go
15 | import (
16 | "github.com/Sirupsen/logrus"
17 | "github.com/Sirupsen/logrus/hooks/sentry"
18 | )
19 |
20 | func main() {
21 | log := logrus.New()
22 | hook, err := logrus_sentry.NewSentryHook(YOUR_DSN, []logrus.Level{
23 | logrus.PanicLevel,
24 | logrus.FatalLevel,
25 | logrus.ErrorLevel,
26 | })
27 |
28 | if err == nil {
29 | log.Hooks.Add(hook)
30 | }
31 | }
32 | ```
33 |
34 | ## Special fields
35 |
36 | Some logrus fields have a special meaning in this hook,
37 | these are server_name and logger.
38 | When logs are sent to sentry these fields are treated differently.
39 | - server_name (also known as hostname) is the name of the server which
40 | is logging the event (hostname.example.com)
41 | - logger is the part of the application which is logging the event.
42 | In go this usually means setting it to the name of the package.
43 |
44 | ## Timeout
45 |
46 | `Timeout` is the time the sentry hook will wait for a response
47 | from the sentry server.
48 |
49 | If this time elapses with no response from
50 | the server an error will be returned.
51 |
52 | If `Timeout` is set to 0 the SentryHook will not wait for a reply
53 | and will assume a correct delivery.
54 |
55 | The SentryHook has a default timeout of `100 milliseconds` when created
56 | with a call to `NewSentryHook`. This can be changed by assigning a value to the `Timeout` field:
57 |
58 | ```go
59 | hook, _ := logrus_sentry.NewSentryHook(...)
60 | hook.Timeout = 20*time.Second
61 | ```
62 |
--------------------------------------------------------------------------------
/Godeps/_workspace/src/github.com/Sirupsen/logrus/hooks/sentry/sentry.go:
--------------------------------------------------------------------------------
1 | package logrus_sentry
2 |
3 | import (
4 | "fmt"
5 | "time"
6 |
7 | "github.com/Sirupsen/logrus"
8 | "github.com/getsentry/raven-go"
9 | )
10 |
11 | var (
12 | severityMap = map[logrus.Level]raven.Severity{
13 | logrus.DebugLevel: raven.DEBUG,
14 | logrus.InfoLevel: raven.INFO,
15 | logrus.WarnLevel: raven.WARNING,
16 | logrus.ErrorLevel: raven.ERROR,
17 | logrus.FatalLevel: raven.FATAL,
18 | logrus.PanicLevel: raven.FATAL,
19 | }
20 | )
21 |
22 | func getAndDel(d logrus.Fields, key string) (string, bool) {
23 | var (
24 | ok bool
25 | v interface{}
26 | val string
27 | )
28 | if v, ok = d[key]; !ok {
29 | return "", false
30 | }
31 |
32 | if val, ok = v.(string); !ok {
33 | return "", false
34 | }
35 | delete(d, key)
36 | return val, true
37 | }
38 |
39 | // SentryHook delivers logs to a sentry server.
40 | type SentryHook struct {
41 | // Timeout sets the time to wait for a delivery error from the sentry server.
42 | // If this is set to zero the server will not wait for any response and will
43 | // consider the message correctly sent
44 | Timeout time.Duration
45 |
46 | client *raven.Client
47 | levels []logrus.Level
48 | }
49 |
50 | // NewSentryHook creates a hook to be added to an instance of logger
51 | // and initializes the raven client.
52 | // This method sets the timeout to 100 milliseconds.
53 | func NewSentryHook(DSN string, levels []logrus.Level) (*SentryHook, error) {
54 | client, err := raven.NewClient(DSN, nil)
55 | if err != nil {
56 | return nil, err
57 | }
58 | return &SentryHook{100 * time.Millisecond, client, levels}, nil
59 | }
60 |
61 | // Called when an event should be sent to sentry
62 | // Special fields that sentry uses to give more information to the server
63 | // are extracted from entry.Data (if they are found)
64 | // These fields are: logger and server_name
65 | func (hook *SentryHook) Fire(entry *logrus.Entry) error {
66 | packet := &raven.Packet{
67 | Message: entry.Message,
68 | Timestamp: raven.Timestamp(entry.Time),
69 | Level: severityMap[entry.Level],
70 | Platform: "go",
71 | }
72 |
73 | d := entry.Data
74 |
75 | if logger, ok := getAndDel(d, "logger"); ok {
76 | packet.Logger = logger
77 | }
78 | if serverName, ok := getAndDel(d, "server_name"); ok {
79 | packet.ServerName = serverName
80 | }
81 | packet.Extra = map[string]interface{}(d)
82 |
83 | _, errCh := hook.client.Capture(packet, nil)
84 | timeout := hook.Timeout
85 | if timeout != 0 {
86 | timeoutCh := time.After(timeout)
87 | select {
88 | case err := <-errCh:
89 | return err
90 | case <-timeoutCh:
91 | return fmt.Errorf("no response from sentry server in %s", timeout)
92 | }
93 | }
94 | return nil
95 | }
96 |
97 | // Levels returns the available logging levels.
98 | func (hook *SentryHook) Levels() []logrus.Level {
99 | return hook.levels
100 | }
101 |
--------------------------------------------------------------------------------
/Godeps/_workspace/src/github.com/Sirupsen/logrus/hooks/sentry/sentry_test.go:
--------------------------------------------------------------------------------
1 | package logrus_sentry
2 |
3 | import (
4 | "encoding/json"
5 | "fmt"
6 | "io/ioutil"
7 | "net/http"
8 | "net/http/httptest"
9 | "strings"
10 | "testing"
11 |
12 | "github.com/Sirupsen/logrus"
13 | "github.com/getsentry/raven-go"
14 | )
15 |
16 | const (
17 | message = "error message"
18 | server_name = "testserver.internal"
19 | logger_name = "test.logger"
20 | )
21 |
22 | func getTestLogger() *logrus.Logger {
23 | l := logrus.New()
24 | l.Out = ioutil.Discard
25 | return l
26 | }
27 |
28 | func WithTestDSN(t *testing.T, tf func(string, <-chan *raven.Packet)) {
29 | pch := make(chan *raven.Packet, 1)
30 | s := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
31 | defer req.Body.Close()
32 | d := json.NewDecoder(req.Body)
33 | p := &raven.Packet{}
34 | err := d.Decode(p)
35 | if err != nil {
36 | t.Fatal(err.Error())
37 | }
38 |
39 | pch <- p
40 | }))
41 | defer s.Close()
42 |
43 | fragments := strings.SplitN(s.URL, "://", 2)
44 | dsn := fmt.Sprintf(
45 | "%s://public:secret@%s/sentry/project-id",
46 | fragments[0],
47 | fragments[1],
48 | )
49 | tf(dsn, pch)
50 | }
51 |
52 | func TestSpecialFields(t *testing.T) {
53 | WithTestDSN(t, func(dsn string, pch <-chan *raven.Packet) {
54 | logger := getTestLogger()
55 |
56 | hook, err := NewSentryHook(dsn, []logrus.Level{
57 | logrus.ErrorLevel,
58 | })
59 |
60 | if err != nil {
61 | t.Fatal(err.Error())
62 | }
63 | logger.Hooks.Add(hook)
64 | logger.WithFields(logrus.Fields{
65 | "server_name": server_name,
66 | "logger": logger_name,
67 | }).Error(message)
68 |
69 | packet := <-pch
70 | if packet.Logger != logger_name {
71 | t.Errorf("logger should have been %s, was %s", logger_name, packet.Logger)
72 | }
73 |
74 | if packet.ServerName != server_name {
75 | t.Errorf("server_name should have been %s, was %s", server_name, packet.ServerName)
76 | }
77 | })
78 | }
79 |
80 | func TestSentryHandler(t *testing.T) {
81 | WithTestDSN(t, func(dsn string, pch <-chan *raven.Packet) {
82 | logger := getTestLogger()
83 | hook, err := NewSentryHook(dsn, []logrus.Level{
84 | logrus.ErrorLevel,
85 | })
86 | if err != nil {
87 | t.Fatal(err.Error())
88 | }
89 | logger.Hooks.Add(hook)
90 |
91 | logger.Error(message)
92 | packet := <-pch
93 | if packet.Message != message {
94 | t.Errorf("message should have been %s, was %s", message, packet.Message)
95 | }
96 | })
97 | }
98 |
--------------------------------------------------------------------------------
/Godeps/_workspace/src/github.com/Sirupsen/logrus/hooks/syslog/README.md:
--------------------------------------------------------------------------------
1 | # Syslog Hooks for Logrus
2 |
3 | ## Usage
4 |
5 | ```go
6 | import (
7 | "log/syslog"
8 | "github.com/Sirupsen/logrus"
9 | logrus_syslog "github.com/Sirupsen/logrus/hooks/syslog"
10 | )
11 |
12 | func main() {
13 | log := logrus.New()
14 | hook, err := logrus_syslog.NewSyslogHook("udp", "localhost:514", syslog.LOG_INFO, "")
15 |
16 | if err == nil {
17 | log.Hooks.Add(hook)
18 | }
19 | }
20 | ```
21 |
--------------------------------------------------------------------------------
/Godeps/_workspace/src/github.com/Sirupsen/logrus/hooks/syslog/syslog.go:
--------------------------------------------------------------------------------
1 | package logrus_syslog
2 |
3 | import (
4 | "fmt"
5 | "github.com/Sirupsen/logrus"
6 | "log/syslog"
7 | "os"
8 | )
9 |
10 | // SyslogHook to send logs via syslog.
11 | type SyslogHook struct {
12 | Writer *syslog.Writer
13 | SyslogNetwork string
14 | SyslogRaddr string
15 | }
16 |
17 | // Creates a hook to be added to an instance of logger. This is called with
18 | // `hook, err := NewSyslogHook("udp", "localhost:514", syslog.LOG_DEBUG, "")`
19 | // `if err == nil { log.Hooks.Add(hook) }`
20 | func NewSyslogHook(network, raddr string, priority syslog.Priority, tag string) (*SyslogHook, error) {
21 | w, err := syslog.Dial(network, raddr, priority, tag)
22 | return &SyslogHook{w, network, raddr}, err
23 | }
24 |
25 | func (hook *SyslogHook) Fire(entry *logrus.Entry) error {
26 | line, err := entry.String()
27 | if err != nil {
28 | fmt.Fprintf(os.Stderr, "Unable to read entry, %v", err)
29 | return err
30 | }
31 |
32 | switch entry.Level {
33 | case logrus.PanicLevel:
34 | return hook.Writer.Crit(line)
35 | case logrus.FatalLevel:
36 | return hook.Writer.Crit(line)
37 | case logrus.ErrorLevel:
38 | return hook.Writer.Err(line)
39 | case logrus.WarnLevel:
40 | return hook.Writer.Warning(line)
41 | case logrus.InfoLevel:
42 | return hook.Writer.Info(line)
43 | case logrus.DebugLevel:
44 | return hook.Writer.Debug(line)
45 | default:
46 | return nil
47 | }
48 | }
49 |
50 | func (hook *SyslogHook) Levels() []logrus.Level {
51 | return []logrus.Level{
52 | logrus.PanicLevel,
53 | logrus.FatalLevel,
54 | logrus.ErrorLevel,
55 | logrus.WarnLevel,
56 | logrus.InfoLevel,
57 | logrus.DebugLevel,
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/Godeps/_workspace/src/github.com/Sirupsen/logrus/hooks/syslog/syslog_test.go:
--------------------------------------------------------------------------------
1 | package logrus_syslog
2 |
3 | import (
4 | "github.com/Sirupsen/logrus"
5 | "log/syslog"
6 | "testing"
7 | )
8 |
9 | func TestLocalhostAddAndPrint(t *testing.T) {
10 | log := logrus.New()
11 | hook, err := NewSyslogHook("udp", "localhost:514", syslog.LOG_INFO, "")
12 |
13 | if err != nil {
14 | t.Errorf("Unable to connect to local syslog.")
15 | }
16 |
17 | log.Hooks.Add(hook)
18 |
19 | for _, level := range hook.Levels() {
20 | if len(log.Hooks[level]) != 1 {
21 | t.Errorf("SyslogHook was not added. The length of log.Hooks[%v]: %v", level, len(log.Hooks[level]))
22 | }
23 | }
24 |
25 | log.Info("Congratulations!")
26 | }
27 |
--------------------------------------------------------------------------------
/Godeps/_workspace/src/github.com/Sirupsen/logrus/json_formatter.go:
--------------------------------------------------------------------------------
1 | package logrus
2 |
3 | import (
4 | "encoding/json"
5 | "fmt"
6 | "time"
7 | )
8 |
9 | type JSONFormatter struct{}
10 |
11 | func (f *JSONFormatter) Format(entry *Entry) ([]byte, error) {
12 | data := make(Fields, len(entry.Data)+3)
13 | for k, v := range entry.Data {
14 | // Otherwise errors are ignored by `encoding/json`
15 | // https://github.com/Sirupsen/logrus/issues/137
16 | if err, ok := v.(error); ok {
17 | data[k] = err.Error()
18 | } else {
19 | data[k] = v
20 | }
21 | }
22 | prefixFieldClashes(data)
23 | data["time"] = entry.Time.Format(time.RFC3339)
24 | data["msg"] = entry.Message
25 | data["level"] = entry.Level.String()
26 |
27 | serialized, err := json.Marshal(data)
28 | if err != nil {
29 | return nil, fmt.Errorf("Failed to marshal fields to JSON, %v", err)
30 | }
31 | return append(serialized, '\n'), nil
32 | }
33 |
--------------------------------------------------------------------------------
/Godeps/_workspace/src/github.com/Sirupsen/logrus/json_formatter_test.go:
--------------------------------------------------------------------------------
1 | package logrus
2 |
3 | import (
4 | "encoding/json"
5 | "errors"
6 |
7 | "testing"
8 | )
9 |
10 | func TestErrorNotLost(t *testing.T) {
11 | formatter := &JSONFormatter{}
12 |
13 | b, err := formatter.Format(WithField("error", errors.New("wild walrus")))
14 | if err != nil {
15 | t.Fatal("Unable to format entry: ", err)
16 | }
17 |
18 | entry := make(map[string]interface{})
19 | err = json.Unmarshal(b, &entry)
20 | if err != nil {
21 | t.Fatal("Unable to unmarshal formatted entry: ", err)
22 | }
23 |
24 | if entry["error"] != "wild walrus" {
25 | t.Fatal("Error field not set")
26 | }
27 | }
28 |
29 | func TestErrorNotLostOnFieldNotNamedError(t *testing.T) {
30 | formatter := &JSONFormatter{}
31 |
32 | b, err := formatter.Format(WithField("omg", errors.New("wild walrus")))
33 | if err != nil {
34 | t.Fatal("Unable to format entry: ", err)
35 | }
36 |
37 | entry := make(map[string]interface{})
38 | err = json.Unmarshal(b, &entry)
39 | if err != nil {
40 | t.Fatal("Unable to unmarshal formatted entry: ", err)
41 | }
42 |
43 | if entry["omg"] != "wild walrus" {
44 | t.Fatal("Error field not set")
45 | }
46 | }
47 |
48 | func TestFieldClashWithTime(t *testing.T) {
49 | formatter := &JSONFormatter{}
50 |
51 | b, err := formatter.Format(WithField("time", "right now!"))
52 | if err != nil {
53 | t.Fatal("Unable to format entry: ", err)
54 | }
55 |
56 | entry := make(map[string]interface{})
57 | err = json.Unmarshal(b, &entry)
58 | if err != nil {
59 | t.Fatal("Unable to unmarshal formatted entry: ", err)
60 | }
61 |
62 | if entry["fields.time"] != "right now!" {
63 | t.Fatal("fields.time not set to original time field")
64 | }
65 |
66 | if entry["time"] != "0001-01-01T00:00:00Z" {
67 | t.Fatal("time field not set to current time, was: ", entry["time"])
68 | }
69 | }
70 |
71 | func TestFieldClashWithMsg(t *testing.T) {
72 | formatter := &JSONFormatter{}
73 |
74 | b, err := formatter.Format(WithField("msg", "something"))
75 | if err != nil {
76 | t.Fatal("Unable to format entry: ", err)
77 | }
78 |
79 | entry := make(map[string]interface{})
80 | err = json.Unmarshal(b, &entry)
81 | if err != nil {
82 | t.Fatal("Unable to unmarshal formatted entry: ", err)
83 | }
84 |
85 | if entry["fields.msg"] != "something" {
86 | t.Fatal("fields.msg not set to original msg field")
87 | }
88 | }
89 |
90 | func TestFieldClashWithLevel(t *testing.T) {
91 | formatter := &JSONFormatter{}
92 |
93 | b, err := formatter.Format(WithField("level", "something"))
94 | if err != nil {
95 | t.Fatal("Unable to format entry: ", err)
96 | }
97 |
98 | entry := make(map[string]interface{})
99 | err = json.Unmarshal(b, &entry)
100 | if err != nil {
101 | t.Fatal("Unable to unmarshal formatted entry: ", err)
102 | }
103 |
104 | if entry["fields.level"] != "something" {
105 | t.Fatal("fields.level not set to original level field")
106 | }
107 | }
108 |
109 | func TestJSONEntryEndsWithNewline(t *testing.T) {
110 | formatter := &JSONFormatter{}
111 |
112 | b, err := formatter.Format(WithField("level", "something"))
113 | if err != nil {
114 | t.Fatal("Unable to format entry: ", err)
115 | }
116 |
117 | if b[len(b)-1] != '\n' {
118 | t.Fatal("Expected JSON log entry to end with a newline")
119 | }
120 | }
121 |
--------------------------------------------------------------------------------
/Godeps/_workspace/src/github.com/Sirupsen/logrus/logger.go:
--------------------------------------------------------------------------------
1 | package logrus
2 |
3 | import (
4 | "io"
5 | "os"
6 | "sync"
7 | )
8 |
9 | type Logger struct {
10 | // The logs are `io.Copy`'d to this in a mutex. It's common to set this to a
11 | // file, or leave it default which is `os.Stdout`. You can also set this to
12 | // something more adventorous, such as logging to Kafka.
13 | Out io.Writer
14 | // Hooks for the logger instance. These allow firing events based on logging
15 | // levels and log entries. For example, to send errors to an error tracking
16 | // service, log to StatsD or dump the core on fatal errors.
17 | Hooks levelHooks
18 | // All log entries pass through the formatter before logged to Out. The
19 | // included formatters are `TextFormatter` and `JSONFormatter` for which
20 | // TextFormatter is the default. In development (when a TTY is attached) it
21 | // logs with colors, but to a file it wouldn't. You can easily implement your
22 | // own that implements the `Formatter` interface, see the `README` or included
23 | // formatters for examples.
24 | Formatter Formatter
25 | // The logging level the logger should log at. This is typically (and defaults
26 | // to) `logrus.Info`, which allows Info(), Warn(), Error() and Fatal() to be
27 | // logged. `logrus.Debug` is useful in
28 | Level Level
29 | // Used to sync writing to the log.
30 | mu sync.Mutex
31 | }
32 |
33 | // Creates a new logger. Configuration should be set by changing `Formatter`,
34 | // `Out` and `Hooks` directly on the default logger instance. You can also just
35 | // instantiate your own:
36 | //
37 | // var log = &Logger{
38 | // Out: os.Stderr,
39 | // Formatter: new(JSONFormatter),
40 | // Hooks: make(levelHooks),
41 | // Level: logrus.DebugLevel,
42 | // }
43 | //
44 | // It's recommended to make this a global instance called `log`.
45 | func New() *Logger {
46 | return &Logger{
47 | Out: os.Stdout,
48 | Formatter: new(TextFormatter),
49 | Hooks: make(levelHooks),
50 | Level: InfoLevel,
51 | }
52 | }
53 |
54 | // Adds a field to the log entry, note that you it doesn't log until you call
55 | // Debug, Print, Info, Warn, Fatal or Panic. It only creates a log entry.
56 | // Ff you want multiple fields, use `WithFields`.
57 | func (logger *Logger) WithField(key string, value interface{}) *Entry {
58 | return NewEntry(logger).WithField(key, value)
59 | }
60 |
61 | // Adds a struct of fields to the log entry. All it does is call `WithField` for
62 | // each `Field`.
63 | func (logger *Logger) WithFields(fields Fields) *Entry {
64 | return NewEntry(logger).WithFields(fields)
65 | }
66 |
67 | func (logger *Logger) Debugf(format string, args ...interface{}) {
68 | NewEntry(logger).Debugf(format, args...)
69 | }
70 |
71 | func (logger *Logger) Infof(format string, args ...interface{}) {
72 | NewEntry(logger).Infof(format, args...)
73 | }
74 |
75 | func (logger *Logger) Printf(format string, args ...interface{}) {
76 | NewEntry(logger).Printf(format, args...)
77 | }
78 |
79 | func (logger *Logger) Warnf(format string, args ...interface{}) {
80 | NewEntry(logger).Warnf(format, args...)
81 | }
82 |
83 | func (logger *Logger) Warningf(format string, args ...interface{}) {
84 | NewEntry(logger).Warnf(format, args...)
85 | }
86 |
87 | func (logger *Logger) Errorf(format string, args ...interface{}) {
88 | NewEntry(logger).Errorf(format, args...)
89 | }
90 |
91 | func (logger *Logger) Fatalf(format string, args ...interface{}) {
92 | NewEntry(logger).Fatalf(format, args...)
93 | }
94 |
95 | func (logger *Logger) Panicf(format string, args ...interface{}) {
96 | NewEntry(logger).Panicf(format, args...)
97 | }
98 |
99 | func (logger *Logger) Debug(args ...interface{}) {
100 | NewEntry(logger).Debug(args...)
101 | }
102 |
103 | func (logger *Logger) Info(args ...interface{}) {
104 | NewEntry(logger).Info(args...)
105 | }
106 |
107 | func (logger *Logger) Print(args ...interface{}) {
108 | NewEntry(logger).Info(args...)
109 | }
110 |
111 | func (logger *Logger) Warn(args ...interface{}) {
112 | NewEntry(logger).Warn(args...)
113 | }
114 |
115 | func (logger *Logger) Warning(args ...interface{}) {
116 | NewEntry(logger).Warn(args...)
117 | }
118 |
119 | func (logger *Logger) Error(args ...interface{}) {
120 | NewEntry(logger).Error(args...)
121 | }
122 |
123 | func (logger *Logger) Fatal(args ...interface{}) {
124 | NewEntry(logger).Fatal(args...)
125 | }
126 |
127 | func (logger *Logger) Panic(args ...interface{}) {
128 | NewEntry(logger).Panic(args...)
129 | }
130 |
131 | func (logger *Logger) Debugln(args ...interface{}) {
132 | NewEntry(logger).Debugln(args...)
133 | }
134 |
135 | func (logger *Logger) Infoln(args ...interface{}) {
136 | NewEntry(logger).Infoln(args...)
137 | }
138 |
139 | func (logger *Logger) Println(args ...interface{}) {
140 | NewEntry(logger).Println(args...)
141 | }
142 |
143 | func (logger *Logger) Warnln(args ...interface{}) {
144 | NewEntry(logger).Warnln(args...)
145 | }
146 |
147 | func (logger *Logger) Warningln(args ...interface{}) {
148 | NewEntry(logger).Warnln(args...)
149 | }
150 |
151 | func (logger *Logger) Errorln(args ...interface{}) {
152 | NewEntry(logger).Errorln(args...)
153 | }
154 |
155 | func (logger *Logger) Fatalln(args ...interface{}) {
156 | NewEntry(logger).Fatalln(args...)
157 | }
158 |
159 | func (logger *Logger) Panicln(args ...interface{}) {
160 | NewEntry(logger).Panicln(args...)
161 | }
162 |
--------------------------------------------------------------------------------
/Godeps/_workspace/src/github.com/Sirupsen/logrus/logrus.go:
--------------------------------------------------------------------------------
1 | package logrus
2 |
3 | import (
4 | "fmt"
5 | "log"
6 | )
7 |
8 | // Fields type, used to pass to `WithFields`.
9 | type Fields map[string]interface{}
10 |
11 | // Level type
12 | type Level uint8
13 |
14 | // Convert the Level to a string. E.g. PanicLevel becomes "panic".
15 | func (level Level) String() string {
16 | switch level {
17 | case DebugLevel:
18 | return "debug"
19 | case InfoLevel:
20 | return "info"
21 | case WarnLevel:
22 | return "warning"
23 | case ErrorLevel:
24 | return "error"
25 | case FatalLevel:
26 | return "fatal"
27 | case PanicLevel:
28 | return "panic"
29 | }
30 |
31 | return "unknown"
32 | }
33 |
34 | // ParseLevel takes a string level and returns the Logrus log level constant.
35 | func ParseLevel(lvl string) (Level, error) {
36 | switch lvl {
37 | case "panic":
38 | return PanicLevel, nil
39 | case "fatal":
40 | return FatalLevel, nil
41 | case "error":
42 | return ErrorLevel, nil
43 | case "warn", "warning":
44 | return WarnLevel, nil
45 | case "info":
46 | return InfoLevel, nil
47 | case "debug":
48 | return DebugLevel, nil
49 | }
50 |
51 | var l Level
52 | return l, fmt.Errorf("not a valid logrus Level: %q", lvl)
53 | }
54 |
55 | // These are the different logging levels. You can set the logging level to log
56 | // on your instance of logger, obtained with `logrus.New()`.
57 | const (
58 | // PanicLevel level, highest level of severity. Logs and then calls panic with the
59 | // message passed to Debug, Info, ...
60 | PanicLevel Level = iota
61 | // FatalLevel level. Logs and then calls `os.Exit(1)`. It will exit even if the
62 | // logging level is set to Panic.
63 | FatalLevel
64 | // ErrorLevel level. Logs. Used for errors that should definitely be noted.
65 | // Commonly used for hooks to send errors to an error tracking service.
66 | ErrorLevel
67 | // WarnLevel level. Non-critical entries that deserve eyes.
68 | WarnLevel
69 | // InfoLevel level. General operational entries about what's going on inside the
70 | // application.
71 | InfoLevel
72 | // DebugLevel level. Usually only enabled when debugging. Very verbose logging.
73 | DebugLevel
74 | )
75 |
76 | // Won't compile if StdLogger can't be realized by a log.Logger
77 | var _ StdLogger = &log.Logger{}
78 |
79 | // StdLogger is what your logrus-enabled library should take, that way
80 | // it'll accept a stdlib logger and a logrus logger. There's no standard
81 | // interface, this is the closest we get, unfortunately.
82 | type StdLogger interface {
83 | Print(...interface{})
84 | Printf(string, ...interface{})
85 | Println(...interface{})
86 |
87 | Fatal(...interface{})
88 | Fatalf(string, ...interface{})
89 | Fatalln(...interface{})
90 |
91 | Panic(...interface{})
92 | Panicf(string, ...interface{})
93 | Panicln(...interface{})
94 | }
95 |
--------------------------------------------------------------------------------
/Godeps/_workspace/src/github.com/Sirupsen/logrus/logrus_test.go:
--------------------------------------------------------------------------------
1 | package logrus
2 |
3 | import (
4 | "bytes"
5 | "encoding/json"
6 | "strconv"
7 | "strings"
8 | "sync"
9 | "testing"
10 |
11 | "github.com/stretchr/testify/assert"
12 | )
13 |
14 | func LogAndAssertJSON(t *testing.T, log func(*Logger), assertions func(fields Fields)) {
15 | var buffer bytes.Buffer
16 | var fields Fields
17 |
18 | logger := New()
19 | logger.Out = &buffer
20 | logger.Formatter = new(JSONFormatter)
21 |
22 | log(logger)
23 |
24 | err := json.Unmarshal(buffer.Bytes(), &fields)
25 | assert.Nil(t, err)
26 |
27 | assertions(fields)
28 | }
29 |
30 | func LogAndAssertText(t *testing.T, log func(*Logger), assertions func(fields map[string]string)) {
31 | var buffer bytes.Buffer
32 |
33 | logger := New()
34 | logger.Out = &buffer
35 | logger.Formatter = &TextFormatter{
36 | DisableColors: true,
37 | }
38 |
39 | log(logger)
40 |
41 | fields := make(map[string]string)
42 | for _, kv := range strings.Split(buffer.String(), " ") {
43 | if !strings.Contains(kv, "=") {
44 | continue
45 | }
46 | kvArr := strings.Split(kv, "=")
47 | key := strings.TrimSpace(kvArr[0])
48 | val := kvArr[1]
49 | if kvArr[1][0] == '"' {
50 | var err error
51 | val, err = strconv.Unquote(val)
52 | assert.NoError(t, err)
53 | }
54 | fields[key] = val
55 | }
56 | assertions(fields)
57 | }
58 |
59 | func TestPrint(t *testing.T) {
60 | LogAndAssertJSON(t, func(log *Logger) {
61 | log.Print("test")
62 | }, func(fields Fields) {
63 | assert.Equal(t, fields["msg"], "test")
64 | assert.Equal(t, fields["level"], "info")
65 | })
66 | }
67 |
68 | func TestInfo(t *testing.T) {
69 | LogAndAssertJSON(t, func(log *Logger) {
70 | log.Info("test")
71 | }, func(fields Fields) {
72 | assert.Equal(t, fields["msg"], "test")
73 | assert.Equal(t, fields["level"], "info")
74 | })
75 | }
76 |
77 | func TestWarn(t *testing.T) {
78 | LogAndAssertJSON(t, func(log *Logger) {
79 | log.Warn("test")
80 | }, func(fields Fields) {
81 | assert.Equal(t, fields["msg"], "test")
82 | assert.Equal(t, fields["level"], "warning")
83 | })
84 | }
85 |
86 | func TestInfolnShouldAddSpacesBetweenStrings(t *testing.T) {
87 | LogAndAssertJSON(t, func(log *Logger) {
88 | log.Infoln("test", "test")
89 | }, func(fields Fields) {
90 | assert.Equal(t, fields["msg"], "test test")
91 | })
92 | }
93 |
94 | func TestInfolnShouldAddSpacesBetweenStringAndNonstring(t *testing.T) {
95 | LogAndAssertJSON(t, func(log *Logger) {
96 | log.Infoln("test", 10)
97 | }, func(fields Fields) {
98 | assert.Equal(t, fields["msg"], "test 10")
99 | })
100 | }
101 |
102 | func TestInfolnShouldAddSpacesBetweenTwoNonStrings(t *testing.T) {
103 | LogAndAssertJSON(t, func(log *Logger) {
104 | log.Infoln(10, 10)
105 | }, func(fields Fields) {
106 | assert.Equal(t, fields["msg"], "10 10")
107 | })
108 | }
109 |
110 | func TestInfoShouldAddSpacesBetweenTwoNonStrings(t *testing.T) {
111 | LogAndAssertJSON(t, func(log *Logger) {
112 | log.Infoln(10, 10)
113 | }, func(fields Fields) {
114 | assert.Equal(t, fields["msg"], "10 10")
115 | })
116 | }
117 |
118 | func TestInfoShouldNotAddSpacesBetweenStringAndNonstring(t *testing.T) {
119 | LogAndAssertJSON(t, func(log *Logger) {
120 | log.Info("test", 10)
121 | }, func(fields Fields) {
122 | assert.Equal(t, fields["msg"], "test10")
123 | })
124 | }
125 |
126 | func TestInfoShouldNotAddSpacesBetweenStrings(t *testing.T) {
127 | LogAndAssertJSON(t, func(log *Logger) {
128 | log.Info("test", "test")
129 | }, func(fields Fields) {
130 | assert.Equal(t, fields["msg"], "testtest")
131 | })
132 | }
133 |
134 | func TestWithFieldsShouldAllowAssignments(t *testing.T) {
135 | var buffer bytes.Buffer
136 | var fields Fields
137 |
138 | logger := New()
139 | logger.Out = &buffer
140 | logger.Formatter = new(JSONFormatter)
141 |
142 | localLog := logger.WithFields(Fields{
143 | "key1": "value1",
144 | })
145 |
146 | localLog.WithField("key2", "value2").Info("test")
147 | err := json.Unmarshal(buffer.Bytes(), &fields)
148 | assert.Nil(t, err)
149 |
150 | assert.Equal(t, "value2", fields["key2"])
151 | assert.Equal(t, "value1", fields["key1"])
152 |
153 | buffer = bytes.Buffer{}
154 | fields = Fields{}
155 | localLog.Info("test")
156 | err = json.Unmarshal(buffer.Bytes(), &fields)
157 | assert.Nil(t, err)
158 |
159 | _, ok := fields["key2"]
160 | assert.Equal(t, false, ok)
161 | assert.Equal(t, "value1", fields["key1"])
162 | }
163 |
164 | func TestUserSuppliedFieldDoesNotOverwriteDefaults(t *testing.T) {
165 | LogAndAssertJSON(t, func(log *Logger) {
166 | log.WithField("msg", "hello").Info("test")
167 | }, func(fields Fields) {
168 | assert.Equal(t, fields["msg"], "test")
169 | })
170 | }
171 |
172 | func TestUserSuppliedMsgFieldHasPrefix(t *testing.T) {
173 | LogAndAssertJSON(t, func(log *Logger) {
174 | log.WithField("msg", "hello").Info("test")
175 | }, func(fields Fields) {
176 | assert.Equal(t, fields["msg"], "test")
177 | assert.Equal(t, fields["fields.msg"], "hello")
178 | })
179 | }
180 |
181 | func TestUserSuppliedTimeFieldHasPrefix(t *testing.T) {
182 | LogAndAssertJSON(t, func(log *Logger) {
183 | log.WithField("time", "hello").Info("test")
184 | }, func(fields Fields) {
185 | assert.Equal(t, fields["fields.time"], "hello")
186 | })
187 | }
188 |
189 | func TestUserSuppliedLevelFieldHasPrefix(t *testing.T) {
190 | LogAndAssertJSON(t, func(log *Logger) {
191 | log.WithField("level", 1).Info("test")
192 | }, func(fields Fields) {
193 | assert.Equal(t, fields["level"], "info")
194 | assert.Equal(t, fields["fields.level"], 1)
195 | })
196 | }
197 |
198 | func TestDefaultFieldsAreNotPrefixed(t *testing.T) {
199 | LogAndAssertText(t, func(log *Logger) {
200 | ll := log.WithField("herp", "derp")
201 | ll.Info("hello")
202 | ll.Info("bye")
203 | }, func(fields map[string]string) {
204 | for _, fieldName := range []string{"fields.level", "fields.time", "fields.msg"} {
205 | if _, ok := fields[fieldName]; ok {
206 | t.Fatalf("should not have prefixed %q: %v", fieldName, fields)
207 | }
208 | }
209 | })
210 | }
211 |
212 | func TestDoubleLoggingDoesntPrefixPreviousFields(t *testing.T) {
213 |
214 | var buffer bytes.Buffer
215 | var fields Fields
216 |
217 | logger := New()
218 | logger.Out = &buffer
219 | logger.Formatter = new(JSONFormatter)
220 |
221 | llog := logger.WithField("context", "eating raw fish")
222 |
223 | llog.Info("looks delicious")
224 |
225 | err := json.Unmarshal(buffer.Bytes(), &fields)
226 | assert.NoError(t, err, "should have decoded first message")
227 | assert.Equal(t, len(fields), 4, "should only have msg/time/level/context fields")
228 | assert.Equal(t, fields["msg"], "looks delicious")
229 | assert.Equal(t, fields["context"], "eating raw fish")
230 |
231 | buffer.Reset()
232 |
233 | llog.Warn("omg it is!")
234 |
235 | err = json.Unmarshal(buffer.Bytes(), &fields)
236 | assert.NoError(t, err, "should have decoded second message")
237 | assert.Equal(t, len(fields), 4, "should only have msg/time/level/context fields")
238 | assert.Equal(t, fields["msg"], "omg it is!")
239 | assert.Equal(t, fields["context"], "eating raw fish")
240 | assert.Nil(t, fields["fields.msg"], "should not have prefixed previous `msg` entry")
241 |
242 | }
243 |
244 | func TestConvertLevelToString(t *testing.T) {
245 | assert.Equal(t, "debug", DebugLevel.String())
246 | assert.Equal(t, "info", InfoLevel.String())
247 | assert.Equal(t, "warning", WarnLevel.String())
248 | assert.Equal(t, "error", ErrorLevel.String())
249 | assert.Equal(t, "fatal", FatalLevel.String())
250 | assert.Equal(t, "panic", PanicLevel.String())
251 | }
252 |
253 | func TestParseLevel(t *testing.T) {
254 | l, err := ParseLevel("panic")
255 | assert.Nil(t, err)
256 | assert.Equal(t, PanicLevel, l)
257 |
258 | l, err = ParseLevel("fatal")
259 | assert.Nil(t, err)
260 | assert.Equal(t, FatalLevel, l)
261 |
262 | l, err = ParseLevel("error")
263 | assert.Nil(t, err)
264 | assert.Equal(t, ErrorLevel, l)
265 |
266 | l, err = ParseLevel("warn")
267 | assert.Nil(t, err)
268 | assert.Equal(t, WarnLevel, l)
269 |
270 | l, err = ParseLevel("warning")
271 | assert.Nil(t, err)
272 | assert.Equal(t, WarnLevel, l)
273 |
274 | l, err = ParseLevel("info")
275 | assert.Nil(t, err)
276 | assert.Equal(t, InfoLevel, l)
277 |
278 | l, err = ParseLevel("debug")
279 | assert.Nil(t, err)
280 | assert.Equal(t, DebugLevel, l)
281 |
282 | l, err = ParseLevel("invalid")
283 | assert.Equal(t, "not a valid logrus Level: \"invalid\"", err.Error())
284 | }
285 |
286 | func TestGetSetLevelRace(t *testing.T) {
287 | wg := sync.WaitGroup{}
288 | for i := 0; i < 100; i++ {
289 | wg.Add(1)
290 | go func(i int) {
291 | defer wg.Done()
292 | if i%2 == 0 {
293 | SetLevel(InfoLevel)
294 | } else {
295 | GetLevel()
296 | }
297 | }(i)
298 |
299 | }
300 | wg.Wait()
301 | }
302 |
--------------------------------------------------------------------------------
/Godeps/_workspace/src/github.com/Sirupsen/logrus/terminal_darwin.go:
--------------------------------------------------------------------------------
1 | // Based on ssh/terminal:
2 | // Copyright 2013 The Go Authors. All rights reserved.
3 | // Use of this source code is governed by a BSD-style
4 | // license that can be found in the LICENSE file.
5 |
6 | package logrus
7 |
8 | import "syscall"
9 |
10 | const ioctlReadTermios = syscall.TIOCGETA
11 |
12 | type Termios syscall.Termios
13 |
--------------------------------------------------------------------------------
/Godeps/_workspace/src/github.com/Sirupsen/logrus/terminal_freebsd.go:
--------------------------------------------------------------------------------
1 | /*
2 | Go 1.2 doesn't include Termios for FreeBSD. This should be added in 1.3 and this could be merged with terminal_darwin.
3 | */
4 | package logrus
5 |
6 | import (
7 | "syscall"
8 | )
9 |
10 | const ioctlReadTermios = syscall.TIOCGETA
11 |
12 | type Termios struct {
13 | Iflag uint32
14 | Oflag uint32
15 | Cflag uint32
16 | Lflag uint32
17 | Cc [20]uint8
18 | Ispeed uint32
19 | Ospeed uint32
20 | }
21 |
--------------------------------------------------------------------------------
/Godeps/_workspace/src/github.com/Sirupsen/logrus/terminal_linux.go:
--------------------------------------------------------------------------------
1 | // Based on ssh/terminal:
2 | // Copyright 2013 The Go Authors. All rights reserved.
3 | // Use of this source code is governed by a BSD-style
4 | // license that can be found in the LICENSE file.
5 |
6 | package logrus
7 |
8 | import "syscall"
9 |
10 | const ioctlReadTermios = syscall.TCGETS
11 |
12 | type Termios syscall.Termios
13 |
--------------------------------------------------------------------------------
/Godeps/_workspace/src/github.com/Sirupsen/logrus/terminal_notwindows.go:
--------------------------------------------------------------------------------
1 | // Based on ssh/terminal:
2 | // Copyright 2011 The Go Authors. All rights reserved.
3 | // Use of this source code is governed by a BSD-style
4 | // license that can be found in the LICENSE file.
5 |
6 | // +build linux darwin freebsd openbsd
7 |
8 | package logrus
9 |
10 | import (
11 | "syscall"
12 | "unsafe"
13 | )
14 |
15 | // IsTerminal returns true if the given file descriptor is a terminal.
16 | func IsTerminal() bool {
17 | fd := syscall.Stdout
18 | var termios Termios
19 | _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlReadTermios, uintptr(unsafe.Pointer(&termios)), 0, 0, 0)
20 | return err == 0
21 | }
22 |
--------------------------------------------------------------------------------
/Godeps/_workspace/src/github.com/Sirupsen/logrus/terminal_openbsd.go:
--------------------------------------------------------------------------------
1 |
2 | package logrus
3 |
4 | import "syscall"
5 |
6 | const ioctlReadTermios = syscall.TIOCGETA
7 |
8 | type Termios syscall.Termios
9 |
--------------------------------------------------------------------------------
/Godeps/_workspace/src/github.com/Sirupsen/logrus/terminal_windows.go:
--------------------------------------------------------------------------------
1 | // Based on ssh/terminal:
2 | // Copyright 2011 The Go Authors. All rights reserved.
3 | // Use of this source code is governed by a BSD-style
4 | // license that can be found in the LICENSE file.
5 |
6 | // +build windows
7 |
8 | package logrus
9 |
10 | import (
11 | "syscall"
12 | "unsafe"
13 | )
14 |
15 | var kernel32 = syscall.NewLazyDLL("kernel32.dll")
16 |
17 | var (
18 | procGetConsoleMode = kernel32.NewProc("GetConsoleMode")
19 | )
20 |
21 | // IsTerminal returns true if the given file descriptor is a terminal.
22 | func IsTerminal() bool {
23 | fd := syscall.Stdout
24 | var st uint32
25 | r, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, uintptr(fd), uintptr(unsafe.Pointer(&st)), 0)
26 | return r != 0 && e == 0
27 | }
28 |
--------------------------------------------------------------------------------
/Godeps/_workspace/src/github.com/Sirupsen/logrus/text_formatter.go:
--------------------------------------------------------------------------------
1 | package logrus
2 |
3 | import (
4 | "bytes"
5 | "fmt"
6 | "regexp"
7 | "sort"
8 | "strings"
9 | "time"
10 | )
11 |
12 | const (
13 | nocolor = 0
14 | red = 31
15 | green = 32
16 | yellow = 33
17 | blue = 34
18 | gray = 37
19 | )
20 |
21 | var (
22 | baseTimestamp time.Time
23 | isTerminal bool
24 | noQuoteNeeded *regexp.Regexp
25 | )
26 |
27 | func init() {
28 | baseTimestamp = time.Now()
29 | isTerminal = IsTerminal()
30 | }
31 |
32 | func miniTS() int {
33 | return int(time.Since(baseTimestamp) / time.Second)
34 | }
35 |
36 | type TextFormatter struct {
37 | // Set to true to bypass checking for a TTY before outputting colors.
38 | ForceColors bool
39 |
40 | // Force disabling colors.
41 | DisableColors bool
42 |
43 | // Disable timestamp logging. useful when output is redirected to logging
44 | // system that already adds timestamps.
45 | DisableTimestamp bool
46 |
47 | // Enable logging the full timestamp when a TTY is attached instead of just
48 | // the time passed since beginning of execution.
49 | FullTimestamp bool
50 |
51 | // The fields are sorted by default for a consistent output. For applications
52 | // that log extremely frequently and don't use the JSON formatter this may not
53 | // be desired.
54 | DisableSorting bool
55 | }
56 |
57 | func (f *TextFormatter) Format(entry *Entry) ([]byte, error) {
58 | var keys []string = make([]string, 0, len(entry.Data))
59 | for k := range entry.Data {
60 | keys = append(keys, k)
61 | }
62 |
63 | if !f.DisableSorting {
64 | sort.Strings(keys)
65 | }
66 |
67 | b := &bytes.Buffer{}
68 |
69 | prefixFieldClashes(entry.Data)
70 |
71 | isColored := (f.ForceColors || isTerminal) && !f.DisableColors
72 |
73 | if isColored {
74 | f.printColored(b, entry, keys)
75 | } else {
76 | if !f.DisableTimestamp {
77 | f.appendKeyValue(b, "time", entry.Time.Format(time.RFC3339))
78 | }
79 | f.appendKeyValue(b, "level", entry.Level.String())
80 | f.appendKeyValue(b, "msg", entry.Message)
81 | for _, key := range keys {
82 | f.appendKeyValue(b, key, entry.Data[key])
83 | }
84 | }
85 |
86 | b.WriteByte('\n')
87 | return b.Bytes(), nil
88 | }
89 |
90 | func (f *TextFormatter) printColored(b *bytes.Buffer, entry *Entry, keys []string) {
91 | var levelColor int
92 | switch entry.Level {
93 | case DebugLevel:
94 | levelColor = gray
95 | case WarnLevel:
96 | levelColor = yellow
97 | case ErrorLevel, FatalLevel, PanicLevel:
98 | levelColor = red
99 | default:
100 | levelColor = blue
101 | }
102 |
103 | levelText := strings.ToUpper(entry.Level.String())[0:4]
104 |
105 | if !f.FullTimestamp {
106 | fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%04d] %-44s ", levelColor, levelText, miniTS(), entry.Message)
107 | } else {
108 | fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%s] %-44s ", levelColor, levelText, entry.Time.Format(time.RFC3339), entry.Message)
109 | }
110 | for _, k := range keys {
111 | v := entry.Data[k]
112 | fmt.Fprintf(b, " \x1b[%dm%s\x1b[0m=%v", levelColor, k, v)
113 | }
114 | }
115 |
116 | func needsQuoting(text string) bool {
117 | for _, ch := range text {
118 | if !((ch >= 'a' && ch <= 'z') ||
119 | (ch >= 'A' && ch <= 'Z') ||
120 | (ch >= '0' && ch <= '9') ||
121 | ch == '-' || ch == '.') {
122 | return false
123 | }
124 | }
125 | return true
126 | }
127 |
128 | func (f *TextFormatter) appendKeyValue(b *bytes.Buffer, key, value interface{}) {
129 | switch value.(type) {
130 | case string:
131 | if needsQuoting(value.(string)) {
132 | fmt.Fprintf(b, "%v=%s ", key, value)
133 | } else {
134 | fmt.Fprintf(b, "%v=%q ", key, value)
135 | }
136 | case error:
137 | if needsQuoting(value.(error).Error()) {
138 | fmt.Fprintf(b, "%v=%s ", key, value)
139 | } else {
140 | fmt.Fprintf(b, "%v=%q ", key, value)
141 | }
142 | default:
143 | fmt.Fprintf(b, "%v=%v ", key, value)
144 | }
145 | }
146 |
--------------------------------------------------------------------------------
/Godeps/_workspace/src/github.com/Sirupsen/logrus/text_formatter_test.go:
--------------------------------------------------------------------------------
1 | package logrus
2 |
3 | import (
4 | "bytes"
5 | "errors"
6 |
7 | "testing"
8 | )
9 |
10 | func TestQuoting(t *testing.T) {
11 | tf := &TextFormatter{DisableColors: true}
12 |
13 | checkQuoting := func(q bool, value interface{}) {
14 | b, _ := tf.Format(WithField("test", value))
15 | idx := bytes.Index(b, ([]byte)("test="))
16 | cont := bytes.Contains(b[idx+5:], []byte{'"'})
17 | if cont != q {
18 | if q {
19 | t.Errorf("quoting expected for: %#v", value)
20 | } else {
21 | t.Errorf("quoting not expected for: %#v", value)
22 | }
23 | }
24 | }
25 |
26 | checkQuoting(false, "abcd")
27 | checkQuoting(false, "v1.0")
28 | checkQuoting(false, "1234567890")
29 | checkQuoting(true, "/foobar")
30 | checkQuoting(true, "x y")
31 | checkQuoting(true, "x,y")
32 | checkQuoting(false, errors.New("invalid"))
33 | checkQuoting(true, errors.New("invalid argument"))
34 | }
35 |
36 | // TODO add tests for sorting etc., this requires a parser for the text
37 | // formatter output.
38 |
--------------------------------------------------------------------------------
/Godeps/_workspace/src/github.com/Sirupsen/logrus/writer.go:
--------------------------------------------------------------------------------
1 | package logrus
2 |
3 | import (
4 | "bufio"
5 | "io"
6 | "runtime"
7 | )
8 |
9 | func (logger *Logger) Writer() (*io.PipeWriter) {
10 | reader, writer := io.Pipe()
11 |
12 | go logger.writerScanner(reader)
13 | runtime.SetFinalizer(writer, writerFinalizer)
14 |
15 | return writer
16 | }
17 |
18 | func (logger *Logger) writerScanner(reader *io.PipeReader) {
19 | scanner := bufio.NewScanner(reader)
20 | for scanner.Scan() {
21 | logger.Print(scanner.Text())
22 | }
23 | if err := scanner.Err(); err != nil {
24 | logger.Errorf("Error while reading from Writer: %s", err)
25 | }
26 | reader.Close()
27 | }
28 |
29 | func writerFinalizer(writer *io.PipeWriter) {
30 | writer.Close()
31 | }
32 |
--------------------------------------------------------------------------------
/Godeps/_workspace/src/golang.org/x/crypto/ssh/agent/client_test.go:
--------------------------------------------------------------------------------
1 | // Copyright 2012 The Go Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style
3 | // license that can be found in the LICENSE file.
4 |
5 | package agent
6 |
7 | import (
8 | "bytes"
9 | "crypto/rand"
10 | "errors"
11 | "net"
12 | "os"
13 | "os/exec"
14 | "path/filepath"
15 | "strconv"
16 | "testing"
17 |
18 | "golang.org/x/crypto/ssh"
19 | )
20 |
21 | // startAgent executes ssh-agent, and returns a Agent interface to it.
22 | func startAgent(t *testing.T) (client Agent, socket string, cleanup func()) {
23 | if testing.Short() {
24 | // ssh-agent is not always available, and the key
25 | // types supported vary by platform.
26 | t.Skip("skipping test due to -short")
27 | }
28 |
29 | bin, err := exec.LookPath("ssh-agent")
30 | if err != nil {
31 | t.Skip("could not find ssh-agent")
32 | }
33 |
34 | cmd := exec.Command(bin, "-s")
35 | out, err := cmd.Output()
36 | if err != nil {
37 | t.Fatalf("cmd.Output: %v", err)
38 | }
39 |
40 | /* Output looks like:
41 |
42 | SSH_AUTH_SOCK=/tmp/ssh-P65gpcqArqvH/agent.15541; export SSH_AUTH_SOCK;
43 | SSH_AGENT_PID=15542; export SSH_AGENT_PID;
44 | echo Agent pid 15542;
45 | */
46 | fields := bytes.Split(out, []byte(";"))
47 | line := bytes.SplitN(fields[0], []byte("="), 2)
48 | line[0] = bytes.TrimLeft(line[0], "\n")
49 | if string(line[0]) != "SSH_AUTH_SOCK" {
50 | t.Fatalf("could not find key SSH_AUTH_SOCK in %q", fields[0])
51 | }
52 | socket = string(line[1])
53 |
54 | line = bytes.SplitN(fields[2], []byte("="), 2)
55 | line[0] = bytes.TrimLeft(line[0], "\n")
56 | if string(line[0]) != "SSH_AGENT_PID" {
57 | t.Fatalf("could not find key SSH_AGENT_PID in %q", fields[2])
58 | }
59 | pidStr := line[1]
60 | pid, err := strconv.Atoi(string(pidStr))
61 | if err != nil {
62 | t.Fatalf("Atoi(%q): %v", pidStr, err)
63 | }
64 |
65 | conn, err := net.Dial("unix", string(socket))
66 | if err != nil {
67 | t.Fatalf("net.Dial: %v", err)
68 | }
69 |
70 | ac := NewClient(conn)
71 | return ac, socket, func() {
72 | proc, _ := os.FindProcess(pid)
73 | if proc != nil {
74 | proc.Kill()
75 | }
76 | conn.Close()
77 | os.RemoveAll(filepath.Dir(socket))
78 | }
79 | }
80 |
81 | func testAgent(t *testing.T, key interface{}, cert *ssh.Certificate) {
82 | agent, _, cleanup := startAgent(t)
83 | defer cleanup()
84 |
85 | testAgentInterface(t, agent, key, cert)
86 | }
87 |
88 | func testAgentInterface(t *testing.T, agent Agent, key interface{}, cert *ssh.Certificate) {
89 | signer, err := ssh.NewSignerFromKey(key)
90 | if err != nil {
91 | t.Fatalf("NewSignerFromKey(%T): %v", key, err)
92 | }
93 | // The agent should start up empty.
94 | if keys, err := agent.List(); err != nil {
95 | t.Fatalf("RequestIdentities: %v", err)
96 | } else if len(keys) > 0 {
97 | t.Fatalf("got %d keys, want 0: %v", len(keys), keys)
98 | }
99 |
100 | // Attempt to insert the key, with certificate if specified.
101 | var pubKey ssh.PublicKey
102 | if cert != nil {
103 | err = agent.Add(key, cert, "comment")
104 | pubKey = cert
105 | } else {
106 | err = agent.Add(key, nil, "comment")
107 | pubKey = signer.PublicKey()
108 | }
109 | if err != nil {
110 | t.Fatalf("insert(%T): %v", key, err)
111 | }
112 |
113 | // Did the key get inserted successfully?
114 | if keys, err := agent.List(); err != nil {
115 | t.Fatalf("List: %v", err)
116 | } else if len(keys) != 1 {
117 | t.Fatalf("got %v, want 1 key", keys)
118 | } else if keys[0].Comment != "comment" {
119 | t.Fatalf("key comment: got %v, want %v", keys[0].Comment, "comment")
120 | } else if !bytes.Equal(keys[0].Blob, pubKey.Marshal()) {
121 | t.Fatalf("key mismatch")
122 | }
123 |
124 | // Can the agent make a valid signature?
125 | data := []byte("hello")
126 | sig, err := agent.Sign(pubKey, data)
127 | if err != nil {
128 | t.Fatalf("Sign(%s): %v", pubKey.Type(), err)
129 | }
130 |
131 | if err := pubKey.Verify(data, sig); err != nil {
132 | t.Fatalf("Verify(%s): %v", pubKey.Type(), err)
133 | }
134 | }
135 |
136 | func TestAgent(t *testing.T) {
137 | for _, keyType := range []string{"rsa", "dsa", "ecdsa"} {
138 | testAgent(t, testPrivateKeys[keyType], nil)
139 | }
140 | }
141 |
142 | func TestCert(t *testing.T) {
143 | cert := &ssh.Certificate{
144 | Key: testPublicKeys["rsa"],
145 | ValidBefore: ssh.CertTimeInfinity,
146 | CertType: ssh.UserCert,
147 | }
148 | cert.SignCert(rand.Reader, testSigners["ecdsa"])
149 |
150 | testAgent(t, testPrivateKeys["rsa"], cert)
151 | }
152 |
153 | // netPipe is analogous to net.Pipe, but it uses a real net.Conn, and
154 | // therefore is buffered (net.Pipe deadlocks if both sides start with
155 | // a write.)
156 | func netPipe() (net.Conn, net.Conn, error) {
157 | listener, err := net.Listen("tcp", "127.0.0.1:0")
158 | if err != nil {
159 | return nil, nil, err
160 | }
161 | defer listener.Close()
162 | c1, err := net.Dial("tcp", listener.Addr().String())
163 | if err != nil {
164 | return nil, nil, err
165 | }
166 |
167 | c2, err := listener.Accept()
168 | if err != nil {
169 | c1.Close()
170 | return nil, nil, err
171 | }
172 |
173 | return c1, c2, nil
174 | }
175 |
176 | func TestAuth(t *testing.T) {
177 | a, b, err := netPipe()
178 | if err != nil {
179 | t.Fatalf("netPipe: %v", err)
180 | }
181 |
182 | defer a.Close()
183 | defer b.Close()
184 |
185 | agent, _, cleanup := startAgent(t)
186 | defer cleanup()
187 |
188 | if err := agent.Add(testPrivateKeys["rsa"], nil, "comment"); err != nil {
189 | t.Errorf("Add: %v", err)
190 | }
191 |
192 | serverConf := ssh.ServerConfig{}
193 | serverConf.AddHostKey(testSigners["rsa"])
194 | serverConf.PublicKeyCallback = func(c ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error) {
195 | if bytes.Equal(key.Marshal(), testPublicKeys["rsa"].Marshal()) {
196 | return nil, nil
197 | }
198 |
199 | return nil, errors.New("pubkey rejected")
200 | }
201 |
202 | go func() {
203 | conn, _, _, err := ssh.NewServerConn(a, &serverConf)
204 | if err != nil {
205 | t.Fatalf("Server: %v", err)
206 | }
207 | conn.Close()
208 | }()
209 |
210 | conf := ssh.ClientConfig{}
211 | conf.Auth = append(conf.Auth, ssh.PublicKeysCallback(agent.Signers))
212 | conn, _, _, err := ssh.NewClientConn(b, "", &conf)
213 | if err != nil {
214 | t.Fatalf("NewClientConn: %v", err)
215 | }
216 | conn.Close()
217 | }
218 |
219 | func TestLockClient(t *testing.T) {
220 | agent, _, cleanup := startAgent(t)
221 | defer cleanup()
222 | testLockAgent(agent, t)
223 | }
224 |
225 | func testLockAgent(agent Agent, t *testing.T) {
226 | if err := agent.Add(testPrivateKeys["rsa"], nil, "comment 1"); err != nil {
227 | t.Errorf("Add: %v", err)
228 | }
229 | if err := agent.Add(testPrivateKeys["dsa"], nil, "comment dsa"); err != nil {
230 | t.Errorf("Add: %v", err)
231 | }
232 | if keys, err := agent.List(); err != nil {
233 | t.Errorf("List: %v", err)
234 | } else if len(keys) != 2 {
235 | t.Errorf("Want 2 keys, got %v", keys)
236 | }
237 |
238 | passphrase := []byte("secret")
239 | if err := agent.Lock(passphrase); err != nil {
240 | t.Errorf("Lock: %v", err)
241 | }
242 |
243 | if keys, err := agent.List(); err != nil {
244 | t.Errorf("List: %v", err)
245 | } else if len(keys) != 0 {
246 | t.Errorf("Want 0 keys, got %v", keys)
247 | }
248 |
249 | signer, _ := ssh.NewSignerFromKey(testPrivateKeys["rsa"])
250 | if _, err := agent.Sign(signer.PublicKey(), []byte("hello")); err == nil {
251 | t.Fatalf("Sign did not fail")
252 | }
253 |
254 | if err := agent.Remove(signer.PublicKey()); err == nil {
255 | t.Fatalf("Remove did not fail")
256 | }
257 |
258 | if err := agent.RemoveAll(); err == nil {
259 | t.Fatalf("RemoveAll did not fail")
260 | }
261 |
262 | if err := agent.Unlock(nil); err == nil {
263 | t.Errorf("Unlock with wrong passphrase succeeded")
264 | }
265 | if err := agent.Unlock(passphrase); err != nil {
266 | t.Errorf("Unlock: %v", err)
267 | }
268 |
269 | if err := agent.Remove(signer.PublicKey()); err != nil {
270 | t.Fatalf("Remove: %v", err)
271 | }
272 |
273 | if keys, err := agent.List(); err != nil {
274 | t.Errorf("List: %v", err)
275 | } else if len(keys) != 1 {
276 | t.Errorf("Want 1 keys, got %v", keys)
277 | }
278 | }
279 |
--------------------------------------------------------------------------------
/Godeps/_workspace/src/golang.org/x/crypto/ssh/agent/forward.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014 The Go Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style
3 | // license that can be found in the LICENSE file.
4 |
5 | package agent
6 |
7 | import (
8 | "errors"
9 | "io"
10 | "net"
11 | "sync"
12 |
13 | "golang.org/x/crypto/ssh"
14 | )
15 |
16 | // RequestAgentForwarding sets up agent forwarding for the session.
17 | // ForwardToAgent or ForwardToRemote should be called to route
18 | // the authentication requests.
19 | func RequestAgentForwarding(session *ssh.Session) error {
20 | ok, err := session.SendRequest("auth-agent-req@openssh.com", true, nil)
21 | if err != nil {
22 | return err
23 | }
24 | if !ok {
25 | return errors.New("forwarding request denied")
26 | }
27 | return nil
28 | }
29 |
30 | // ForwardToAgent routes authentication requests to the given keyring.
31 | func ForwardToAgent(client *ssh.Client, keyring Agent) error {
32 | channels := client.HandleChannelOpen(channelType)
33 | if channels == nil {
34 | return errors.New("agent: already have handler for " + channelType)
35 | }
36 |
37 | go func() {
38 | for ch := range channels {
39 | channel, reqs, err := ch.Accept()
40 | if err != nil {
41 | continue
42 | }
43 | go ssh.DiscardRequests(reqs)
44 | go func() {
45 | ServeAgent(keyring, channel)
46 | channel.Close()
47 | }()
48 | }
49 | }()
50 | return nil
51 | }
52 |
53 | const channelType = "auth-agent@openssh.com"
54 |
55 | // ForwardToRemote routes authentication requests to the ssh-agent
56 | // process serving on the given unix socket.
57 | func ForwardToRemote(client *ssh.Client, addr string) error {
58 | channels := client.HandleChannelOpen(channelType)
59 | if channels == nil {
60 | return errors.New("agent: already have handler for " + channelType)
61 | }
62 | conn, err := net.Dial("unix", addr)
63 | if err != nil {
64 | return err
65 | }
66 | conn.Close()
67 |
68 | go func() {
69 | for ch := range channels {
70 | channel, reqs, err := ch.Accept()
71 | if err != nil {
72 | continue
73 | }
74 | go ssh.DiscardRequests(reqs)
75 | go forwardUnixSocket(channel, addr)
76 | }
77 | }()
78 | return nil
79 | }
80 |
81 | func forwardUnixSocket(channel ssh.Channel, addr string) {
82 | conn, err := net.Dial("unix", addr)
83 | if err != nil {
84 | return
85 | }
86 |
87 | var wg sync.WaitGroup
88 | wg.Add(2)
89 | go func() {
90 | io.Copy(conn, channel)
91 | conn.(*net.UnixConn).CloseWrite()
92 | wg.Done()
93 | }()
94 | go func() {
95 | io.Copy(channel, conn)
96 | channel.CloseWrite()
97 | wg.Done()
98 | }()
99 |
100 | wg.Wait()
101 | conn.Close()
102 | channel.Close()
103 | }
104 |
--------------------------------------------------------------------------------
/Godeps/_workspace/src/golang.org/x/crypto/ssh/agent/keyring.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014 The Go Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style
3 | // license that can be found in the LICENSE file.
4 |
5 | package agent
6 |
7 | import (
8 | "bytes"
9 | "crypto/rand"
10 | "crypto/subtle"
11 | "errors"
12 | "fmt"
13 | "sync"
14 |
15 | "golang.org/x/crypto/ssh"
16 | )
17 |
18 | type privKey struct {
19 | signer ssh.Signer
20 | comment string
21 | }
22 |
23 | type keyring struct {
24 | mu sync.Mutex
25 | keys []privKey
26 |
27 | locked bool
28 | passphrase []byte
29 | }
30 |
31 | var errLocked = errors.New("agent: locked")
32 |
33 | // NewKeyring returns an Agent that holds keys in memory. It is safe
34 | // for concurrent use by multiple goroutines.
35 | func NewKeyring() Agent {
36 | return &keyring{}
37 | }
38 |
39 | // RemoveAll removes all identities.
40 | func (r *keyring) RemoveAll() error {
41 | r.mu.Lock()
42 | defer r.mu.Unlock()
43 | if r.locked {
44 | return errLocked
45 | }
46 |
47 | r.keys = nil
48 | return nil
49 | }
50 |
51 | // Remove removes all identities with the given public key.
52 | func (r *keyring) Remove(key ssh.PublicKey) error {
53 | r.mu.Lock()
54 | defer r.mu.Unlock()
55 | if r.locked {
56 | return errLocked
57 | }
58 |
59 | want := key.Marshal()
60 | found := false
61 | for i := 0; i < len(r.keys); {
62 | if bytes.Equal(r.keys[i].signer.PublicKey().Marshal(), want) {
63 | found = true
64 | r.keys[i] = r.keys[len(r.keys)-1]
65 | r.keys = r.keys[len(r.keys)-1:]
66 | continue
67 | } else {
68 | i++
69 | }
70 | }
71 |
72 | if !found {
73 | return errors.New("agent: key not found")
74 | }
75 | return nil
76 | }
77 |
78 | // Lock locks the agent. Sign and Remove will fail, and List will empty an empty list.
79 | func (r *keyring) Lock(passphrase []byte) error {
80 | r.mu.Lock()
81 | defer r.mu.Unlock()
82 | if r.locked {
83 | return errLocked
84 | }
85 |
86 | r.locked = true
87 | r.passphrase = passphrase
88 | return nil
89 | }
90 |
91 | // Unlock undoes the effect of Lock
92 | func (r *keyring) Unlock(passphrase []byte) error {
93 | r.mu.Lock()
94 | defer r.mu.Unlock()
95 | if !r.locked {
96 | return errors.New("agent: not locked")
97 | }
98 | if len(passphrase) != len(r.passphrase) || 1 != subtle.ConstantTimeCompare(passphrase, r.passphrase) {
99 | return fmt.Errorf("agent: incorrect passphrase")
100 | }
101 |
102 | r.locked = false
103 | r.passphrase = nil
104 | return nil
105 | }
106 |
107 | // List returns the identities known to the agent.
108 | func (r *keyring) List() ([]*Key, error) {
109 | r.mu.Lock()
110 | defer r.mu.Unlock()
111 | if r.locked {
112 | // section 2.7: locked agents return empty.
113 | return nil, nil
114 | }
115 |
116 | var ids []*Key
117 | for _, k := range r.keys {
118 | pub := k.signer.PublicKey()
119 | ids = append(ids, &Key{
120 | Format: pub.Type(),
121 | Blob: pub.Marshal(),
122 | Comment: k.comment})
123 | }
124 | return ids, nil
125 | }
126 |
127 | // Insert adds a private key to the keyring. If a certificate
128 | // is given, that certificate is added as public key.
129 | func (r *keyring) Add(priv interface{}, cert *ssh.Certificate, comment string) error {
130 | r.mu.Lock()
131 | defer r.mu.Unlock()
132 | if r.locked {
133 | return errLocked
134 | }
135 | signer, err := ssh.NewSignerFromKey(priv)
136 |
137 | if err != nil {
138 | return err
139 | }
140 |
141 | if cert != nil {
142 | signer, err = ssh.NewCertSigner(cert, signer)
143 | if err != nil {
144 | return err
145 | }
146 | }
147 |
148 | r.keys = append(r.keys, privKey{signer, comment})
149 |
150 | return nil
151 | }
152 |
153 | // Sign returns a signature for the data.
154 | func (r *keyring) Sign(key ssh.PublicKey, data []byte) (*ssh.Signature, error) {
155 | r.mu.Lock()
156 | defer r.mu.Unlock()
157 | if r.locked {
158 | return nil, errLocked
159 | }
160 |
161 | wanted := key.Marshal()
162 | for _, k := range r.keys {
163 | if bytes.Equal(k.signer.PublicKey().Marshal(), wanted) {
164 | return k.signer.Sign(rand.Reader, data)
165 | }
166 | }
167 | return nil, errors.New("not found")
168 | }
169 |
170 | // Signers returns signers for all the known keys.
171 | func (r *keyring) Signers() ([]ssh.Signer, error) {
172 | r.mu.Lock()
173 | defer r.mu.Unlock()
174 | if r.locked {
175 | return nil, errLocked
176 | }
177 |
178 | s := make([]ssh.Signer, 0, len(r.keys))
179 | for _, k := range r.keys {
180 | s = append(s, k.signer)
181 | }
182 | return s, nil
183 | }
184 |
--------------------------------------------------------------------------------
/Godeps/_workspace/src/golang.org/x/crypto/ssh/agent/server.go:
--------------------------------------------------------------------------------
1 | // Copyright 2012 The Go Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style
3 | // license that can be found in the LICENSE file.
4 |
5 | package agent
6 |
7 | import (
8 | "crypto/rsa"
9 | "encoding/binary"
10 | "fmt"
11 | "io"
12 | "log"
13 | "math/big"
14 |
15 | "golang.org/x/crypto/ssh"
16 | )
17 |
18 | // Server wraps an Agent and uses it to implement the agent side of
19 | // the SSH-agent, wire protocol.
20 | type server struct {
21 | agent Agent
22 | }
23 |
24 | func (s *server) processRequestBytes(reqData []byte) []byte {
25 | rep, err := s.processRequest(reqData)
26 | if err != nil {
27 | if err != errLocked {
28 | // TODO(hanwen): provide better logging interface?
29 | log.Printf("agent %d: %v", reqData[0], err)
30 | }
31 | return []byte{agentFailure}
32 | }
33 |
34 | if err == nil && rep == nil {
35 | return []byte{agentSuccess}
36 | }
37 |
38 | return ssh.Marshal(rep)
39 | }
40 |
41 | func marshalKey(k *Key) []byte {
42 | var record struct {
43 | Blob []byte
44 | Comment string
45 | }
46 | record.Blob = k.Marshal()
47 | record.Comment = k.Comment
48 |
49 | return ssh.Marshal(&record)
50 | }
51 |
52 | type agentV1IdentityMsg struct {
53 | Numkeys uint32 `sshtype:"2"`
54 | }
55 |
56 | type agentRemoveIdentityMsg struct {
57 | KeyBlob []byte `sshtype:"18"`
58 | }
59 |
60 | type agentLockMsg struct {
61 | Passphrase []byte `sshtype:"22"`
62 | }
63 |
64 | type agentUnlockMsg struct {
65 | Passphrase []byte `sshtype:"23"`
66 | }
67 |
68 | func (s *server) processRequest(data []byte) (interface{}, error) {
69 | switch data[0] {
70 | case agentRequestV1Identities:
71 | return &agentV1IdentityMsg{0}, nil
72 | case agentRemoveIdentity:
73 | var req agentRemoveIdentityMsg
74 | if err := ssh.Unmarshal(data, &req); err != nil {
75 | return nil, err
76 | }
77 |
78 | var wk wireKey
79 | if err := ssh.Unmarshal(req.KeyBlob, &wk); err != nil {
80 | return nil, err
81 | }
82 |
83 | return nil, s.agent.Remove(&Key{Format: wk.Format, Blob: req.KeyBlob})
84 |
85 | case agentRemoveAllIdentities:
86 | return nil, s.agent.RemoveAll()
87 |
88 | case agentLock:
89 | var req agentLockMsg
90 | if err := ssh.Unmarshal(data, &req); err != nil {
91 | return nil, err
92 | }
93 |
94 | return nil, s.agent.Lock(req.Passphrase)
95 |
96 | case agentUnlock:
97 | var req agentLockMsg
98 | if err := ssh.Unmarshal(data, &req); err != nil {
99 | return nil, err
100 | }
101 | return nil, s.agent.Unlock(req.Passphrase)
102 |
103 | case agentSignRequest:
104 | var req signRequestAgentMsg
105 | if err := ssh.Unmarshal(data, &req); err != nil {
106 | return nil, err
107 | }
108 |
109 | var wk wireKey
110 | if err := ssh.Unmarshal(req.KeyBlob, &wk); err != nil {
111 | return nil, err
112 | }
113 |
114 | k := &Key{
115 | Format: wk.Format,
116 | Blob: req.KeyBlob,
117 | }
118 |
119 | sig, err := s.agent.Sign(k, req.Data) // TODO(hanwen): flags.
120 | if err != nil {
121 | return nil, err
122 | }
123 | return &signResponseAgentMsg{SigBlob: ssh.Marshal(sig)}, nil
124 | case agentRequestIdentities:
125 | keys, err := s.agent.List()
126 | if err != nil {
127 | return nil, err
128 | }
129 |
130 | rep := identitiesAnswerAgentMsg{
131 | NumKeys: uint32(len(keys)),
132 | }
133 | for _, k := range keys {
134 | rep.Keys = append(rep.Keys, marshalKey(k)...)
135 | }
136 | return rep, nil
137 | case agentAddIdentity:
138 | return nil, s.insertIdentity(data)
139 | }
140 |
141 | return nil, fmt.Errorf("unknown opcode %d", data[0])
142 | }
143 |
144 | func (s *server) insertIdentity(req []byte) error {
145 | var record struct {
146 | Type string `sshtype:"17"`
147 | Rest []byte `ssh:"rest"`
148 | }
149 | if err := ssh.Unmarshal(req, &record); err != nil {
150 | return err
151 | }
152 |
153 | switch record.Type {
154 | case ssh.KeyAlgoRSA:
155 | var k rsaKeyMsg
156 | if err := ssh.Unmarshal(req, &k); err != nil {
157 | return err
158 | }
159 |
160 | priv := rsa.PrivateKey{
161 | PublicKey: rsa.PublicKey{
162 | E: int(k.E.Int64()),
163 | N: k.N,
164 | },
165 | D: k.D,
166 | Primes: []*big.Int{k.P, k.Q},
167 | }
168 | priv.Precompute()
169 |
170 | return s.agent.Add(&priv, nil, k.Comments)
171 | }
172 | return fmt.Errorf("not implemented: %s", record.Type)
173 | }
174 |
175 | // ServeAgent serves the agent protocol on the given connection. It
176 | // returns when an I/O error occurs.
177 | func ServeAgent(agent Agent, c io.ReadWriter) error {
178 | s := &server{agent}
179 |
180 | var length [4]byte
181 | for {
182 | if _, err := io.ReadFull(c, length[:]); err != nil {
183 | return err
184 | }
185 | l := binary.BigEndian.Uint32(length[:])
186 | if l > maxAgentResponseBytes {
187 | // We also cap requests.
188 | return fmt.Errorf("agent: request too large: %d", l)
189 | }
190 |
191 | req := make([]byte, l)
192 | if _, err := io.ReadFull(c, req); err != nil {
193 | return err
194 | }
195 |
196 | repData := s.processRequestBytes(req)
197 | if len(repData) > maxAgentResponseBytes {
198 | return fmt.Errorf("agent: reply too large: %d bytes", len(repData))
199 | }
200 |
201 | binary.BigEndian.PutUint32(length[:], uint32(len(repData)))
202 | if _, err := c.Write(length[:]); err != nil {
203 | return err
204 | }
205 | if _, err := c.Write(repData); err != nil {
206 | return err
207 | }
208 | }
209 | }
210 |
--------------------------------------------------------------------------------
/Godeps/_workspace/src/golang.org/x/crypto/ssh/agent/server_test.go:
--------------------------------------------------------------------------------
1 | // Copyright 2012 The Go Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style
3 | // license that can be found in the LICENSE file.
4 |
5 | package agent
6 |
7 | import (
8 | "testing"
9 |
10 | "golang.org/x/crypto/ssh"
11 | )
12 |
13 | func TestServer(t *testing.T) {
14 | c1, c2, err := netPipe()
15 | if err != nil {
16 | t.Fatalf("netPipe: %v", err)
17 | }
18 | defer c1.Close()
19 | defer c2.Close()
20 | client := NewClient(c1)
21 |
22 | go ServeAgent(NewKeyring(), c2)
23 |
24 | testAgentInterface(t, client, testPrivateKeys["rsa"], nil)
25 | }
26 |
27 | func TestLockServer(t *testing.T) {
28 | testLockAgent(NewKeyring(), t)
29 | }
30 |
31 | func TestSetupForwardAgent(t *testing.T) {
32 | a, b, err := netPipe()
33 | if err != nil {
34 | t.Fatalf("netPipe: %v", err)
35 | }
36 |
37 | defer a.Close()
38 | defer b.Close()
39 |
40 | _, socket, cleanup := startAgent(t)
41 | defer cleanup()
42 |
43 | serverConf := ssh.ServerConfig{
44 | NoClientAuth: true,
45 | }
46 | serverConf.AddHostKey(testSigners["rsa"])
47 | incoming := make(chan *ssh.ServerConn, 1)
48 | go func() {
49 | conn, _, _, err := ssh.NewServerConn(a, &serverConf)
50 | if err != nil {
51 | t.Fatalf("Server: %v", err)
52 | }
53 | incoming <- conn
54 | }()
55 |
56 | conf := ssh.ClientConfig{}
57 | conn, chans, reqs, err := ssh.NewClientConn(b, "", &conf)
58 | if err != nil {
59 | t.Fatalf("NewClientConn: %v", err)
60 | }
61 | client := ssh.NewClient(conn, chans, reqs)
62 |
63 | if err := ForwardToRemote(client, socket); err != nil {
64 | t.Fatalf("SetupForwardAgent: %v", err)
65 | }
66 |
67 | server := <-incoming
68 | ch, reqs, err := server.OpenChannel(channelType, nil)
69 | if err != nil {
70 | t.Fatalf("OpenChannel(%q): %v", channelType, err)
71 | }
72 | go ssh.DiscardRequests(reqs)
73 |
74 | agentClient := NewClient(ch)
75 | testAgentInterface(t, agentClient, testPrivateKeys["rsa"], nil)
76 | conn.Close()
77 | }
78 |
--------------------------------------------------------------------------------
/Godeps/_workspace/src/golang.org/x/crypto/ssh/agent/testdata_test.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014 The Go Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style
3 | // license that can be found in the LICENSE file.
4 |
5 | // IMPLEMENTOR NOTE: To avoid a package loop, this file is in three places:
6 | // ssh/, ssh/agent, and ssh/test/. It should be kept in sync across all three
7 | // instances.
8 |
9 | package agent
10 |
11 | import (
12 | "crypto/rand"
13 | "fmt"
14 |
15 | "golang.org/x/crypto/ssh"
16 | "golang.org/x/crypto/ssh/testdata"
17 | )
18 |
19 | var (
20 | testPrivateKeys map[string]interface{}
21 | testSigners map[string]ssh.Signer
22 | testPublicKeys map[string]ssh.PublicKey
23 | )
24 |
25 | func init() {
26 | var err error
27 |
28 | n := len(testdata.PEMBytes)
29 | testPrivateKeys = make(map[string]interface{}, n)
30 | testSigners = make(map[string]ssh.Signer, n)
31 | testPublicKeys = make(map[string]ssh.PublicKey, n)
32 | for t, k := range testdata.PEMBytes {
33 | testPrivateKeys[t], err = ssh.ParseRawPrivateKey(k)
34 | if err != nil {
35 | panic(fmt.Sprintf("Unable to parse test key %s: %v", t, err))
36 | }
37 | testSigners[t], err = ssh.NewSignerFromKey(testPrivateKeys[t])
38 | if err != nil {
39 | panic(fmt.Sprintf("Unable to create signer for test key %s: %v", t, err))
40 | }
41 | testPublicKeys[t] = testSigners[t].PublicKey()
42 | }
43 |
44 | // Create a cert and sign it for use in tests.
45 | testCert := &ssh.Certificate{
46 | Nonce: []byte{}, // To pass reflect.DeepEqual after marshal & parse, this must be non-nil
47 | ValidPrincipals: []string{"gopher1", "gopher2"}, // increases test coverage
48 | ValidAfter: 0, // unix epoch
49 | ValidBefore: ssh.CertTimeInfinity, // The end of currently representable time.
50 | Reserved: []byte{}, // To pass reflect.DeepEqual after marshal & parse, this must be non-nil
51 | Key: testPublicKeys["ecdsa"],
52 | SignatureKey: testPublicKeys["rsa"],
53 | Permissions: ssh.Permissions{
54 | CriticalOptions: map[string]string{},
55 | Extensions: map[string]string{},
56 | },
57 | }
58 | testCert.SignCert(rand.Reader, testSigners["rsa"])
59 | testPrivateKeys["cert"] = testPrivateKeys["ecdsa"]
60 | testSigners["cert"], err = ssh.NewCertSigner(testCert, testSigners["ecdsa"])
61 | if err != nil {
62 | panic(fmt.Sprintf("Unable to create certificate signer: %v", err))
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/Godeps/_workspace/src/golang.org/x/crypto/ssh/benchmark_test.go:
--------------------------------------------------------------------------------
1 | // Copyright 2013 The Go Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style
3 | // license that can be found in the LICENSE file.
4 |
5 | package ssh
6 |
7 | import (
8 | "errors"
9 | "io"
10 | "net"
11 | "testing"
12 | )
13 |
14 | type server struct {
15 | *ServerConn
16 | chans <-chan NewChannel
17 | }
18 |
19 | func newServer(c net.Conn, conf *ServerConfig) (*server, error) {
20 | sconn, chans, reqs, err := NewServerConn(c, conf)
21 | if err != nil {
22 | return nil, err
23 | }
24 | go DiscardRequests(reqs)
25 | return &server{sconn, chans}, nil
26 | }
27 |
28 | func (s *server) Accept() (NewChannel, error) {
29 | n, ok := <-s.chans
30 | if !ok {
31 | return nil, io.EOF
32 | }
33 | return n, nil
34 | }
35 |
36 | func sshPipe() (Conn, *server, error) {
37 | c1, c2, err := netPipe()
38 | if err != nil {
39 | return nil, nil, err
40 | }
41 |
42 | clientConf := ClientConfig{
43 | User: "user",
44 | }
45 | serverConf := ServerConfig{
46 | NoClientAuth: true,
47 | }
48 | serverConf.AddHostKey(testSigners["ecdsa"])
49 | done := make(chan *server, 1)
50 | go func() {
51 | server, err := newServer(c2, &serverConf)
52 | if err != nil {
53 | done <- nil
54 | }
55 | done <- server
56 | }()
57 |
58 | client, _, reqs, err := NewClientConn(c1, "", &clientConf)
59 | if err != nil {
60 | return nil, nil, err
61 | }
62 |
63 | server := <-done
64 | if server == nil {
65 | return nil, nil, errors.New("server handshake failed.")
66 | }
67 | go DiscardRequests(reqs)
68 |
69 | return client, server, nil
70 | }
71 |
72 | func BenchmarkEndToEnd(b *testing.B) {
73 | b.StopTimer()
74 |
75 | client, server, err := sshPipe()
76 | if err != nil {
77 | b.Fatalf("sshPipe: %v", err)
78 | }
79 |
80 | defer client.Close()
81 | defer server.Close()
82 |
83 | size := (1 << 20)
84 | input := make([]byte, size)
85 | output := make([]byte, size)
86 | b.SetBytes(int64(size))
87 | done := make(chan int, 1)
88 |
89 | go func() {
90 | newCh, err := server.Accept()
91 | if err != nil {
92 | b.Fatalf("Client: %v", err)
93 | }
94 | ch, incoming, err := newCh.Accept()
95 | go DiscardRequests(incoming)
96 | for i := 0; i < b.N; i++ {
97 | if _, err := io.ReadFull(ch, output); err != nil {
98 | b.Fatalf("ReadFull: %v", err)
99 | }
100 | }
101 | ch.Close()
102 | done <- 1
103 | }()
104 |
105 | ch, in, err := client.OpenChannel("speed", nil)
106 | if err != nil {
107 | b.Fatalf("OpenChannel: %v", err)
108 | }
109 | go DiscardRequests(in)
110 |
111 | b.ResetTimer()
112 | b.StartTimer()
113 | for i := 0; i < b.N; i++ {
114 | if _, err := ch.Write(input); err != nil {
115 | b.Fatalf("WriteFull: %v", err)
116 | }
117 | }
118 | ch.Close()
119 | b.StopTimer()
120 |
121 | <-done
122 | }
123 |
--------------------------------------------------------------------------------
/Godeps/_workspace/src/golang.org/x/crypto/ssh/buffer.go:
--------------------------------------------------------------------------------
1 | // Copyright 2012 The Go Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style
3 | // license that can be found in the LICENSE file.
4 |
5 | package ssh
6 |
7 | import (
8 | "io"
9 | "sync"
10 | )
11 |
12 | // buffer provides a linked list buffer for data exchange
13 | // between producer and consumer. Theoretically the buffer is
14 | // of unlimited capacity as it does no allocation of its own.
15 | type buffer struct {
16 | // protects concurrent access to head, tail and closed
17 | *sync.Cond
18 |
19 | head *element // the buffer that will be read first
20 | tail *element // the buffer that will be read last
21 |
22 | closed bool
23 | }
24 |
25 | // An element represents a single link in a linked list.
26 | type element struct {
27 | buf []byte
28 | next *element
29 | }
30 |
31 | // newBuffer returns an empty buffer that is not closed.
32 | func newBuffer() *buffer {
33 | e := new(element)
34 | b := &buffer{
35 | Cond: newCond(),
36 | head: e,
37 | tail: e,
38 | }
39 | return b
40 | }
41 |
42 | // write makes buf available for Read to receive.
43 | // buf must not be modified after the call to write.
44 | func (b *buffer) write(buf []byte) {
45 | b.Cond.L.Lock()
46 | e := &element{buf: buf}
47 | b.tail.next = e
48 | b.tail = e
49 | b.Cond.Signal()
50 | b.Cond.L.Unlock()
51 | }
52 |
53 | // eof closes the buffer. Reads from the buffer once all
54 | // the data has been consumed will receive os.EOF.
55 | func (b *buffer) eof() error {
56 | b.Cond.L.Lock()
57 | b.closed = true
58 | b.Cond.Signal()
59 | b.Cond.L.Unlock()
60 | return nil
61 | }
62 |
63 | // Read reads data from the internal buffer in buf. Reads will block
64 | // if no data is available, or until the buffer is closed.
65 | func (b *buffer) Read(buf []byte) (n int, err error) {
66 | b.Cond.L.Lock()
67 | defer b.Cond.L.Unlock()
68 |
69 | for len(buf) > 0 {
70 | // if there is data in b.head, copy it
71 | if len(b.head.buf) > 0 {
72 | r := copy(buf, b.head.buf)
73 | buf, b.head.buf = buf[r:], b.head.buf[r:]
74 | n += r
75 | continue
76 | }
77 | // if there is a next buffer, make it the head
78 | if len(b.head.buf) == 0 && b.head != b.tail {
79 | b.head = b.head.next
80 | continue
81 | }
82 |
83 | // if at least one byte has been copied, return
84 | if n > 0 {
85 | break
86 | }
87 |
88 | // if nothing was read, and there is nothing outstanding
89 | // check to see if the buffer is closed.
90 | if b.closed {
91 | err = io.EOF
92 | break
93 | }
94 | // out of buffers, wait for producer
95 | b.Cond.Wait()
96 | }
97 | return
98 | }
99 |
--------------------------------------------------------------------------------
/Godeps/_workspace/src/golang.org/x/crypto/ssh/buffer_test.go:
--------------------------------------------------------------------------------
1 | // Copyright 2011 The Go Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style
3 | // license that can be found in the LICENSE file.
4 |
5 | package ssh
6 |
7 | import (
8 | "io"
9 | "testing"
10 | )
11 |
12 | var alphabet = []byte("abcdefghijklmnopqrstuvwxyz")
13 |
14 | func TestBufferReadwrite(t *testing.T) {
15 | b := newBuffer()
16 | b.write(alphabet[:10])
17 | r, _ := b.Read(make([]byte, 10))
18 | if r != 10 {
19 | t.Fatalf("Expected written == read == 10, written: 10, read %d", r)
20 | }
21 |
22 | b = newBuffer()
23 | b.write(alphabet[:5])
24 | r, _ = b.Read(make([]byte, 10))
25 | if r != 5 {
26 | t.Fatalf("Expected written == read == 5, written: 5, read %d", r)
27 | }
28 |
29 | b = newBuffer()
30 | b.write(alphabet[:10])
31 | r, _ = b.Read(make([]byte, 5))
32 | if r != 5 {
33 | t.Fatalf("Expected written == 10, read == 5, written: 10, read %d", r)
34 | }
35 |
36 | b = newBuffer()
37 | b.write(alphabet[:5])
38 | b.write(alphabet[5:15])
39 | r, _ = b.Read(make([]byte, 10))
40 | r2, _ := b.Read(make([]byte, 10))
41 | if r != 10 || r2 != 5 || 15 != r+r2 {
42 | t.Fatal("Expected written == read == 15")
43 | }
44 | }
45 |
46 | func TestBufferClose(t *testing.T) {
47 | b := newBuffer()
48 | b.write(alphabet[:10])
49 | b.eof()
50 | _, err := b.Read(make([]byte, 5))
51 | if err != nil {
52 | t.Fatal("expected read of 5 to not return EOF")
53 | }
54 | b = newBuffer()
55 | b.write(alphabet[:10])
56 | b.eof()
57 | r, err := b.Read(make([]byte, 5))
58 | r2, err2 := b.Read(make([]byte, 10))
59 | if r != 5 || r2 != 5 || err != nil || err2 != nil {
60 | t.Fatal("expected reads of 5 and 5")
61 | }
62 |
63 | b = newBuffer()
64 | b.write(alphabet[:10])
65 | b.eof()
66 | r, err = b.Read(make([]byte, 5))
67 | r2, err2 = b.Read(make([]byte, 10))
68 | r3, err3 := b.Read(make([]byte, 10))
69 | if r != 5 || r2 != 5 || r3 != 0 || err != nil || err2 != nil || err3 != io.EOF {
70 | t.Fatal("expected reads of 5 and 5 and 0, with EOF")
71 | }
72 |
73 | b = newBuffer()
74 | b.write(make([]byte, 5))
75 | b.write(make([]byte, 10))
76 | b.eof()
77 | r, err = b.Read(make([]byte, 9))
78 | r2, err2 = b.Read(make([]byte, 3))
79 | r3, err3 = b.Read(make([]byte, 3))
80 | r4, err4 := b.Read(make([]byte, 10))
81 | if err != nil || err2 != nil || err3 != nil || err4 != io.EOF {
82 | t.Fatalf("Expected EOF on forth read only, err=%v, err2=%v, err3=%v, err4=%v", err, err2, err3, err4)
83 | }
84 | if r != 9 || r2 != 3 || r3 != 3 || r4 != 0 {
85 | t.Fatal("Expected written == read == 15", r, r2, r3, r4)
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/Godeps/_workspace/src/golang.org/x/crypto/ssh/certs_test.go:
--------------------------------------------------------------------------------
1 | // Copyright 2013 The Go Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style
3 | // license that can be found in the LICENSE file.
4 |
5 | package ssh
6 |
7 | import (
8 | "bytes"
9 | "crypto/rand"
10 | "testing"
11 | "time"
12 | )
13 |
14 | // Cert generated by ssh-keygen 6.0p1 Debian-4.
15 | // % ssh-keygen -s ca-key -I test user-key
16 | var exampleSSHCert = `ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgb1srW/W3ZDjYAO45xLYAwzHBDLsJ4Ux6ICFIkTjb1LEAAAADAQABAAAAYQCkoR51poH0wE8w72cqSB8Sszx+vAhzcMdCO0wqHTj7UNENHWEXGrU0E0UQekD7U+yhkhtoyjbPOVIP7hNa6aRk/ezdh/iUnCIt4Jt1v3Z1h1P+hA4QuYFMHNB+rmjPwAcAAAAAAAAAAAAAAAEAAAAEdGVzdAAAAAAAAAAAAAAAAP//////////AAAAAAAAAIIAAAAVcGVybWl0LVgxMS1mb3J3YXJkaW5nAAAAAAAAABdwZXJtaXQtYWdlbnQtZm9yd2FyZGluZwAAAAAAAAAWcGVybWl0LXBvcnQtZm9yd2FyZGluZwAAAAAAAAAKcGVybWl0LXB0eQAAAAAAAAAOcGVybWl0LXVzZXItcmMAAAAAAAAAAAAAAHcAAAAHc3NoLXJzYQAAAAMBAAEAAABhANFS2kaktpSGc+CcmEKPyw9mJC4nZKxHKTgLVZeaGbFZOvJTNzBspQHdy7Q1uKSfktxpgjZnksiu/tFF9ngyY2KFoc+U88ya95IZUycBGCUbBQ8+bhDtw/icdDGQD5WnUwAAAG8AAAAHc3NoLXJzYQAAAGC8Y9Z2LQKhIhxf52773XaWrXdxP0t3GBVo4A10vUWiYoAGepr6rQIoGGXFxT4B9Gp+nEBJjOwKDXPrAevow0T9ca8gZN+0ykbhSrXLE5Ao48rqr3zP4O1/9P7e6gp0gw8=`
17 |
18 | func TestParseCert(t *testing.T) {
19 | authKeyBytes := []byte(exampleSSHCert)
20 |
21 | key, _, _, rest, err := ParseAuthorizedKey(authKeyBytes)
22 | if err != nil {
23 | t.Fatalf("ParseAuthorizedKey: %v", err)
24 | }
25 | if len(rest) > 0 {
26 | t.Errorf("rest: got %q, want empty", rest)
27 | }
28 |
29 | if _, ok := key.(*Certificate); !ok {
30 | t.Fatalf("got %#v, want *Certificate", key)
31 | }
32 |
33 | marshaled := MarshalAuthorizedKey(key)
34 | // Before comparison, remove the trailing newline that
35 | // MarshalAuthorizedKey adds.
36 | marshaled = marshaled[:len(marshaled)-1]
37 | if !bytes.Equal(authKeyBytes, marshaled) {
38 | t.Errorf("marshaled certificate does not match original: got %q, want %q", marshaled, authKeyBytes)
39 | }
40 | }
41 |
42 | func TestValidateCert(t *testing.T) {
43 | key, _, _, _, err := ParseAuthorizedKey([]byte(exampleSSHCert))
44 | if err != nil {
45 | t.Fatalf("ParseAuthorizedKey: %v", err)
46 | }
47 | validCert, ok := key.(*Certificate)
48 | if !ok {
49 | t.Fatalf("got %v (%T), want *Certificate", key, key)
50 | }
51 | checker := CertChecker{}
52 | checker.IsAuthority = func(k PublicKey) bool {
53 | return bytes.Equal(k.Marshal(), validCert.SignatureKey.Marshal())
54 | }
55 |
56 | if err := checker.CheckCert("user", validCert); err != nil {
57 | t.Errorf("Unable to validate certificate: %v", err)
58 | }
59 | invalidCert := &Certificate{
60 | Key: testPublicKeys["rsa"],
61 | SignatureKey: testPublicKeys["ecdsa"],
62 | ValidBefore: CertTimeInfinity,
63 | Signature: &Signature{},
64 | }
65 | if err := checker.CheckCert("user", invalidCert); err == nil {
66 | t.Error("Invalid cert signature passed validation")
67 | }
68 | }
69 |
70 | func TestValidateCertTime(t *testing.T) {
71 | cert := Certificate{
72 | ValidPrincipals: []string{"user"},
73 | Key: testPublicKeys["rsa"],
74 | ValidAfter: 50,
75 | ValidBefore: 100,
76 | }
77 |
78 | cert.SignCert(rand.Reader, testSigners["ecdsa"])
79 |
80 | for ts, ok := range map[int64]bool{
81 | 25: false,
82 | 50: true,
83 | 99: true,
84 | 100: false,
85 | 125: false,
86 | } {
87 | checker := CertChecker{
88 | Clock: func() time.Time { return time.Unix(ts, 0) },
89 | }
90 | checker.IsAuthority = func(k PublicKey) bool {
91 | return bytes.Equal(k.Marshal(),
92 | testPublicKeys["ecdsa"].Marshal())
93 | }
94 |
95 | if v := checker.CheckCert("user", &cert); (v == nil) != ok {
96 | t.Errorf("Authenticate(%d): %v", ts, v)
97 | }
98 | }
99 | }
100 |
101 | // TODO(hanwen): tests for
102 | //
103 | // host keys:
104 | // * fallbacks
105 |
106 | func TestHostKeyCert(t *testing.T) {
107 | cert := &Certificate{
108 | ValidPrincipals: []string{"hostname", "hostname.domain"},
109 | Key: testPublicKeys["rsa"],
110 | ValidBefore: CertTimeInfinity,
111 | CertType: HostCert,
112 | }
113 | cert.SignCert(rand.Reader, testSigners["ecdsa"])
114 |
115 | checker := &CertChecker{
116 | IsAuthority: func(p PublicKey) bool {
117 | return bytes.Equal(testPublicKeys["ecdsa"].Marshal(), p.Marshal())
118 | },
119 | }
120 |
121 | certSigner, err := NewCertSigner(cert, testSigners["rsa"])
122 | if err != nil {
123 | t.Errorf("NewCertSigner: %v", err)
124 | }
125 |
126 | for _, name := range []string{"hostname", "otherhost"} {
127 | c1, c2, err := netPipe()
128 | if err != nil {
129 | t.Fatalf("netPipe: %v", err)
130 | }
131 | defer c1.Close()
132 | defer c2.Close()
133 |
134 | go func() {
135 | conf := ServerConfig{
136 | NoClientAuth: true,
137 | }
138 | conf.AddHostKey(certSigner)
139 | _, _, _, err := NewServerConn(c1, &conf)
140 | if err != nil {
141 | t.Fatalf("NewServerConn: %v", err)
142 | }
143 | }()
144 |
145 | config := &ClientConfig{
146 | User: "user",
147 | HostKeyCallback: checker.CheckHostKey,
148 | }
149 | _, _, _, err = NewClientConn(c2, name, config)
150 |
151 | succeed := name == "hostname"
152 | if (err == nil) != succeed {
153 | t.Fatalf("NewClientConn(%q): %v", name, err)
154 | }
155 | }
156 | }
157 |
--------------------------------------------------------------------------------
/Godeps/_workspace/src/golang.org/x/crypto/ssh/cipher_test.go:
--------------------------------------------------------------------------------
1 | // Copyright 2011 The Go Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style
3 | // license that can be found in the LICENSE file.
4 |
5 | package ssh
6 |
7 | import (
8 | "bytes"
9 | "crypto"
10 | "crypto/rand"
11 | "testing"
12 | )
13 |
14 | func TestDefaultCiphersExist(t *testing.T) {
15 | for _, cipherAlgo := range supportedCiphers {
16 | if _, ok := cipherModes[cipherAlgo]; !ok {
17 | t.Errorf("default cipher %q is unknown", cipherAlgo)
18 | }
19 | }
20 | }
21 |
22 | func TestPacketCiphers(t *testing.T) {
23 | for cipher := range cipherModes {
24 | kr := &kexResult{Hash: crypto.SHA1}
25 | algs := directionAlgorithms{
26 | Cipher: cipher,
27 | MAC: "hmac-sha1",
28 | Compression: "none",
29 | }
30 | client, err := newPacketCipher(clientKeys, algs, kr)
31 | if err != nil {
32 | t.Errorf("newPacketCipher(client, %q): %v", cipher, err)
33 | continue
34 | }
35 | server, err := newPacketCipher(clientKeys, algs, kr)
36 | if err != nil {
37 | t.Errorf("newPacketCipher(client, %q): %v", cipher, err)
38 | continue
39 | }
40 |
41 | want := "bla bla"
42 | input := []byte(want)
43 | buf := &bytes.Buffer{}
44 | if err := client.writePacket(0, buf, rand.Reader, input); err != nil {
45 | t.Errorf("writePacket(%q): %v", cipher, err)
46 | continue
47 | }
48 |
49 | packet, err := server.readPacket(0, buf)
50 | if err != nil {
51 | t.Errorf("readPacket(%q): %v", cipher, err)
52 | continue
53 | }
54 |
55 | if string(packet) != want {
56 | t.Errorf("roundtrip(%q): got %q, want %q", cipher, packet, want)
57 | }
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/Godeps/_workspace/src/golang.org/x/crypto/ssh/client.go:
--------------------------------------------------------------------------------
1 | // Copyright 2011 The Go Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style
3 | // license that can be found in the LICENSE file.
4 |
5 | package ssh
6 |
7 | import (
8 | "errors"
9 | "fmt"
10 | "net"
11 | "sync"
12 | )
13 |
14 | // Client implements a traditional SSH client that supports shells,
15 | // subprocesses, port forwarding and tunneled dialing.
16 | type Client struct {
17 | Conn
18 |
19 | forwards forwardList // forwarded tcpip connections from the remote side
20 | mu sync.Mutex
21 | channelHandlers map[string]chan NewChannel
22 | }
23 |
24 | // HandleChannelOpen returns a channel on which NewChannel requests
25 | // for the given type are sent. If the type already is being handled,
26 | // nil is returned. The channel is closed when the connection is closed.
27 | func (c *Client) HandleChannelOpen(channelType string) <-chan NewChannel {
28 | c.mu.Lock()
29 | defer c.mu.Unlock()
30 | if c.channelHandlers == nil {
31 | // The SSH channel has been closed.
32 | c := make(chan NewChannel)
33 | close(c)
34 | return c
35 | }
36 |
37 | ch := c.channelHandlers[channelType]
38 | if ch != nil {
39 | return nil
40 | }
41 |
42 | ch = make(chan NewChannel, 16)
43 | c.channelHandlers[channelType] = ch
44 | return ch
45 | }
46 |
47 | // NewClient creates a Client on top of the given connection.
48 | func NewClient(c Conn, chans <-chan NewChannel, reqs <-chan *Request) *Client {
49 | conn := &Client{
50 | Conn: c,
51 | channelHandlers: make(map[string]chan NewChannel, 1),
52 | }
53 |
54 | go conn.handleGlobalRequests(reqs)
55 | go conn.handleChannelOpens(chans)
56 | go func() {
57 | conn.Wait()
58 | conn.forwards.closeAll()
59 | }()
60 | go conn.forwards.handleChannels(conn.HandleChannelOpen("forwarded-tcpip"))
61 | return conn
62 | }
63 |
64 | // NewClientConn establishes an authenticated SSH connection using c
65 | // as the underlying transport. The Request and NewChannel channels
66 | // must be serviced or the connection will hang.
67 | func NewClientConn(c net.Conn, addr string, config *ClientConfig) (Conn, <-chan NewChannel, <-chan *Request, error) {
68 | fullConf := *config
69 | fullConf.SetDefaults()
70 | conn := &connection{
71 | sshConn: sshConn{conn: c},
72 | }
73 |
74 | if err := conn.clientHandshake(addr, &fullConf); err != nil {
75 | c.Close()
76 | return nil, nil, nil, fmt.Errorf("ssh: handshake failed: %v", err)
77 | }
78 | conn.mux = newMux(conn.transport)
79 | return conn, conn.mux.incomingChannels, conn.mux.incomingRequests, nil
80 | }
81 |
82 | // clientHandshake performs the client side key exchange. See RFC 4253 Section
83 | // 7.
84 | func (c *connection) clientHandshake(dialAddress string, config *ClientConfig) error {
85 | if config.ClientVersion != "" {
86 | c.clientVersion = []byte(config.ClientVersion)
87 | } else {
88 | c.clientVersion = []byte(packageVersion)
89 | }
90 | var err error
91 | c.serverVersion, err = exchangeVersions(c.sshConn.conn, c.clientVersion)
92 | if err != nil {
93 | return err
94 | }
95 |
96 | c.transport = newClientTransport(
97 | newTransport(c.sshConn.conn, config.Rand, true /* is client */),
98 | c.clientVersion, c.serverVersion, config, dialAddress, c.sshConn.RemoteAddr())
99 | if err := c.transport.requestKeyChange(); err != nil {
100 | return err
101 | }
102 |
103 | if packet, err := c.transport.readPacket(); err != nil {
104 | return err
105 | } else if packet[0] != msgNewKeys {
106 | return unexpectedMessageError(msgNewKeys, packet[0])
107 | }
108 |
109 | // We just did the key change, so the session ID is established.
110 | c.sessionID = c.transport.getSessionID()
111 |
112 | return c.clientAuthenticate(config)
113 | }
114 |
115 | // verifyHostKeySignature verifies the host key obtained in the key
116 | // exchange.
117 | func verifyHostKeySignature(hostKey PublicKey, result *kexResult) error {
118 | sig, rest, ok := parseSignatureBody(result.Signature)
119 | if len(rest) > 0 || !ok {
120 | return errors.New("ssh: signature parse error")
121 | }
122 |
123 | return hostKey.Verify(result.H, sig)
124 | }
125 |
126 | // NewSession opens a new Session for this client. (A session is a remote
127 | // execution of a program.)
128 | func (c *Client) NewSession() (*Session, error) {
129 | ch, in, err := c.OpenChannel("session", nil)
130 | if err != nil {
131 | return nil, err
132 | }
133 | return newSession(ch, in)
134 | }
135 |
136 | func (c *Client) handleGlobalRequests(incoming <-chan *Request) {
137 | for r := range incoming {
138 | // This handles keepalive messages and matches
139 | // the behaviour of OpenSSH.
140 | r.Reply(false, nil)
141 | }
142 | }
143 |
144 | // handleChannelOpens channel open messages from the remote side.
145 | func (c *Client) handleChannelOpens(in <-chan NewChannel) {
146 | for ch := range in {
147 | c.mu.Lock()
148 | handler := c.channelHandlers[ch.ChannelType()]
149 | c.mu.Unlock()
150 |
151 | if handler != nil {
152 | handler <- ch
153 | } else {
154 | ch.Reject(UnknownChannelType, fmt.Sprintf("unknown channel type: %v", ch.ChannelType()))
155 | }
156 | }
157 |
158 | c.mu.Lock()
159 | for _, ch := range c.channelHandlers {
160 | close(ch)
161 | }
162 | c.channelHandlers = nil
163 | c.mu.Unlock()
164 | }
165 |
166 | // Dial starts a client connection to the given SSH server. It is a
167 | // convenience function that connects to the given network address,
168 | // initiates the SSH handshake, and then sets up a Client. For access
169 | // to incoming channels and requests, use net.Dial with NewClientConn
170 | // instead.
171 | func Dial(network, addr string, config *ClientConfig) (*Client, error) {
172 | conn, err := net.Dial(network, addr)
173 | if err != nil {
174 | return nil, err
175 | }
176 | c, chans, reqs, err := NewClientConn(conn, addr, config)
177 | if err != nil {
178 | return nil, err
179 | }
180 | return NewClient(c, chans, reqs), nil
181 | }
182 |
183 | // A ClientConfig structure is used to configure a Client. It must not be
184 | // modified after having been passed to an SSH function.
185 | type ClientConfig struct {
186 | // Config contains configuration that is shared between clients and
187 | // servers.
188 | Config
189 |
190 | // User contains the username to authenticate as.
191 | User string
192 |
193 | // Auth contains possible authentication methods to use with the
194 | // server. Only the first instance of a particular RFC 4252 method will
195 | // be used during authentication.
196 | Auth []AuthMethod
197 |
198 | // HostKeyCallback, if not nil, is called during the cryptographic
199 | // handshake to validate the server's host key. A nil HostKeyCallback
200 | // implies that all host keys are accepted.
201 | HostKeyCallback func(hostname string, remote net.Addr, key PublicKey) error
202 |
203 | // ClientVersion contains the version identification string that will
204 | // be used for the connection. If empty, a reasonable default is used.
205 | ClientVersion string
206 | }
207 |
--------------------------------------------------------------------------------
/Godeps/_workspace/src/golang.org/x/crypto/ssh/client_test.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014 The Go Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style
3 | // license that can be found in the LICENSE file.
4 |
5 | package ssh
6 |
7 | import (
8 | "net"
9 | "testing"
10 | )
11 |
12 | func testClientVersion(t *testing.T, config *ClientConfig, expected string) {
13 | clientConn, serverConn := net.Pipe()
14 | defer clientConn.Close()
15 | receivedVersion := make(chan string, 1)
16 | go func() {
17 | version, err := readVersion(serverConn)
18 | if err != nil {
19 | receivedVersion <- ""
20 | } else {
21 | receivedVersion <- string(version)
22 | }
23 | serverConn.Close()
24 | }()
25 | NewClientConn(clientConn, "", config)
26 | actual := <-receivedVersion
27 | if actual != expected {
28 | t.Fatalf("got %s; want %s", actual, expected)
29 | }
30 | }
31 |
32 | func TestCustomClientVersion(t *testing.T) {
33 | version := "Test-Client-Version-0.0"
34 | testClientVersion(t, &ClientConfig{ClientVersion: version}, version)
35 | }
36 |
37 | func TestDefaultClientVersion(t *testing.T) {
38 | testClientVersion(t, &ClientConfig{}, packageVersion)
39 | }
40 |
--------------------------------------------------------------------------------
/Godeps/_workspace/src/golang.org/x/crypto/ssh/connection.go:
--------------------------------------------------------------------------------
1 | // Copyright 2013 The Go Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style
3 | // license that can be found in the LICENSE file.
4 |
5 | package ssh
6 |
7 | import (
8 | "fmt"
9 | "net"
10 | )
11 |
12 | // OpenChannelError is returned if the other side rejects an
13 | // OpenChannel request.
14 | type OpenChannelError struct {
15 | Reason RejectionReason
16 | Message string
17 | }
18 |
19 | func (e *OpenChannelError) Error() string {
20 | return fmt.Sprintf("ssh: rejected: %s (%s)", e.Reason, e.Message)
21 | }
22 |
23 | // ConnMetadata holds metadata for the connection.
24 | type ConnMetadata interface {
25 | // User returns the user ID for this connection.
26 | // It is empty if no authentication is used.
27 | User() string
28 |
29 | // SessionID returns the sesson hash, also denoted by H.
30 | SessionID() []byte
31 |
32 | // ClientVersion returns the client's version string as hashed
33 | // into the session ID.
34 | ClientVersion() []byte
35 |
36 | // ServerVersion returns the client's version string as hashed
37 | // into the session ID.
38 | ServerVersion() []byte
39 |
40 | // RemoteAddr returns the remote address for this connection.
41 | RemoteAddr() net.Addr
42 |
43 | // LocalAddr returns the local address for this connection.
44 | LocalAddr() net.Addr
45 | }
46 |
47 | // Conn represents an SSH connection for both server and client roles.
48 | // Conn is the basis for implementing an application layer, such
49 | // as ClientConn, which implements the traditional shell access for
50 | // clients.
51 | type Conn interface {
52 | ConnMetadata
53 |
54 | // SendRequest sends a global request, and returns the
55 | // reply. If wantReply is true, it returns the response status
56 | // and payload. See also RFC4254, section 4.
57 | SendRequest(name string, wantReply bool, payload []byte) (bool, []byte, error)
58 |
59 | // OpenChannel tries to open an channel. If the request is
60 | // rejected, it returns *OpenChannelError. On success it returns
61 | // the SSH Channel and a Go channel for incoming, out-of-band
62 | // requests. The Go channel must be serviced, or the
63 | // connection will hang.
64 | OpenChannel(name string, data []byte) (Channel, <-chan *Request, error)
65 |
66 | // Close closes the underlying network connection
67 | Close() error
68 |
69 | // Wait blocks until the connection has shut down, and returns the
70 | // error causing the shutdown.
71 | Wait() error
72 |
73 | // TODO(hanwen): consider exposing:
74 | // RequestKeyChange
75 | // Disconnect
76 | }
77 |
78 | // DiscardRequests consumes and rejects all requests from the
79 | // passed-in channel.
80 | func DiscardRequests(in <-chan *Request) {
81 | for req := range in {
82 | if req.WantReply {
83 | req.Reply(false, nil)
84 | }
85 | }
86 | }
87 |
88 | // A connection represents an incoming connection.
89 | type connection struct {
90 | transport *handshakeTransport
91 | sshConn
92 |
93 | // The connection protocol.
94 | *mux
95 | }
96 |
97 | func (c *connection) Close() error {
98 | return c.sshConn.conn.Close()
99 | }
100 |
101 | // sshconn provides net.Conn metadata, but disallows direct reads and
102 | // writes.
103 | type sshConn struct {
104 | conn net.Conn
105 |
106 | user string
107 | sessionID []byte
108 | clientVersion []byte
109 | serverVersion []byte
110 | }
111 |
112 | func dup(src []byte) []byte {
113 | dst := make([]byte, len(src))
114 | copy(dst, src)
115 | return dst
116 | }
117 |
118 | func (c *sshConn) User() string {
119 | return c.user
120 | }
121 |
122 | func (c *sshConn) RemoteAddr() net.Addr {
123 | return c.conn.RemoteAddr()
124 | }
125 |
126 | func (c *sshConn) Close() error {
127 | return c.conn.Close()
128 | }
129 |
130 | func (c *sshConn) LocalAddr() net.Addr {
131 | return c.conn.LocalAddr()
132 | }
133 |
134 | func (c *sshConn) SessionID() []byte {
135 | return dup(c.sessionID)
136 | }
137 |
138 | func (c *sshConn) ClientVersion() []byte {
139 | return dup(c.clientVersion)
140 | }
141 |
142 | func (c *sshConn) ServerVersion() []byte {
143 | return dup(c.serverVersion)
144 | }
145 |
--------------------------------------------------------------------------------
/Godeps/_workspace/src/golang.org/x/crypto/ssh/doc.go:
--------------------------------------------------------------------------------
1 | // Copyright 2011 The Go Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style
3 | // license that can be found in the LICENSE file.
4 |
5 | /*
6 | Package ssh implements an SSH client and server.
7 |
8 | SSH is a transport security protocol, an authentication protocol and a
9 | family of application protocols. The most typical application level
10 | protocol is a remote shell and this is specifically implemented. However,
11 | the multiplexed nature of SSH is exposed to users that wish to support
12 | others.
13 |
14 | References:
15 | [PROTOCOL.certkeys]: http://www.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL.certkeys
16 | [SSH-PARAMETERS]: http://www.iana.org/assignments/ssh-parameters/ssh-parameters.xml#ssh-parameters-1
17 | */
18 | package ssh // import "golang.org/x/crypto/ssh"
19 |
--------------------------------------------------------------------------------
/Godeps/_workspace/src/golang.org/x/crypto/ssh/example_test.go:
--------------------------------------------------------------------------------
1 | // Copyright 2011 The Go Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style
3 | // license that can be found in the LICENSE file.
4 |
5 | package ssh_test
6 |
7 | import (
8 | "bytes"
9 | "fmt"
10 | "io/ioutil"
11 | "log"
12 | "net"
13 | "net/http"
14 |
15 | "golang.org/x/crypto/ssh"
16 | "golang.org/x/crypto/ssh/terminal"
17 | )
18 |
19 | func ExampleNewServerConn() {
20 | // An SSH server is represented by a ServerConfig, which holds
21 | // certificate details and handles authentication of ServerConns.
22 | config := &ssh.ServerConfig{
23 | PasswordCallback: func(c ssh.ConnMetadata, pass []byte) (*ssh.Permissions, error) {
24 | // Should use constant-time compare (or better, salt+hash) in
25 | // a production setting.
26 | if c.User() == "testuser" && string(pass) == "tiger" {
27 | return nil, nil
28 | }
29 | return nil, fmt.Errorf("password rejected for %q", c.User())
30 | },
31 | }
32 |
33 | privateBytes, err := ioutil.ReadFile("id_rsa")
34 | if err != nil {
35 | panic("Failed to load private key")
36 | }
37 |
38 | private, err := ssh.ParsePrivateKey(privateBytes)
39 | if err != nil {
40 | panic("Failed to parse private key")
41 | }
42 |
43 | config.AddHostKey(private)
44 |
45 | // Once a ServerConfig has been configured, connections can be
46 | // accepted.
47 | listener, err := net.Listen("tcp", "0.0.0.0:2022")
48 | if err != nil {
49 | panic("failed to listen for connection")
50 | }
51 | nConn, err := listener.Accept()
52 | if err != nil {
53 | panic("failed to accept incoming connection")
54 | }
55 |
56 | // Before use, a handshake must be performed on the incoming
57 | // net.Conn.
58 | _, chans, reqs, err := ssh.NewServerConn(nConn, config)
59 | if err != nil {
60 | panic("failed to handshake")
61 | }
62 | // The incoming Request channel must be serviced.
63 | go ssh.DiscardRequests(reqs)
64 |
65 | // Service the incoming Channel channel.
66 | for newChannel := range chans {
67 | // Channels have a type, depending on the application level
68 | // protocol intended. In the case of a shell, the type is
69 | // "session" and ServerShell may be used to present a simple
70 | // terminal interface.
71 | if newChannel.ChannelType() != "session" {
72 | newChannel.Reject(ssh.UnknownChannelType, "unknown channel type")
73 | continue
74 | }
75 | channel, requests, err := newChannel.Accept()
76 | if err != nil {
77 | panic("could not accept channel.")
78 | }
79 |
80 | // Sessions have out-of-band requests such as "shell",
81 | // "pty-req" and "env". Here we handle only the
82 | // "shell" request.
83 | go func(in <-chan *ssh.Request) {
84 | for req := range in {
85 | ok := false
86 | switch req.Type {
87 | case "shell":
88 | ok = true
89 | if len(req.Payload) > 0 {
90 | // We don't accept any
91 | // commands, only the
92 | // default shell.
93 | ok = false
94 | }
95 | }
96 | req.Reply(ok, nil)
97 | }
98 | }(requests)
99 |
100 | term := terminal.NewTerminal(channel, "> ")
101 |
102 | go func() {
103 | defer channel.Close()
104 | for {
105 | line, err := term.ReadLine()
106 | if err != nil {
107 | break
108 | }
109 | fmt.Println(line)
110 | }
111 | }()
112 | }
113 | }
114 |
115 | func ExampleDial() {
116 | // An SSH client is represented with a ClientConn. Currently only
117 | // the "password" authentication method is supported.
118 | //
119 | // To authenticate with the remote server you must pass at least one
120 | // implementation of AuthMethod via the Auth field in ClientConfig.
121 | config := &ssh.ClientConfig{
122 | User: "username",
123 | Auth: []ssh.AuthMethod{
124 | ssh.Password("yourpassword"),
125 | },
126 | }
127 | client, err := ssh.Dial("tcp", "yourserver.com:22", config)
128 | if err != nil {
129 | panic("Failed to dial: " + err.Error())
130 | }
131 |
132 | // Each ClientConn can support multiple interactive sessions,
133 | // represented by a Session.
134 | session, err := client.NewSession()
135 | if err != nil {
136 | panic("Failed to create session: " + err.Error())
137 | }
138 | defer session.Close()
139 |
140 | // Once a Session is created, you can execute a single command on
141 | // the remote side using the Run method.
142 | var b bytes.Buffer
143 | session.Stdout = &b
144 | if err := session.Run("/usr/bin/whoami"); err != nil {
145 | panic("Failed to run: " + err.Error())
146 | }
147 | fmt.Println(b.String())
148 | }
149 |
150 | func ExampleClient_Listen() {
151 | config := &ssh.ClientConfig{
152 | User: "username",
153 | Auth: []ssh.AuthMethod{
154 | ssh.Password("password"),
155 | },
156 | }
157 | // Dial your ssh server.
158 | conn, err := ssh.Dial("tcp", "localhost:22", config)
159 | if err != nil {
160 | log.Fatalf("unable to connect: %s", err)
161 | }
162 | defer conn.Close()
163 |
164 | // Request the remote side to open port 8080 on all interfaces.
165 | l, err := conn.Listen("tcp", "0.0.0.0:8080")
166 | if err != nil {
167 | log.Fatalf("unable to register tcp forward: %v", err)
168 | }
169 | defer l.Close()
170 |
171 | // Serve HTTP with your SSH server acting as a reverse proxy.
172 | http.Serve(l, http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
173 | fmt.Fprintf(resp, "Hello world!\n")
174 | }))
175 | }
176 |
177 | func ExampleSession_RequestPty() {
178 | // Create client config
179 | config := &ssh.ClientConfig{
180 | User: "username",
181 | Auth: []ssh.AuthMethod{
182 | ssh.Password("password"),
183 | },
184 | }
185 | // Connect to ssh server
186 | conn, err := ssh.Dial("tcp", "localhost:22", config)
187 | if err != nil {
188 | log.Fatalf("unable to connect: %s", err)
189 | }
190 | defer conn.Close()
191 | // Create a session
192 | session, err := conn.NewSession()
193 | if err != nil {
194 | log.Fatalf("unable to create session: %s", err)
195 | }
196 | defer session.Close()
197 | // Set up terminal modes
198 | modes := ssh.TerminalModes{
199 | ssh.ECHO: 0, // disable echoing
200 | ssh.TTY_OP_ISPEED: 14400, // input speed = 14.4kbaud
201 | ssh.TTY_OP_OSPEED: 14400, // output speed = 14.4kbaud
202 | }
203 | // Request pseudo terminal
204 | if err := session.RequestPty("xterm", 80, 40, modes); err != nil {
205 | log.Fatalf("request for pseudo terminal failed: %s", err)
206 | }
207 | // Start remote shell
208 | if err := session.Shell(); err != nil {
209 | log.Fatalf("failed to start shell: %s", err)
210 | }
211 | }
212 |
--------------------------------------------------------------------------------
/Godeps/_workspace/src/golang.org/x/crypto/ssh/kex_test.go:
--------------------------------------------------------------------------------
1 | // Copyright 2013 The Go Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style
3 | // license that can be found in the LICENSE file.
4 |
5 | package ssh
6 |
7 | // Key exchange tests.
8 |
9 | import (
10 | "crypto/rand"
11 | "reflect"
12 | "testing"
13 | )
14 |
15 | func TestKexes(t *testing.T) {
16 | type kexResultErr struct {
17 | result *kexResult
18 | err error
19 | }
20 |
21 | for name, kex := range kexAlgoMap {
22 | a, b := memPipe()
23 |
24 | s := make(chan kexResultErr, 1)
25 | c := make(chan kexResultErr, 1)
26 | var magics handshakeMagics
27 | go func() {
28 | r, e := kex.Client(a, rand.Reader, &magics)
29 | c <- kexResultErr{r, e}
30 | }()
31 | go func() {
32 | r, e := kex.Server(b, rand.Reader, &magics, testSigners["ecdsa"])
33 | s <- kexResultErr{r, e}
34 | }()
35 |
36 | clientRes := <-c
37 | serverRes := <-s
38 | if clientRes.err != nil {
39 | t.Errorf("client: %v", clientRes.err)
40 | }
41 | if serverRes.err != nil {
42 | t.Errorf("server: %v", serverRes.err)
43 | }
44 | if !reflect.DeepEqual(clientRes.result, serverRes.result) {
45 | t.Errorf("kex %q: mismatch %#v, %#v", name, clientRes.result, serverRes.result)
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/Godeps/_workspace/src/golang.org/x/crypto/ssh/mac.go:
--------------------------------------------------------------------------------
1 | // Copyright 2012 The Go Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style
3 | // license that can be found in the LICENSE file.
4 |
5 | package ssh
6 |
7 | // Message authentication support
8 |
9 | import (
10 | "crypto/hmac"
11 | "crypto/sha1"
12 | "hash"
13 | )
14 |
15 | type macMode struct {
16 | keySize int
17 | new func(key []byte) hash.Hash
18 | }
19 |
20 | // truncatingMAC wraps around a hash.Hash and truncates the output digest to
21 | // a given size.
22 | type truncatingMAC struct {
23 | length int
24 | hmac hash.Hash
25 | }
26 |
27 | func (t truncatingMAC) Write(data []byte) (int, error) {
28 | return t.hmac.Write(data)
29 | }
30 |
31 | func (t truncatingMAC) Sum(in []byte) []byte {
32 | out := t.hmac.Sum(in)
33 | return out[:len(in)+t.length]
34 | }
35 |
36 | func (t truncatingMAC) Reset() {
37 | t.hmac.Reset()
38 | }
39 |
40 | func (t truncatingMAC) Size() int {
41 | return t.length
42 | }
43 |
44 | func (t truncatingMAC) BlockSize() int { return t.hmac.BlockSize() }
45 |
46 | var macModes = map[string]*macMode{
47 | "hmac-sha1": {20, func(key []byte) hash.Hash {
48 | return hmac.New(sha1.New, key)
49 | }},
50 | "hmac-sha1-96": {20, func(key []byte) hash.Hash {
51 | return truncatingMAC{12, hmac.New(sha1.New, key)}
52 | }},
53 | }
54 |
--------------------------------------------------------------------------------
/Godeps/_workspace/src/golang.org/x/crypto/ssh/mempipe_test.go:
--------------------------------------------------------------------------------
1 | // Copyright 2013 The Go Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style
3 | // license that can be found in the LICENSE file.
4 |
5 | package ssh
6 |
7 | import (
8 | "io"
9 | "sync"
10 | "testing"
11 | )
12 |
13 | // An in-memory packetConn. It is safe to call Close and writePacket
14 | // from different goroutines.
15 | type memTransport struct {
16 | eof bool
17 | pending [][]byte
18 | write *memTransport
19 | sync.Mutex
20 | *sync.Cond
21 | }
22 |
23 | func (t *memTransport) readPacket() ([]byte, error) {
24 | t.Lock()
25 | defer t.Unlock()
26 | for {
27 | if len(t.pending) > 0 {
28 | r := t.pending[0]
29 | t.pending = t.pending[1:]
30 | return r, nil
31 | }
32 | if t.eof {
33 | return nil, io.EOF
34 | }
35 | t.Cond.Wait()
36 | }
37 | }
38 |
39 | func (t *memTransport) closeSelf() error {
40 | t.Lock()
41 | defer t.Unlock()
42 | if t.eof {
43 | return io.EOF
44 | }
45 | t.eof = true
46 | t.Cond.Broadcast()
47 | return nil
48 | }
49 |
50 | func (t *memTransport) Close() error {
51 | err := t.write.closeSelf()
52 | t.closeSelf()
53 | return err
54 | }
55 |
56 | func (t *memTransport) writePacket(p []byte) error {
57 | t.write.Lock()
58 | defer t.write.Unlock()
59 | if t.write.eof {
60 | return io.EOF
61 | }
62 | c := make([]byte, len(p))
63 | copy(c, p)
64 | t.write.pending = append(t.write.pending, c)
65 | t.write.Cond.Signal()
66 | return nil
67 | }
68 |
69 | func memPipe() (a, b packetConn) {
70 | t1 := memTransport{}
71 | t2 := memTransport{}
72 | t1.write = &t2
73 | t2.write = &t1
74 | t1.Cond = sync.NewCond(&t1.Mutex)
75 | t2.Cond = sync.NewCond(&t2.Mutex)
76 | return &t1, &t2
77 | }
78 |
79 | func TestmemPipe(t *testing.T) {
80 | a, b := memPipe()
81 | if err := a.writePacket([]byte{42}); err != nil {
82 | t.Fatalf("writePacket: %v", err)
83 | }
84 | if err := a.Close(); err != nil {
85 | t.Fatal("Close: ", err)
86 | }
87 | p, err := b.readPacket()
88 | if err != nil {
89 | t.Fatal("readPacket: ", err)
90 | }
91 | if len(p) != 1 || p[0] != 42 {
92 | t.Fatalf("got %v, want {42}", p)
93 | }
94 | p, err = b.readPacket()
95 | if err != io.EOF {
96 | t.Fatalf("got %v, %v, want EOF", p, err)
97 | }
98 | }
99 |
100 | func TestDoubleClose(t *testing.T) {
101 | a, _ := memPipe()
102 | err := a.Close()
103 | if err != nil {
104 | t.Errorf("Close: %v", err)
105 | }
106 | err = a.Close()
107 | if err != io.EOF {
108 | t.Errorf("expect EOF on double close.")
109 | }
110 | }
111 |
--------------------------------------------------------------------------------
/Godeps/_workspace/src/golang.org/x/crypto/ssh/messages_test.go:
--------------------------------------------------------------------------------
1 | // Copyright 2011 The Go Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style
3 | // license that can be found in the LICENSE file.
4 |
5 | package ssh
6 |
7 | import (
8 | "bytes"
9 | "math/big"
10 | "math/rand"
11 | "reflect"
12 | "testing"
13 | "testing/quick"
14 | )
15 |
16 | var intLengthTests = []struct {
17 | val, length int
18 | }{
19 | {0, 4 + 0},
20 | {1, 4 + 1},
21 | {127, 4 + 1},
22 | {128, 4 + 2},
23 | {-1, 4 + 1},
24 | }
25 |
26 | func TestIntLength(t *testing.T) {
27 | for _, test := range intLengthTests {
28 | v := new(big.Int).SetInt64(int64(test.val))
29 | length := intLength(v)
30 | if length != test.length {
31 | t.Errorf("For %d, got length %d but expected %d", test.val, length, test.length)
32 | }
33 | }
34 | }
35 |
36 | type msgAllTypes struct {
37 | Bool bool `sshtype:"21"`
38 | Array [16]byte
39 | Uint64 uint64
40 | Uint32 uint32
41 | Uint8 uint8
42 | String string
43 | Strings []string
44 | Bytes []byte
45 | Int *big.Int
46 | Rest []byte `ssh:"rest"`
47 | }
48 |
49 | func (t *msgAllTypes) Generate(rand *rand.Rand, size int) reflect.Value {
50 | m := &msgAllTypes{}
51 | m.Bool = rand.Intn(2) == 1
52 | randomBytes(m.Array[:], rand)
53 | m.Uint64 = uint64(rand.Int63n(1<<63 - 1))
54 | m.Uint32 = uint32(rand.Intn((1 << 31) - 1))
55 | m.Uint8 = uint8(rand.Intn(1 << 8))
56 | m.String = string(m.Array[:])
57 | m.Strings = randomNameList(rand)
58 | m.Bytes = m.Array[:]
59 | m.Int = randomInt(rand)
60 | m.Rest = m.Array[:]
61 | return reflect.ValueOf(m)
62 | }
63 |
64 | func TestMarshalUnmarshal(t *testing.T) {
65 | rand := rand.New(rand.NewSource(0))
66 | iface := &msgAllTypes{}
67 | ty := reflect.ValueOf(iface).Type()
68 |
69 | n := 100
70 | if testing.Short() {
71 | n = 5
72 | }
73 | for j := 0; j < n; j++ {
74 | v, ok := quick.Value(ty, rand)
75 | if !ok {
76 | t.Errorf("failed to create value")
77 | break
78 | }
79 |
80 | m1 := v.Elem().Interface()
81 | m2 := iface
82 |
83 | marshaled := Marshal(m1)
84 | if err := Unmarshal(marshaled, m2); err != nil {
85 | t.Errorf("Unmarshal %#v: %s", m1, err)
86 | break
87 | }
88 |
89 | if !reflect.DeepEqual(v.Interface(), m2) {
90 | t.Errorf("got: %#v\nwant:%#v\n%x", m2, m1, marshaled)
91 | break
92 | }
93 | }
94 | }
95 |
96 | func TestUnmarshalEmptyPacket(t *testing.T) {
97 | var b []byte
98 | var m channelRequestSuccessMsg
99 | if err := Unmarshal(b, &m); err == nil {
100 | t.Fatalf("unmarshal of empty slice succeeded")
101 | }
102 | }
103 |
104 | func TestUnmarshalUnexpectedPacket(t *testing.T) {
105 | type S struct {
106 | I uint32 `sshtype:"43"`
107 | S string
108 | B bool
109 | }
110 |
111 | s := S{11, "hello", true}
112 | packet := Marshal(s)
113 | packet[0] = 42
114 | roundtrip := S{}
115 | err := Unmarshal(packet, &roundtrip)
116 | if err == nil {
117 | t.Fatal("expected error, not nil")
118 | }
119 | }
120 |
121 | func TestMarshalPtr(t *testing.T) {
122 | s := struct {
123 | S string
124 | }{"hello"}
125 |
126 | m1 := Marshal(s)
127 | m2 := Marshal(&s)
128 | if !bytes.Equal(m1, m2) {
129 | t.Errorf("got %q, want %q for marshaled pointer", m2, m1)
130 | }
131 | }
132 |
133 | func TestBareMarshalUnmarshal(t *testing.T) {
134 | type S struct {
135 | I uint32
136 | S string
137 | B bool
138 | }
139 |
140 | s := S{42, "hello", true}
141 | packet := Marshal(s)
142 | roundtrip := S{}
143 | Unmarshal(packet, &roundtrip)
144 |
145 | if !reflect.DeepEqual(s, roundtrip) {
146 | t.Errorf("got %#v, want %#v", roundtrip, s)
147 | }
148 | }
149 |
150 | func TestBareMarshal(t *testing.T) {
151 | type S2 struct {
152 | I uint32
153 | }
154 | s := S2{42}
155 | packet := Marshal(s)
156 | i, rest, ok := parseUint32(packet)
157 | if len(rest) > 0 || !ok {
158 | t.Errorf("parseInt(%q): parse error", packet)
159 | }
160 | if i != s.I {
161 | t.Errorf("got %d, want %d", i, s.I)
162 | }
163 | }
164 |
165 | func randomBytes(out []byte, rand *rand.Rand) {
166 | for i := 0; i < len(out); i++ {
167 | out[i] = byte(rand.Int31())
168 | }
169 | }
170 |
171 | func randomNameList(rand *rand.Rand) []string {
172 | ret := make([]string, rand.Int31()&15)
173 | for i := range ret {
174 | s := make([]byte, 1+(rand.Int31()&15))
175 | for j := range s {
176 | s[j] = 'a' + uint8(rand.Int31()&15)
177 | }
178 | ret[i] = string(s)
179 | }
180 | return ret
181 | }
182 |
183 | func randomInt(rand *rand.Rand) *big.Int {
184 | return new(big.Int).SetInt64(int64(int32(rand.Uint32())))
185 | }
186 |
187 | func (*kexInitMsg) Generate(rand *rand.Rand, size int) reflect.Value {
188 | ki := &kexInitMsg{}
189 | randomBytes(ki.Cookie[:], rand)
190 | ki.KexAlgos = randomNameList(rand)
191 | ki.ServerHostKeyAlgos = randomNameList(rand)
192 | ki.CiphersClientServer = randomNameList(rand)
193 | ki.CiphersServerClient = randomNameList(rand)
194 | ki.MACsClientServer = randomNameList(rand)
195 | ki.MACsServerClient = randomNameList(rand)
196 | ki.CompressionClientServer = randomNameList(rand)
197 | ki.CompressionServerClient = randomNameList(rand)
198 | ki.LanguagesClientServer = randomNameList(rand)
199 | ki.LanguagesServerClient = randomNameList(rand)
200 | if rand.Int31()&1 == 1 {
201 | ki.FirstKexFollows = true
202 | }
203 | return reflect.ValueOf(ki)
204 | }
205 |
206 | func (*kexDHInitMsg) Generate(rand *rand.Rand, size int) reflect.Value {
207 | dhi := &kexDHInitMsg{}
208 | dhi.X = randomInt(rand)
209 | return reflect.ValueOf(dhi)
210 | }
211 |
212 | var (
213 | _kexInitMsg = new(kexInitMsg).Generate(rand.New(rand.NewSource(0)), 10).Elem().Interface()
214 | _kexDHInitMsg = new(kexDHInitMsg).Generate(rand.New(rand.NewSource(0)), 10).Elem().Interface()
215 |
216 | _kexInit = Marshal(_kexInitMsg)
217 | _kexDHInit = Marshal(_kexDHInitMsg)
218 | )
219 |
220 | func BenchmarkMarshalKexInitMsg(b *testing.B) {
221 | for i := 0; i < b.N; i++ {
222 | Marshal(_kexInitMsg)
223 | }
224 | }
225 |
226 | func BenchmarkUnmarshalKexInitMsg(b *testing.B) {
227 | m := new(kexInitMsg)
228 | for i := 0; i < b.N; i++ {
229 | Unmarshal(_kexInit, m)
230 | }
231 | }
232 |
233 | func BenchmarkMarshalKexDHInitMsg(b *testing.B) {
234 | for i := 0; i < b.N; i++ {
235 | Marshal(_kexDHInitMsg)
236 | }
237 | }
238 |
239 | func BenchmarkUnmarshalKexDHInitMsg(b *testing.B) {
240 | m := new(kexDHInitMsg)
241 | for i := 0; i < b.N; i++ {
242 | Unmarshal(_kexDHInit, m)
243 | }
244 | }
245 |
--------------------------------------------------------------------------------
/Godeps/_workspace/src/golang.org/x/crypto/ssh/tcpip_test.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014 The Go Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style
3 | // license that can be found in the LICENSE file.
4 |
5 | package ssh
6 |
7 | import (
8 | "testing"
9 | )
10 |
11 | func TestAutoPortListenBroken(t *testing.T) {
12 | broken := "SSH-2.0-OpenSSH_5.9hh11"
13 | works := "SSH-2.0-OpenSSH_6.1"
14 | if !isBrokenOpenSSHVersion(broken) {
15 | t.Errorf("version %q not marked as broken", broken)
16 | }
17 | if isBrokenOpenSSHVersion(works) {
18 | t.Errorf("version %q marked as broken", works)
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/Godeps/_workspace/src/golang.org/x/crypto/ssh/terminal/terminal_test.go:
--------------------------------------------------------------------------------
1 | // Copyright 2011 The Go Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style
3 | // license that can be found in the LICENSE file.
4 |
5 | package terminal
6 |
7 | import (
8 | "io"
9 | "testing"
10 | )
11 |
12 | type MockTerminal struct {
13 | toSend []byte
14 | bytesPerRead int
15 | received []byte
16 | }
17 |
18 | func (c *MockTerminal) Read(data []byte) (n int, err error) {
19 | n = len(data)
20 | if n == 0 {
21 | return
22 | }
23 | if n > len(c.toSend) {
24 | n = len(c.toSend)
25 | }
26 | if n == 0 {
27 | return 0, io.EOF
28 | }
29 | if c.bytesPerRead > 0 && n > c.bytesPerRead {
30 | n = c.bytesPerRead
31 | }
32 | copy(data, c.toSend[:n])
33 | c.toSend = c.toSend[n:]
34 | return
35 | }
36 |
37 | func (c *MockTerminal) Write(data []byte) (n int, err error) {
38 | c.received = append(c.received, data...)
39 | return len(data), nil
40 | }
41 |
42 | func TestClose(t *testing.T) {
43 | c := &MockTerminal{}
44 | ss := NewTerminal(c, "> ")
45 | line, err := ss.ReadLine()
46 | if line != "" {
47 | t.Errorf("Expected empty line but got: %s", line)
48 | }
49 | if err != io.EOF {
50 | t.Errorf("Error should have been EOF but got: %s", err)
51 | }
52 | }
53 |
54 | var keyPressTests = []struct {
55 | in string
56 | line string
57 | err error
58 | throwAwayLines int
59 | }{
60 | {
61 | err: io.EOF,
62 | },
63 | {
64 | in: "\r",
65 | line: "",
66 | },
67 | {
68 | in: "foo\r",
69 | line: "foo",
70 | },
71 | {
72 | in: "a\x1b[Cb\r", // right
73 | line: "ab",
74 | },
75 | {
76 | in: "a\x1b[Db\r", // left
77 | line: "ba",
78 | },
79 | {
80 | in: "a\177b\r", // backspace
81 | line: "b",
82 | },
83 | {
84 | in: "\x1b[A\r", // up
85 | },
86 | {
87 | in: "\x1b[B\r", // down
88 | },
89 | {
90 | in: "line\x1b[A\x1b[B\r", // up then down
91 | line: "line",
92 | },
93 | {
94 | in: "line1\rline2\x1b[A\r", // recall previous line.
95 | line: "line1",
96 | throwAwayLines: 1,
97 | },
98 | {
99 | // recall two previous lines and append.
100 | in: "line1\rline2\rline3\x1b[A\x1b[Axxx\r",
101 | line: "line1xxx",
102 | throwAwayLines: 2,
103 | },
104 | {
105 | // Ctrl-A to move to beginning of line followed by ^K to kill
106 | // line.
107 | in: "a b \001\013\r",
108 | line: "",
109 | },
110 | {
111 | // Ctrl-A to move to beginning of line, Ctrl-E to move to end,
112 | // finally ^K to kill nothing.
113 | in: "a b \001\005\013\r",
114 | line: "a b ",
115 | },
116 | {
117 | in: "\027\r",
118 | line: "",
119 | },
120 | {
121 | in: "a\027\r",
122 | line: "",
123 | },
124 | {
125 | in: "a \027\r",
126 | line: "",
127 | },
128 | {
129 | in: "a b\027\r",
130 | line: "a ",
131 | },
132 | {
133 | in: "a b \027\r",
134 | line: "a ",
135 | },
136 | {
137 | in: "one two thr\x1b[D\027\r",
138 | line: "one two r",
139 | },
140 | {
141 | in: "\013\r",
142 | line: "",
143 | },
144 | {
145 | in: "a\013\r",
146 | line: "a",
147 | },
148 | {
149 | in: "ab\x1b[D\013\r",
150 | line: "a",
151 | },
152 | {
153 | in: "Ξεσκεπάζω\r",
154 | line: "Ξεσκεπάζω",
155 | },
156 | {
157 | in: "£\r\x1b[A\177\r", // non-ASCII char, enter, up, backspace.
158 | line: "",
159 | throwAwayLines: 1,
160 | },
161 | {
162 | in: "£\r££\x1b[A\x1b[B\177\r", // non-ASCII char, enter, 2x non-ASCII, up, down, backspace, enter.
163 | line: "£",
164 | throwAwayLines: 1,
165 | },
166 | {
167 | // Ctrl-D at the end of the line should be ignored.
168 | in: "a\004\r",
169 | line: "a",
170 | },
171 | {
172 | // a, b, left, Ctrl-D should erase the b.
173 | in: "ab\x1b[D\004\r",
174 | line: "a",
175 | },
176 | {
177 | // a, b, c, d, left, left, ^U should erase to the beginning of
178 | // the line.
179 | in: "abcd\x1b[D\x1b[D\025\r",
180 | line: "cd",
181 | },
182 | {
183 | // Bracketed paste mode: control sequences should be returned
184 | // verbatim in paste mode.
185 | in: "abc\x1b[200~de\177f\x1b[201~\177\r",
186 | line: "abcde\177",
187 | },
188 | {
189 | // Enter in bracketed paste mode should still work.
190 | in: "abc\x1b[200~d\refg\x1b[201~h\r",
191 | line: "efgh",
192 | throwAwayLines: 1,
193 | },
194 | {
195 | // Lines consisting entirely of pasted data should be indicated as such.
196 | in: "\x1b[200~a\r",
197 | line: "a",
198 | err: ErrPasteIndicator,
199 | },
200 | }
201 |
202 | func TestKeyPresses(t *testing.T) {
203 | for i, test := range keyPressTests {
204 | for j := 1; j < len(test.in); j++ {
205 | c := &MockTerminal{
206 | toSend: []byte(test.in),
207 | bytesPerRead: j,
208 | }
209 | ss := NewTerminal(c, "> ")
210 | for k := 0; k < test.throwAwayLines; k++ {
211 | _, err := ss.ReadLine()
212 | if err != nil {
213 | t.Errorf("Throwaway line %d from test %d resulted in error: %s", k, i, err)
214 | }
215 | }
216 | line, err := ss.ReadLine()
217 | if line != test.line {
218 | t.Errorf("Line resulting from test %d (%d bytes per read) was '%s', expected '%s'", i, j, line, test.line)
219 | break
220 | }
221 | if err != test.err {
222 | t.Errorf("Error resulting from test %d (%d bytes per read) was '%v', expected '%v'", i, j, err, test.err)
223 | break
224 | }
225 | }
226 | }
227 | }
228 |
229 | func TestPasswordNotSaved(t *testing.T) {
230 | c := &MockTerminal{
231 | toSend: []byte("password\r\x1b[A\r"),
232 | bytesPerRead: 1,
233 | }
234 | ss := NewTerminal(c, "> ")
235 | pw, _ := ss.ReadPassword("> ")
236 | if pw != "password" {
237 | t.Fatalf("failed to read password, got %s", pw)
238 | }
239 | line, _ := ss.ReadLine()
240 | if len(line) > 0 {
241 | t.Fatalf("password was saved in history")
242 | }
243 | }
244 |
245 | var setSizeTests = []struct {
246 | width, height int
247 | }{
248 | {40, 13},
249 | {80, 24},
250 | {132, 43},
251 | }
252 |
253 | func TestTerminalSetSize(t *testing.T) {
254 | for _, setSize := range setSizeTests {
255 | c := &MockTerminal{
256 | toSend: []byte("password\r\x1b[A\r"),
257 | bytesPerRead: 1,
258 | }
259 | ss := NewTerminal(c, "> ")
260 | ss.SetSize(setSize.width, setSize.height)
261 | pw, _ := ss.ReadPassword("Password: ")
262 | if pw != "password" {
263 | t.Fatalf("failed to read password, got %s", pw)
264 | }
265 | if string(c.received) != "Password: \r\n" {
266 | t.Errorf("failed to set the temporary prompt expected %q, got %q", "Password: ", c.received)
267 | }
268 | }
269 | }
270 |
--------------------------------------------------------------------------------
/Godeps/_workspace/src/golang.org/x/crypto/ssh/terminal/util.go:
--------------------------------------------------------------------------------
1 | // Copyright 2011 The Go Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style
3 | // license that can be found in the LICENSE file.
4 |
5 | // +build darwin dragonfly freebsd linux,!appengine netbsd openbsd
6 |
7 | // Package terminal provides support functions for dealing with terminals, as
8 | // commonly found on UNIX systems.
9 | //
10 | // Putting a terminal into raw mode is the most common requirement:
11 | //
12 | // oldState, err := terminal.MakeRaw(0)
13 | // if err != nil {
14 | // panic(err)
15 | // }
16 | // defer terminal.Restore(0, oldState)
17 | package terminal // import "golang.org/x/crypto/ssh/terminal"
18 |
19 | import (
20 | "io"
21 | "syscall"
22 | "unsafe"
23 | )
24 |
25 | // State contains the state of a terminal.
26 | type State struct {
27 | termios syscall.Termios
28 | }
29 |
30 | // IsTerminal returns true if the given file descriptor is a terminal.
31 | func IsTerminal(fd int) bool {
32 | var termios syscall.Termios
33 | _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlReadTermios, uintptr(unsafe.Pointer(&termios)), 0, 0, 0)
34 | return err == 0
35 | }
36 |
37 | // MakeRaw put the terminal connected to the given file descriptor into raw
38 | // mode and returns the previous state of the terminal so that it can be
39 | // restored.
40 | func MakeRaw(fd int) (*State, error) {
41 | var oldState State
42 | if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlReadTermios, uintptr(unsafe.Pointer(&oldState.termios)), 0, 0, 0); err != 0 {
43 | return nil, err
44 | }
45 |
46 | newState := oldState.termios
47 | newState.Iflag &^= syscall.ISTRIP | syscall.INLCR | syscall.ICRNL | syscall.IGNCR | syscall.IXON | syscall.IXOFF
48 | newState.Lflag &^= syscall.ECHO | syscall.ICANON | syscall.ISIG
49 | if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlWriteTermios, uintptr(unsafe.Pointer(&newState)), 0, 0, 0); err != 0 {
50 | return nil, err
51 | }
52 |
53 | return &oldState, nil
54 | }
55 |
56 | // GetState returns the current state of a terminal which may be useful to
57 | // restore the terminal after a signal.
58 | func GetState(fd int) (*State, error) {
59 | var oldState State
60 | if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlReadTermios, uintptr(unsafe.Pointer(&oldState.termios)), 0, 0, 0); err != 0 {
61 | return nil, err
62 | }
63 |
64 | return &oldState, nil
65 | }
66 |
67 | // Restore restores the terminal connected to the given file descriptor to a
68 | // previous state.
69 | func Restore(fd int, state *State) error {
70 | _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlWriteTermios, uintptr(unsafe.Pointer(&state.termios)), 0, 0, 0)
71 | return err
72 | }
73 |
74 | // GetSize returns the dimensions of the given terminal.
75 | func GetSize(fd int) (width, height int, err error) {
76 | var dimensions [4]uint16
77 |
78 | if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), uintptr(syscall.TIOCGWINSZ), uintptr(unsafe.Pointer(&dimensions)), 0, 0, 0); err != 0 {
79 | return -1, -1, err
80 | }
81 | return int(dimensions[1]), int(dimensions[0]), nil
82 | }
83 |
84 | // ReadPassword reads a line of input from a terminal without local echo. This
85 | // is commonly used for inputting passwords and other sensitive data. The slice
86 | // returned does not include the \n.
87 | func ReadPassword(fd int) ([]byte, error) {
88 | var oldState syscall.Termios
89 | if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlReadTermios, uintptr(unsafe.Pointer(&oldState)), 0, 0, 0); err != 0 {
90 | return nil, err
91 | }
92 |
93 | newState := oldState
94 | newState.Lflag &^= syscall.ECHO
95 | newState.Lflag |= syscall.ICANON | syscall.ISIG
96 | newState.Iflag |= syscall.ICRNL
97 | if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlWriteTermios, uintptr(unsafe.Pointer(&newState)), 0, 0, 0); err != 0 {
98 | return nil, err
99 | }
100 |
101 | defer func() {
102 | syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlWriteTermios, uintptr(unsafe.Pointer(&oldState)), 0, 0, 0)
103 | }()
104 |
105 | var buf [16]byte
106 | var ret []byte
107 | for {
108 | n, err := syscall.Read(fd, buf[:])
109 | if err != nil {
110 | return nil, err
111 | }
112 | if n == 0 {
113 | if len(ret) == 0 {
114 | return nil, io.EOF
115 | }
116 | break
117 | }
118 | if buf[n-1] == '\n' {
119 | n--
120 | }
121 | ret = append(ret, buf[:n]...)
122 | if n < len(buf) {
123 | break
124 | }
125 | }
126 |
127 | return ret, nil
128 | }
129 |
--------------------------------------------------------------------------------
/Godeps/_workspace/src/golang.org/x/crypto/ssh/terminal/util_bsd.go:
--------------------------------------------------------------------------------
1 | // Copyright 2013 The Go Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style
3 | // license that can be found in the LICENSE file.
4 |
5 | // +build darwin dragonfly freebsd netbsd openbsd
6 |
7 | package terminal
8 |
9 | import "syscall"
10 |
11 | const ioctlReadTermios = syscall.TIOCGETA
12 | const ioctlWriteTermios = syscall.TIOCSETA
13 |
--------------------------------------------------------------------------------
/Godeps/_workspace/src/golang.org/x/crypto/ssh/terminal/util_linux.go:
--------------------------------------------------------------------------------
1 | // Copyright 2013 The Go Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style
3 | // license that can be found in the LICENSE file.
4 |
5 | package terminal
6 |
7 | // These constants are declared here, rather than importing
8 | // them from the syscall package as some syscall packages, even
9 | // on linux, for example gccgo, do not declare them.
10 | const ioctlReadTermios = 0x5401 // syscall.TCGETS
11 | const ioctlWriteTermios = 0x5402 // syscall.TCSETS
12 |
--------------------------------------------------------------------------------
/Godeps/_workspace/src/golang.org/x/crypto/ssh/terminal/util_windows.go:
--------------------------------------------------------------------------------
1 | // Copyright 2011 The Go Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style
3 | // license that can be found in the LICENSE file.
4 |
5 | // +build windows
6 |
7 | // Package terminal provides support functions for dealing with terminals, as
8 | // commonly found on UNIX systems.
9 | //
10 | // Putting a terminal into raw mode is the most common requirement:
11 | //
12 | // oldState, err := terminal.MakeRaw(0)
13 | // if err != nil {
14 | // panic(err)
15 | // }
16 | // defer terminal.Restore(0, oldState)
17 | package terminal
18 |
19 | import (
20 | "io"
21 | "syscall"
22 | "unsafe"
23 | )
24 |
25 | const (
26 | enableLineInput = 2
27 | enableEchoInput = 4
28 | enableProcessedInput = 1
29 | enableWindowInput = 8
30 | enableMouseInput = 16
31 | enableInsertMode = 32
32 | enableQuickEditMode = 64
33 | enableExtendedFlags = 128
34 | enableAutoPosition = 256
35 | enableProcessedOutput = 1
36 | enableWrapAtEolOutput = 2
37 | )
38 |
39 | var kernel32 = syscall.NewLazyDLL("kernel32.dll")
40 |
41 | var (
42 | procGetConsoleMode = kernel32.NewProc("GetConsoleMode")
43 | procSetConsoleMode = kernel32.NewProc("SetConsoleMode")
44 | procGetConsoleScreenBufferInfo = kernel32.NewProc("GetConsoleScreenBufferInfo")
45 | )
46 |
47 | type (
48 | short int16
49 | word uint16
50 |
51 | coord struct {
52 | x short
53 | y short
54 | }
55 | smallRect struct {
56 | left short
57 | top short
58 | right short
59 | bottom short
60 | }
61 | consoleScreenBufferInfo struct {
62 | size coord
63 | cursorPosition coord
64 | attributes word
65 | window smallRect
66 | maximumWindowSize coord
67 | }
68 | )
69 |
70 | type State struct {
71 | mode uint32
72 | }
73 |
74 | // IsTerminal returns true if the given file descriptor is a terminal.
75 | func IsTerminal(fd int) bool {
76 | var st uint32
77 | r, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, uintptr(fd), uintptr(unsafe.Pointer(&st)), 0)
78 | return r != 0 && e == 0
79 | }
80 |
81 | // MakeRaw put the terminal connected to the given file descriptor into raw
82 | // mode and returns the previous state of the terminal so that it can be
83 | // restored.
84 | func MakeRaw(fd int) (*State, error) {
85 | var st uint32
86 | _, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, uintptr(fd), uintptr(unsafe.Pointer(&st)), 0)
87 | if e != 0 {
88 | return nil, error(e)
89 | }
90 | st &^= (enableEchoInput | enableProcessedInput | enableLineInput | enableProcessedOutput)
91 | _, _, e = syscall.Syscall(procSetConsoleMode.Addr(), 2, uintptr(fd), uintptr(st), 0)
92 | if e != 0 {
93 | return nil, error(e)
94 | }
95 | return &State{st}, nil
96 | }
97 |
98 | // GetState returns the current state of a terminal which may be useful to
99 | // restore the terminal after a signal.
100 | func GetState(fd int) (*State, error) {
101 | var st uint32
102 | _, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, uintptr(fd), uintptr(unsafe.Pointer(&st)), 0)
103 | if e != 0 {
104 | return nil, error(e)
105 | }
106 | return &State{st}, nil
107 | }
108 |
109 | // Restore restores the terminal connected to the given file descriptor to a
110 | // previous state.
111 | func Restore(fd int, state *State) error {
112 | _, _, err := syscall.Syscall(procSetConsoleMode.Addr(), 2, uintptr(fd), uintptr(state.mode), 0)
113 | return err
114 | }
115 |
116 | // GetSize returns the dimensions of the given terminal.
117 | func GetSize(fd int) (width, height int, err error) {
118 | var info consoleScreenBufferInfo
119 | _, _, e := syscall.Syscall(procGetConsoleScreenBufferInfo.Addr(), 2, uintptr(fd), uintptr(unsafe.Pointer(&info)), 0)
120 | if e != 0 {
121 | return 0, 0, error(e)
122 | }
123 | return int(info.size.x), int(info.size.y), nil
124 | }
125 |
126 | // ReadPassword reads a line of input from a terminal without local echo. This
127 | // is commonly used for inputting passwords and other sensitive data. The slice
128 | // returned does not include the \n.
129 | func ReadPassword(fd int) ([]byte, error) {
130 | var st uint32
131 | _, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, uintptr(fd), uintptr(unsafe.Pointer(&st)), 0)
132 | if e != 0 {
133 | return nil, error(e)
134 | }
135 | old := st
136 |
137 | st &^= (enableEchoInput)
138 | st |= (enableProcessedInput | enableLineInput | enableProcessedOutput)
139 | _, _, e = syscall.Syscall(procSetConsoleMode.Addr(), 2, uintptr(fd), uintptr(st), 0)
140 | if e != 0 {
141 | return nil, error(e)
142 | }
143 |
144 | defer func() {
145 | syscall.Syscall(procSetConsoleMode.Addr(), 2, uintptr(fd), uintptr(old), 0)
146 | }()
147 |
148 | var buf [16]byte
149 | var ret []byte
150 | for {
151 | n, err := syscall.Read(syscall.Handle(fd), buf[:])
152 | if err != nil {
153 | return nil, err
154 | }
155 | if n == 0 {
156 | if len(ret) == 0 {
157 | return nil, io.EOF
158 | }
159 | break
160 | }
161 | if buf[n-1] == '\n' {
162 | n--
163 | }
164 | if n > 0 && buf[n-1] == '\r' {
165 | n--
166 | }
167 | ret = append(ret, buf[:n]...)
168 | if n < len(buf) {
169 | break
170 | }
171 | }
172 |
173 | return ret, nil
174 | }
175 |
--------------------------------------------------------------------------------
/Godeps/_workspace/src/golang.org/x/crypto/ssh/test/agent_unix_test.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014 The Go Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style
3 | // license that can be found in the LICENSE file.
4 |
5 | // +build darwin dragonfly freebsd linux netbsd openbsd
6 |
7 | package test
8 |
9 | import (
10 | "bytes"
11 | "testing"
12 |
13 | "golang.org/x/crypto/ssh"
14 | "golang.org/x/crypto/ssh/agent"
15 | )
16 |
17 | func TestAgentForward(t *testing.T) {
18 | server := newServer(t)
19 | defer server.Shutdown()
20 | conn := server.Dial(clientConfig())
21 | defer conn.Close()
22 |
23 | keyring := agent.NewKeyring()
24 | keyring.Add(testPrivateKeys["dsa"], nil, "")
25 | pub := testPublicKeys["dsa"]
26 |
27 | sess, err := conn.NewSession()
28 | if err != nil {
29 | t.Fatalf("NewSession: %v", err)
30 | }
31 | if err := agent.RequestAgentForwarding(sess); err != nil {
32 | t.Fatalf("RequestAgentForwarding: %v", err)
33 | }
34 |
35 | if err := agent.ForwardToAgent(conn, keyring); err != nil {
36 | t.Fatalf("SetupForwardKeyring: %v", err)
37 | }
38 | out, err := sess.CombinedOutput("ssh-add -L")
39 | if err != nil {
40 | t.Fatalf("running ssh-add: %v, out %s", err, out)
41 | }
42 | key, _, _, _, err := ssh.ParseAuthorizedKey(out)
43 | if err != nil {
44 | t.Fatalf("ParseAuthorizedKey(%q): %v", out, err)
45 | }
46 |
47 | if !bytes.Equal(key.Marshal(), pub.Marshal()) {
48 | t.Fatalf("got key %s, want %s", ssh.MarshalAuthorizedKey(key), ssh.MarshalAuthorizedKey(pub))
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/Godeps/_workspace/src/golang.org/x/crypto/ssh/test/cert_test.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014 The Go Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style
3 | // license that can be found in the LICENSE file.
4 |
5 | // +build darwin dragonfly freebsd linux netbsd openbsd
6 |
7 | package test
8 |
9 | import (
10 | "crypto/rand"
11 | "testing"
12 |
13 | "golang.org/x/crypto/ssh"
14 | )
15 |
16 | func TestCertLogin(t *testing.T) {
17 | s := newServer(t)
18 | defer s.Shutdown()
19 |
20 | // Use a key different from the default.
21 | clientKey := testSigners["dsa"]
22 | caAuthKey := testSigners["ecdsa"]
23 | cert := &ssh.Certificate{
24 | Key: clientKey.PublicKey(),
25 | ValidPrincipals: []string{username()},
26 | CertType: ssh.UserCert,
27 | ValidBefore: ssh.CertTimeInfinity,
28 | }
29 | if err := cert.SignCert(rand.Reader, caAuthKey); err != nil {
30 | t.Fatalf("SetSignature: %v", err)
31 | }
32 |
33 | certSigner, err := ssh.NewCertSigner(cert, clientKey)
34 | if err != nil {
35 | t.Fatalf("NewCertSigner: %v", err)
36 | }
37 |
38 | conf := &ssh.ClientConfig{
39 | User: username(),
40 | }
41 | conf.Auth = append(conf.Auth, ssh.PublicKeys(certSigner))
42 | client, err := s.TryDial(conf)
43 | if err != nil {
44 | t.Fatalf("TryDial: %v", err)
45 | }
46 | client.Close()
47 | }
48 |
--------------------------------------------------------------------------------
/Godeps/_workspace/src/golang.org/x/crypto/ssh/test/doc.go:
--------------------------------------------------------------------------------
1 | // Copyright 2012 The Go Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style
3 | // license that can be found in the LICENSE file.
4 |
5 | // This package contains integration tests for the
6 | // code.google.com/p/go.crypto/ssh package.
7 | package test // import "golang.org/x/crypto/ssh/test"
8 |
--------------------------------------------------------------------------------
/Godeps/_workspace/src/golang.org/x/crypto/ssh/test/forward_unix_test.go:
--------------------------------------------------------------------------------
1 | // Copyright 2012 The Go Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style
3 | // license that can be found in the LICENSE file.
4 |
5 | // +build darwin dragonfly freebsd linux netbsd openbsd
6 |
7 | package test
8 |
9 | import (
10 | "bytes"
11 | "io"
12 | "io/ioutil"
13 | "math/rand"
14 | "net"
15 | "testing"
16 | "time"
17 | )
18 |
19 | func TestPortForward(t *testing.T) {
20 | server := newServer(t)
21 | defer server.Shutdown()
22 | conn := server.Dial(clientConfig())
23 | defer conn.Close()
24 |
25 | sshListener, err := conn.Listen("tcp", "localhost:0")
26 | if err != nil {
27 | t.Fatal(err)
28 | }
29 |
30 | go func() {
31 | sshConn, err := sshListener.Accept()
32 | if err != nil {
33 | t.Fatalf("listen.Accept failed: %v", err)
34 | }
35 |
36 | _, err = io.Copy(sshConn, sshConn)
37 | if err != nil && err != io.EOF {
38 | t.Fatalf("ssh client copy: %v", err)
39 | }
40 | sshConn.Close()
41 | }()
42 |
43 | forwardedAddr := sshListener.Addr().String()
44 | tcpConn, err := net.Dial("tcp", forwardedAddr)
45 | if err != nil {
46 | t.Fatalf("TCP dial failed: %v", err)
47 | }
48 |
49 | readChan := make(chan []byte)
50 | go func() {
51 | data, _ := ioutil.ReadAll(tcpConn)
52 | readChan <- data
53 | }()
54 |
55 | // Invent some data.
56 | data := make([]byte, 100*1000)
57 | for i := range data {
58 | data[i] = byte(i % 255)
59 | }
60 |
61 | var sent []byte
62 | for len(sent) < 1000*1000 {
63 | // Send random sized chunks
64 | m := rand.Intn(len(data))
65 | n, err := tcpConn.Write(data[:m])
66 | if err != nil {
67 | break
68 | }
69 | sent = append(sent, data[:n]...)
70 | }
71 | if err := tcpConn.(*net.TCPConn).CloseWrite(); err != nil {
72 | t.Errorf("tcpConn.CloseWrite: %v", err)
73 | }
74 |
75 | read := <-readChan
76 |
77 | if len(sent) != len(read) {
78 | t.Fatalf("got %d bytes, want %d", len(read), len(sent))
79 | }
80 | if bytes.Compare(sent, read) != 0 {
81 | t.Fatalf("read back data does not match")
82 | }
83 |
84 | if err := sshListener.Close(); err != nil {
85 | t.Fatalf("sshListener.Close: %v", err)
86 | }
87 |
88 | // Check that the forward disappeared.
89 | tcpConn, err = net.Dial("tcp", forwardedAddr)
90 | if err == nil {
91 | tcpConn.Close()
92 | t.Errorf("still listening to %s after closing", forwardedAddr)
93 | }
94 | }
95 |
96 | func TestAcceptClose(t *testing.T) {
97 | server := newServer(t)
98 | defer server.Shutdown()
99 | conn := server.Dial(clientConfig())
100 |
101 | sshListener, err := conn.Listen("tcp", "localhost:0")
102 | if err != nil {
103 | t.Fatal(err)
104 | }
105 |
106 | quit := make(chan error, 1)
107 | go func() {
108 | for {
109 | c, err := sshListener.Accept()
110 | if err != nil {
111 | quit <- err
112 | break
113 | }
114 | c.Close()
115 | }
116 | }()
117 | sshListener.Close()
118 |
119 | select {
120 | case <-time.After(1 * time.Second):
121 | t.Errorf("timeout: listener did not close.")
122 | case err := <-quit:
123 | t.Logf("quit as expected (error %v)", err)
124 | }
125 | }
126 |
127 | // Check that listeners exit if the underlying client transport dies.
128 | func TestPortForwardConnectionClose(t *testing.T) {
129 | server := newServer(t)
130 | defer server.Shutdown()
131 | conn := server.Dial(clientConfig())
132 |
133 | sshListener, err := conn.Listen("tcp", "localhost:0")
134 | if err != nil {
135 | t.Fatal(err)
136 | }
137 |
138 | quit := make(chan error, 1)
139 | go func() {
140 | for {
141 | c, err := sshListener.Accept()
142 | if err != nil {
143 | quit <- err
144 | break
145 | }
146 | c.Close()
147 | }
148 | }()
149 |
150 | // It would be even nicer if we closed the server side, but it
151 | // is more involved as the fd for that side is dup()ed.
152 | server.clientConn.Close()
153 |
154 | select {
155 | case <-time.After(1 * time.Second):
156 | t.Errorf("timeout: listener did not close.")
157 | case err := <-quit:
158 | t.Logf("quit as expected (error %v)", err)
159 | }
160 | }
161 |
--------------------------------------------------------------------------------
/Godeps/_workspace/src/golang.org/x/crypto/ssh/test/session_test.go:
--------------------------------------------------------------------------------
1 | // Copyright 2012 The Go Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style
3 | // license that can be found in the LICENSE file.
4 |
5 | // +build !windows
6 |
7 | package test
8 |
9 | // Session functional tests.
10 |
11 | import (
12 | "bytes"
13 | "errors"
14 | "io"
15 | "strings"
16 | "testing"
17 |
18 | "golang.org/x/crypto/ssh"
19 | )
20 |
21 | func TestRunCommandSuccess(t *testing.T) {
22 | server := newServer(t)
23 | defer server.Shutdown()
24 | conn := server.Dial(clientConfig())
25 | defer conn.Close()
26 |
27 | session, err := conn.NewSession()
28 | if err != nil {
29 | t.Fatalf("session failed: %v", err)
30 | }
31 | defer session.Close()
32 | err = session.Run("true")
33 | if err != nil {
34 | t.Fatalf("session failed: %v", err)
35 | }
36 | }
37 |
38 | func TestHostKeyCheck(t *testing.T) {
39 | server := newServer(t)
40 | defer server.Shutdown()
41 |
42 | conf := clientConfig()
43 | hostDB := hostKeyDB()
44 | conf.HostKeyCallback = hostDB.Check
45 |
46 | // change the keys.
47 | hostDB.keys[ssh.KeyAlgoRSA][25]++
48 | hostDB.keys[ssh.KeyAlgoDSA][25]++
49 | hostDB.keys[ssh.KeyAlgoECDSA256][25]++
50 |
51 | conn, err := server.TryDial(conf)
52 | if err == nil {
53 | conn.Close()
54 | t.Fatalf("dial should have failed.")
55 | } else if !strings.Contains(err.Error(), "host key mismatch") {
56 | t.Fatalf("'host key mismatch' not found in %v", err)
57 | }
58 | }
59 |
60 | func TestRunCommandStdin(t *testing.T) {
61 | server := newServer(t)
62 | defer server.Shutdown()
63 | conn := server.Dial(clientConfig())
64 | defer conn.Close()
65 |
66 | session, err := conn.NewSession()
67 | if err != nil {
68 | t.Fatalf("session failed: %v", err)
69 | }
70 | defer session.Close()
71 |
72 | r, w := io.Pipe()
73 | defer r.Close()
74 | defer w.Close()
75 | session.Stdin = r
76 |
77 | err = session.Run("true")
78 | if err != nil {
79 | t.Fatalf("session failed: %v", err)
80 | }
81 | }
82 |
83 | func TestRunCommandStdinError(t *testing.T) {
84 | server := newServer(t)
85 | defer server.Shutdown()
86 | conn := server.Dial(clientConfig())
87 | defer conn.Close()
88 |
89 | session, err := conn.NewSession()
90 | if err != nil {
91 | t.Fatalf("session failed: %v", err)
92 | }
93 | defer session.Close()
94 |
95 | r, w := io.Pipe()
96 | defer r.Close()
97 | session.Stdin = r
98 | pipeErr := errors.New("closing write end of pipe")
99 | w.CloseWithError(pipeErr)
100 |
101 | err = session.Run("true")
102 | if err != pipeErr {
103 | t.Fatalf("expected %v, found %v", pipeErr, err)
104 | }
105 | }
106 |
107 | func TestRunCommandFailed(t *testing.T) {
108 | server := newServer(t)
109 | defer server.Shutdown()
110 | conn := server.Dial(clientConfig())
111 | defer conn.Close()
112 |
113 | session, err := conn.NewSession()
114 | if err != nil {
115 | t.Fatalf("session failed: %v", err)
116 | }
117 | defer session.Close()
118 | err = session.Run(`bash -c "kill -9 $$"`)
119 | if err == nil {
120 | t.Fatalf("session succeeded: %v", err)
121 | }
122 | }
123 |
124 | func TestRunCommandWeClosed(t *testing.T) {
125 | server := newServer(t)
126 | defer server.Shutdown()
127 | conn := server.Dial(clientConfig())
128 | defer conn.Close()
129 |
130 | session, err := conn.NewSession()
131 | if err != nil {
132 | t.Fatalf("session failed: %v", err)
133 | }
134 | err = session.Shell()
135 | if err != nil {
136 | t.Fatalf("shell failed: %v", err)
137 | }
138 | err = session.Close()
139 | if err != nil {
140 | t.Fatalf("shell failed: %v", err)
141 | }
142 | }
143 |
144 | func TestFuncLargeRead(t *testing.T) {
145 | server := newServer(t)
146 | defer server.Shutdown()
147 | conn := server.Dial(clientConfig())
148 | defer conn.Close()
149 |
150 | session, err := conn.NewSession()
151 | if err != nil {
152 | t.Fatalf("unable to create new session: %s", err)
153 | }
154 |
155 | stdout, err := session.StdoutPipe()
156 | if err != nil {
157 | t.Fatalf("unable to acquire stdout pipe: %s", err)
158 | }
159 |
160 | err = session.Start("dd if=/dev/urandom bs=2048 count=1024")
161 | if err != nil {
162 | t.Fatalf("unable to execute remote command: %s", err)
163 | }
164 |
165 | buf := new(bytes.Buffer)
166 | n, err := io.Copy(buf, stdout)
167 | if err != nil {
168 | t.Fatalf("error reading from remote stdout: %s", err)
169 | }
170 |
171 | if n != 2048*1024 {
172 | t.Fatalf("Expected %d bytes but read only %d from remote command", 2048, n)
173 | }
174 | }
175 |
176 | func TestKeyChange(t *testing.T) {
177 | server := newServer(t)
178 | defer server.Shutdown()
179 | conf := clientConfig()
180 | hostDB := hostKeyDB()
181 | conf.HostKeyCallback = hostDB.Check
182 | conf.RekeyThreshold = 1024
183 | conn := server.Dial(conf)
184 | defer conn.Close()
185 |
186 | for i := 0; i < 4; i++ {
187 | session, err := conn.NewSession()
188 | if err != nil {
189 | t.Fatalf("unable to create new session: %s", err)
190 | }
191 |
192 | stdout, err := session.StdoutPipe()
193 | if err != nil {
194 | t.Fatalf("unable to acquire stdout pipe: %s", err)
195 | }
196 |
197 | err = session.Start("dd if=/dev/urandom bs=1024 count=1")
198 | if err != nil {
199 | t.Fatalf("unable to execute remote command: %s", err)
200 | }
201 | buf := new(bytes.Buffer)
202 | n, err := io.Copy(buf, stdout)
203 | if err != nil {
204 | t.Fatalf("error reading from remote stdout: %s", err)
205 | }
206 |
207 | want := int64(1024)
208 | if n != want {
209 | t.Fatalf("Expected %d bytes but read only %d from remote command", want, n)
210 | }
211 | }
212 |
213 | if changes := hostDB.checkCount; changes < 4 {
214 | t.Errorf("got %d key changes, want 4", changes)
215 | }
216 | }
217 |
218 | func TestInvalidTerminalMode(t *testing.T) {
219 | server := newServer(t)
220 | defer server.Shutdown()
221 | conn := server.Dial(clientConfig())
222 | defer conn.Close()
223 |
224 | session, err := conn.NewSession()
225 | if err != nil {
226 | t.Fatalf("session failed: %v", err)
227 | }
228 | defer session.Close()
229 |
230 | if err = session.RequestPty("vt100", 80, 40, ssh.TerminalModes{255: 1984}); err == nil {
231 | t.Fatalf("req-pty failed: successful request with invalid mode")
232 | }
233 | }
234 |
235 | func TestValidTerminalMode(t *testing.T) {
236 | server := newServer(t)
237 | defer server.Shutdown()
238 | conn := server.Dial(clientConfig())
239 | defer conn.Close()
240 |
241 | session, err := conn.NewSession()
242 | if err != nil {
243 | t.Fatalf("session failed: %v", err)
244 | }
245 | defer session.Close()
246 |
247 | stdout, err := session.StdoutPipe()
248 | if err != nil {
249 | t.Fatalf("unable to acquire stdout pipe: %s", err)
250 | }
251 |
252 | stdin, err := session.StdinPipe()
253 | if err != nil {
254 | t.Fatalf("unable to acquire stdin pipe: %s", err)
255 | }
256 |
257 | tm := ssh.TerminalModes{ssh.ECHO: 0}
258 | if err = session.RequestPty("xterm", 80, 40, tm); err != nil {
259 | t.Fatalf("req-pty failed: %s", err)
260 | }
261 |
262 | err = session.Shell()
263 | if err != nil {
264 | t.Fatalf("session failed: %s", err)
265 | }
266 |
267 | stdin.Write([]byte("stty -a && exit\n"))
268 |
269 | var buf bytes.Buffer
270 | if _, err := io.Copy(&buf, stdout); err != nil {
271 | t.Fatalf("reading failed: %s", err)
272 | }
273 |
274 | if sttyOutput := buf.String(); !strings.Contains(sttyOutput, "-echo ") {
275 | t.Fatalf("terminal mode failure: expected -echo in stty output, got %s", sttyOutput)
276 | }
277 | }
278 |
279 | func TestCiphers(t *testing.T) {
280 | var config ssh.Config
281 | config.SetDefaults()
282 | cipherOrder := config.Ciphers
283 |
284 | for _, ciph := range cipherOrder {
285 | server := newServer(t)
286 | defer server.Shutdown()
287 | conf := clientConfig()
288 | conf.Ciphers = []string{ciph}
289 | // Don't fail if sshd doesnt have the cipher.
290 | conf.Ciphers = append(conf.Ciphers, cipherOrder...)
291 | conn, err := server.TryDial(conf)
292 | if err == nil {
293 | conn.Close()
294 | } else {
295 | t.Fatalf("failed for cipher %q", ciph)
296 | }
297 | }
298 | }
299 |
300 | func TestMACs(t *testing.T) {
301 | var config ssh.Config
302 | config.SetDefaults()
303 | macOrder := config.MACs
304 |
305 | for _, mac := range macOrder {
306 | server := newServer(t)
307 | defer server.Shutdown()
308 | conf := clientConfig()
309 | conf.MACs = []string{mac}
310 | // Don't fail if sshd doesnt have the MAC.
311 | conf.MACs = append(conf.MACs, macOrder...)
312 | if conn, err := server.TryDial(conf); err == nil {
313 | conn.Close()
314 | } else {
315 | t.Fatalf("failed for MAC %q", mac)
316 | }
317 | }
318 | }
319 |
--------------------------------------------------------------------------------
/Godeps/_workspace/src/golang.org/x/crypto/ssh/test/tcpip_test.go:
--------------------------------------------------------------------------------
1 | // Copyright 2012 The Go Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style
3 | // license that can be found in the LICENSE file.
4 |
5 | // +build !windows
6 |
7 | package test
8 |
9 | // direct-tcpip functional tests
10 |
11 | import (
12 | "io"
13 | "net"
14 | "testing"
15 | )
16 |
17 | func TestDial(t *testing.T) {
18 | server := newServer(t)
19 | defer server.Shutdown()
20 | sshConn := server.Dial(clientConfig())
21 | defer sshConn.Close()
22 |
23 | l, err := net.Listen("tcp", "127.0.0.1:0")
24 | if err != nil {
25 | t.Fatalf("Listen: %v", err)
26 | }
27 | defer l.Close()
28 |
29 | go func() {
30 | for {
31 | c, err := l.Accept()
32 | if err != nil {
33 | break
34 | }
35 |
36 | io.WriteString(c, c.RemoteAddr().String())
37 | c.Close()
38 | }
39 | }()
40 |
41 | conn, err := sshConn.Dial("tcp", l.Addr().String())
42 | if err != nil {
43 | t.Fatalf("Dial: %v", err)
44 | }
45 | defer conn.Close()
46 | }
47 |
--------------------------------------------------------------------------------
/Godeps/_workspace/src/golang.org/x/crypto/ssh/test/test_unix_test.go:
--------------------------------------------------------------------------------
1 | // Copyright 2012 The Go Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style
3 | // license that can be found in the LICENSE file.
4 |
5 | // +build darwin dragonfly freebsd linux netbsd openbsd plan9
6 |
7 | package test
8 |
9 | // functional test harness for unix.
10 |
11 | import (
12 | "bytes"
13 | "fmt"
14 | "io/ioutil"
15 | "log"
16 | "net"
17 | "os"
18 | "os/exec"
19 | "os/user"
20 | "path/filepath"
21 | "testing"
22 | "text/template"
23 |
24 | "golang.org/x/crypto/ssh"
25 | "golang.org/x/crypto/ssh/testdata"
26 | )
27 |
28 | const sshd_config = `
29 | Protocol 2
30 | HostKey {{.Dir}}/id_rsa
31 | HostKey {{.Dir}}/id_dsa
32 | HostKey {{.Dir}}/id_ecdsa
33 | Pidfile {{.Dir}}/sshd.pid
34 | #UsePrivilegeSeparation no
35 | KeyRegenerationInterval 3600
36 | ServerKeyBits 768
37 | SyslogFacility AUTH
38 | LogLevel DEBUG2
39 | LoginGraceTime 120
40 | PermitRootLogin no
41 | StrictModes no
42 | RSAAuthentication yes
43 | PubkeyAuthentication yes
44 | AuthorizedKeysFile {{.Dir}}/id_user.pub
45 | TrustedUserCAKeys {{.Dir}}/id_ecdsa.pub
46 | IgnoreRhosts yes
47 | RhostsRSAAuthentication no
48 | HostbasedAuthentication no
49 | `
50 |
51 | var configTmpl = template.Must(template.New("").Parse(sshd_config))
52 |
53 | type server struct {
54 | t *testing.T
55 | cleanup func() // executed during Shutdown
56 | configfile string
57 | cmd *exec.Cmd
58 | output bytes.Buffer // holds stderr from sshd process
59 |
60 | // Client half of the network connection.
61 | clientConn net.Conn
62 | }
63 |
64 | func username() string {
65 | var username string
66 | if user, err := user.Current(); err == nil {
67 | username = user.Username
68 | } else {
69 | // user.Current() currently requires cgo. If an error is
70 | // returned attempt to get the username from the environment.
71 | log.Printf("user.Current: %v; falling back on $USER", err)
72 | username = os.Getenv("USER")
73 | }
74 | if username == "" {
75 | panic("Unable to get username")
76 | }
77 | return username
78 | }
79 |
80 | type storedHostKey struct {
81 | // keys map from an algorithm string to binary key data.
82 | keys map[string][]byte
83 |
84 | // checkCount counts the Check calls. Used for testing
85 | // rekeying.
86 | checkCount int
87 | }
88 |
89 | func (k *storedHostKey) Add(key ssh.PublicKey) {
90 | if k.keys == nil {
91 | k.keys = map[string][]byte{}
92 | }
93 | k.keys[key.Type()] = key.Marshal()
94 | }
95 |
96 | func (k *storedHostKey) Check(addr string, remote net.Addr, key ssh.PublicKey) error {
97 | k.checkCount++
98 | algo := key.Type()
99 |
100 | if k.keys == nil || bytes.Compare(key.Marshal(), k.keys[algo]) != 0 {
101 | return fmt.Errorf("host key mismatch. Got %q, want %q", key, k.keys[algo])
102 | }
103 | return nil
104 | }
105 |
106 | func hostKeyDB() *storedHostKey {
107 | keyChecker := &storedHostKey{}
108 | keyChecker.Add(testPublicKeys["ecdsa"])
109 | keyChecker.Add(testPublicKeys["rsa"])
110 | keyChecker.Add(testPublicKeys["dsa"])
111 | return keyChecker
112 | }
113 |
114 | func clientConfig() *ssh.ClientConfig {
115 | config := &ssh.ClientConfig{
116 | User: username(),
117 | Auth: []ssh.AuthMethod{
118 | ssh.PublicKeys(testSigners["user"]),
119 | },
120 | HostKeyCallback: hostKeyDB().Check,
121 | }
122 | return config
123 | }
124 |
125 | // unixConnection creates two halves of a connected net.UnixConn. It
126 | // is used for connecting the Go SSH client with sshd without opening
127 | // ports.
128 | func unixConnection() (*net.UnixConn, *net.UnixConn, error) {
129 | dir, err := ioutil.TempDir("", "unixConnection")
130 | if err != nil {
131 | return nil, nil, err
132 | }
133 | defer os.Remove(dir)
134 |
135 | addr := filepath.Join(dir, "ssh")
136 | listener, err := net.Listen("unix", addr)
137 | if err != nil {
138 | return nil, nil, err
139 | }
140 | defer listener.Close()
141 | c1, err := net.Dial("unix", addr)
142 | if err != nil {
143 | return nil, nil, err
144 | }
145 |
146 | c2, err := listener.Accept()
147 | if err != nil {
148 | c1.Close()
149 | return nil, nil, err
150 | }
151 |
152 | return c1.(*net.UnixConn), c2.(*net.UnixConn), nil
153 | }
154 |
155 | func (s *server) TryDial(config *ssh.ClientConfig) (*ssh.Client, error) {
156 | sshd, err := exec.LookPath("sshd")
157 | if err != nil {
158 | s.t.Skipf("skipping test: %v", err)
159 | }
160 |
161 | c1, c2, err := unixConnection()
162 | if err != nil {
163 | s.t.Fatalf("unixConnection: %v", err)
164 | }
165 |
166 | s.cmd = exec.Command(sshd, "-f", s.configfile, "-i", "-e")
167 | f, err := c2.File()
168 | if err != nil {
169 | s.t.Fatalf("UnixConn.File: %v", err)
170 | }
171 | defer f.Close()
172 | s.cmd.Stdin = f
173 | s.cmd.Stdout = f
174 | s.cmd.Stderr = &s.output
175 | if err := s.cmd.Start(); err != nil {
176 | s.t.Fail()
177 | s.Shutdown()
178 | s.t.Fatalf("s.cmd.Start: %v", err)
179 | }
180 | s.clientConn = c1
181 | conn, chans, reqs, err := ssh.NewClientConn(c1, "", config)
182 | if err != nil {
183 | return nil, err
184 | }
185 | return ssh.NewClient(conn, chans, reqs), nil
186 | }
187 |
188 | func (s *server) Dial(config *ssh.ClientConfig) *ssh.Client {
189 | conn, err := s.TryDial(config)
190 | if err != nil {
191 | s.t.Fail()
192 | s.Shutdown()
193 | s.t.Fatalf("ssh.Client: %v", err)
194 | }
195 | return conn
196 | }
197 |
198 | func (s *server) Shutdown() {
199 | if s.cmd != nil && s.cmd.Process != nil {
200 | // Don't check for errors; if it fails it's most
201 | // likely "os: process already finished", and we don't
202 | // care about that. Use os.Interrupt, so child
203 | // processes are killed too.
204 | s.cmd.Process.Signal(os.Interrupt)
205 | s.cmd.Wait()
206 | }
207 | if s.t.Failed() {
208 | // log any output from sshd process
209 | s.t.Logf("sshd: %s", s.output.String())
210 | }
211 | s.cleanup()
212 | }
213 |
214 | func writeFile(path string, contents []byte) {
215 | f, err := os.OpenFile(path, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0600)
216 | if err != nil {
217 | panic(err)
218 | }
219 | defer f.Close()
220 | if _, err := f.Write(contents); err != nil {
221 | panic(err)
222 | }
223 | }
224 |
225 | // newServer returns a new mock ssh server.
226 | func newServer(t *testing.T) *server {
227 | if testing.Short() {
228 | t.Skip("skipping test due to -short")
229 | }
230 | dir, err := ioutil.TempDir("", "sshtest")
231 | if err != nil {
232 | t.Fatal(err)
233 | }
234 | f, err := os.Create(filepath.Join(dir, "sshd_config"))
235 | if err != nil {
236 | t.Fatal(err)
237 | }
238 | err = configTmpl.Execute(f, map[string]string{
239 | "Dir": dir,
240 | })
241 | if err != nil {
242 | t.Fatal(err)
243 | }
244 | f.Close()
245 |
246 | for k, v := range testdata.PEMBytes {
247 | filename := "id_" + k
248 | writeFile(filepath.Join(dir, filename), v)
249 | writeFile(filepath.Join(dir, filename+".pub"), ssh.MarshalAuthorizedKey(testPublicKeys[k]))
250 | }
251 |
252 | return &server{
253 | t: t,
254 | configfile: f.Name(),
255 | cleanup: func() {
256 | if err := os.RemoveAll(dir); err != nil {
257 | t.Error(err)
258 | }
259 | },
260 | }
261 | }
262 |
--------------------------------------------------------------------------------
/Godeps/_workspace/src/golang.org/x/crypto/ssh/test/testdata_test.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014 The Go Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style
3 | // license that can be found in the LICENSE file.
4 |
5 | // IMPLEMENTOR NOTE: To avoid a package loop, this file is in three places:
6 | // ssh/, ssh/agent, and ssh/test/. It should be kept in sync across all three
7 | // instances.
8 |
9 | package test
10 |
11 | import (
12 | "crypto/rand"
13 | "fmt"
14 |
15 | "golang.org/x/crypto/ssh"
16 | "golang.org/x/crypto/ssh/testdata"
17 | )
18 |
19 | var (
20 | testPrivateKeys map[string]interface{}
21 | testSigners map[string]ssh.Signer
22 | testPublicKeys map[string]ssh.PublicKey
23 | )
24 |
25 | func init() {
26 | var err error
27 |
28 | n := len(testdata.PEMBytes)
29 | testPrivateKeys = make(map[string]interface{}, n)
30 | testSigners = make(map[string]ssh.Signer, n)
31 | testPublicKeys = make(map[string]ssh.PublicKey, n)
32 | for t, k := range testdata.PEMBytes {
33 | testPrivateKeys[t], err = ssh.ParseRawPrivateKey(k)
34 | if err != nil {
35 | panic(fmt.Sprintf("Unable to parse test key %s: %v", t, err))
36 | }
37 | testSigners[t], err = ssh.NewSignerFromKey(testPrivateKeys[t])
38 | if err != nil {
39 | panic(fmt.Sprintf("Unable to create signer for test key %s: %v", t, err))
40 | }
41 | testPublicKeys[t] = testSigners[t].PublicKey()
42 | }
43 |
44 | // Create a cert and sign it for use in tests.
45 | testCert := &ssh.Certificate{
46 | Nonce: []byte{}, // To pass reflect.DeepEqual after marshal & parse, this must be non-nil
47 | ValidPrincipals: []string{"gopher1", "gopher2"}, // increases test coverage
48 | ValidAfter: 0, // unix epoch
49 | ValidBefore: ssh.CertTimeInfinity, // The end of currently representable time.
50 | Reserved: []byte{}, // To pass reflect.DeepEqual after marshal & parse, this must be non-nil
51 | Key: testPublicKeys["ecdsa"],
52 | SignatureKey: testPublicKeys["rsa"],
53 | Permissions: ssh.Permissions{
54 | CriticalOptions: map[string]string{},
55 | Extensions: map[string]string{},
56 | },
57 | }
58 | testCert.SignCert(rand.Reader, testSigners["rsa"])
59 | testPrivateKeys["cert"] = testPrivateKeys["ecdsa"]
60 | testSigners["cert"], err = ssh.NewCertSigner(testCert, testSigners["ecdsa"])
61 | if err != nil {
62 | panic(fmt.Sprintf("Unable to create certificate signer: %v", err))
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/Godeps/_workspace/src/golang.org/x/crypto/ssh/testdata/doc.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014 The Go Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style
3 | // license that can be found in the LICENSE file.
4 |
5 | // This package contains test data shared between the various subpackages of
6 | // the code.google.com/p/go.crypto/ssh package. Under no circumstance should
7 | // this data be used for production code.
8 | package testdata // import "golang.org/x/crypto/ssh/testdata"
9 |
--------------------------------------------------------------------------------
/Godeps/_workspace/src/golang.org/x/crypto/ssh/testdata/keys.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014 The Go Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style
3 | // license that can be found in the LICENSE file.
4 |
5 | package testdata
6 |
7 | var PEMBytes = map[string][]byte{
8 | "dsa": []byte(`-----BEGIN DSA PRIVATE KEY-----
9 | MIIBuwIBAAKBgQD6PDSEyXiI9jfNs97WuM46MSDCYlOqWw80ajN16AohtBncs1YB
10 | lHk//dQOvCYOsYaE+gNix2jtoRjwXhDsc25/IqQbU1ahb7mB8/rsaILRGIbA5WH3
11 | EgFtJmXFovDz3if6F6TzvhFpHgJRmLYVR8cqsezL3hEZOvvs2iH7MorkxwIVAJHD
12 | nD82+lxh2fb4PMsIiaXudAsBAoGAQRf7Q/iaPRn43ZquUhd6WwvirqUj+tkIu6eV
13 | 2nZWYmXLlqFQKEy4Tejl7Wkyzr2OSYvbXLzo7TNxLKoWor6ips0phYPPMyXld14r
14 | juhT24CrhOzuLMhDduMDi032wDIZG4Y+K7ElU8Oufn8Sj5Wge8r6ANmmVgmFfynr
15 | FhdYCngCgYEA3ucGJ93/Mx4q4eKRDxcWD3QzWyqpbRVRRV1Vmih9Ha/qC994nJFz
16 | DQIdjxDIT2Rk2AGzMqFEB68Zc3O+Wcsmz5eWWzEwFxaTwOGWTyDqsDRLm3fD+QYj
17 | nOwuxb0Kce+gWI8voWcqC9cyRm09jGzu2Ab3Bhtpg8JJ8L7gS3MRZK4CFEx4UAfY
18 | Fmsr0W6fHB9nhS4/UXM8
19 | -----END DSA PRIVATE KEY-----
20 | `),
21 | "ecdsa": []byte(`-----BEGIN EC PRIVATE KEY-----
22 | MHcCAQEEINGWx0zo6fhJ/0EAfrPzVFyFC9s18lBt3cRoEDhS3ARooAoGCCqGSM49
23 | AwEHoUQDQgAEi9Hdw6KvZcWxfg2IDhA7UkpDtzzt6ZqJXSsFdLd+Kx4S3Sx4cVO+
24 | 6/ZOXRnPmNAlLUqjShUsUBBngG0u2fqEqA==
25 | -----END EC PRIVATE KEY-----
26 | `),
27 | "rsa": []byte(`-----BEGIN RSA PRIVATE KEY-----
28 | MIIBOwIBAAJBALdGZxkXDAjsYk10ihwU6Id2KeILz1TAJuoq4tOgDWxEEGeTrcld
29 | r/ZwVaFzjWzxaf6zQIJbfaSEAhqD5yo72+sCAwEAAQJBAK8PEVU23Wj8mV0QjwcJ
30 | tZ4GcTUYQL7cF4+ezTCE9a1NrGnCP2RuQkHEKxuTVrxXt+6OF15/1/fuXnxKjmJC
31 | nxkCIQDaXvPPBi0c7vAxGwNY9726x01/dNbHCE0CBtcotobxpwIhANbbQbh3JHVW
32 | 2haQh4fAG5mhesZKAGcxTyv4mQ7uMSQdAiAj+4dzMpJWdSzQ+qGHlHMIBvVHLkqB
33 | y2VdEyF7DPCZewIhAI7GOI/6LDIFOvtPo6Bj2nNmyQ1HU6k/LRtNIXi4c9NJAiAr
34 | rrxx26itVhJmcvoUhOjwuzSlP2bE5VHAvkGB352YBg==
35 | -----END RSA PRIVATE KEY-----
36 | `),
37 | "user": []byte(`-----BEGIN EC PRIVATE KEY-----
38 | MHcCAQEEILYCAeq8f7V4vSSypRw7pxy8yz3V5W4qg8kSC3zJhqpQoAoGCCqGSM49
39 | AwEHoUQDQgAEYcO2xNKiRUYOLEHM7VYAp57HNyKbOdYtHD83Z4hzNPVC4tM5mdGD
40 | PLL8IEwvYu2wq+lpXfGQnNMbzYf9gspG0w==
41 | -----END EC PRIVATE KEY-----
42 | `),
43 | }
44 |
--------------------------------------------------------------------------------
/Godeps/_workspace/src/golang.org/x/crypto/ssh/testdata_test.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014 The Go Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style
3 | // license that can be found in the LICENSE file.
4 |
5 | // IMPLEMENTOR NOTE: To avoid a package loop, this file is in three places:
6 | // ssh/, ssh/agent, and ssh/test/. It should be kept in sync across all three
7 | // instances.
8 |
9 | package ssh
10 |
11 | import (
12 | "crypto/rand"
13 | "fmt"
14 |
15 | "golang.org/x/crypto/ssh/testdata"
16 | )
17 |
18 | var (
19 | testPrivateKeys map[string]interface{}
20 | testSigners map[string]Signer
21 | testPublicKeys map[string]PublicKey
22 | )
23 |
24 | func init() {
25 | var err error
26 |
27 | n := len(testdata.PEMBytes)
28 | testPrivateKeys = make(map[string]interface{}, n)
29 | testSigners = make(map[string]Signer, n)
30 | testPublicKeys = make(map[string]PublicKey, n)
31 | for t, k := range testdata.PEMBytes {
32 | testPrivateKeys[t], err = ParseRawPrivateKey(k)
33 | if err != nil {
34 | panic(fmt.Sprintf("Unable to parse test key %s: %v", t, err))
35 | }
36 | testSigners[t], err = NewSignerFromKey(testPrivateKeys[t])
37 | if err != nil {
38 | panic(fmt.Sprintf("Unable to create signer for test key %s: %v", t, err))
39 | }
40 | testPublicKeys[t] = testSigners[t].PublicKey()
41 | }
42 |
43 | // Create a cert and sign it for use in tests.
44 | testCert := &Certificate{
45 | Nonce: []byte{}, // To pass reflect.DeepEqual after marshal & parse, this must be non-nil
46 | ValidPrincipals: []string{"gopher1", "gopher2"}, // increases test coverage
47 | ValidAfter: 0, // unix epoch
48 | ValidBefore: CertTimeInfinity, // The end of currently representable time.
49 | Reserved: []byte{}, // To pass reflect.DeepEqual after marshal & parse, this must be non-nil
50 | Key: testPublicKeys["ecdsa"],
51 | SignatureKey: testPublicKeys["rsa"],
52 | Permissions: Permissions{
53 | CriticalOptions: map[string]string{},
54 | Extensions: map[string]string{},
55 | },
56 | }
57 | testCert.SignCert(rand.Reader, testSigners["rsa"])
58 | testPrivateKeys["cert"] = testPrivateKeys["ecdsa"]
59 | testSigners["cert"], err = NewCertSigner(testCert, testSigners["ecdsa"])
60 | if err != nil {
61 | panic(fmt.Sprintf("Unable to create certificate signer: %v", err))
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/Godeps/_workspace/src/golang.org/x/crypto/ssh/transport_test.go:
--------------------------------------------------------------------------------
1 | // Copyright 2011 The Go Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style
3 | // license that can be found in the LICENSE file.
4 |
5 | package ssh
6 |
7 | import (
8 | "bytes"
9 | "crypto/rand"
10 | "encoding/binary"
11 | "strings"
12 | "testing"
13 | )
14 |
15 | func TestReadVersion(t *testing.T) {
16 | longversion := strings.Repeat("SSH-2.0-bla", 50)[:253]
17 | cases := map[string]string{
18 | "SSH-2.0-bla\r\n": "SSH-2.0-bla",
19 | "SSH-2.0-bla\n": "SSH-2.0-bla",
20 | longversion + "\r\n": longversion,
21 | }
22 |
23 | for in, want := range cases {
24 | result, err := readVersion(bytes.NewBufferString(in))
25 | if err != nil {
26 | t.Errorf("readVersion(%q): %s", in, err)
27 | }
28 | got := string(result)
29 | if got != want {
30 | t.Errorf("got %q, want %q", got, want)
31 | }
32 | }
33 | }
34 |
35 | func TestReadVersionError(t *testing.T) {
36 | longversion := strings.Repeat("SSH-2.0-bla", 50)[:253]
37 | cases := []string{
38 | longversion + "too-long\r\n",
39 | }
40 | for _, in := range cases {
41 | if _, err := readVersion(bytes.NewBufferString(in)); err == nil {
42 | t.Errorf("readVersion(%q) should have failed", in)
43 | }
44 | }
45 | }
46 |
47 | func TestExchangeVersionsBasic(t *testing.T) {
48 | v := "SSH-2.0-bla"
49 | buf := bytes.NewBufferString(v + "\r\n")
50 | them, err := exchangeVersions(buf, []byte("xyz"))
51 | if err != nil {
52 | t.Errorf("exchangeVersions: %v", err)
53 | }
54 |
55 | if want := "SSH-2.0-bla"; string(them) != want {
56 | t.Errorf("got %q want %q for our version", them, want)
57 | }
58 | }
59 |
60 | func TestExchangeVersions(t *testing.T) {
61 | cases := []string{
62 | "not\x000allowed",
63 | "not allowed\n",
64 | }
65 | for _, c := range cases {
66 | buf := bytes.NewBufferString("SSH-2.0-bla\r\n")
67 | if _, err := exchangeVersions(buf, []byte(c)); err == nil {
68 | t.Errorf("exchangeVersions(%q): should have failed", c)
69 | }
70 | }
71 | }
72 |
73 | type closerBuffer struct {
74 | bytes.Buffer
75 | }
76 |
77 | func (b *closerBuffer) Close() error {
78 | return nil
79 | }
80 |
81 | func TestTransportMaxPacketWrite(t *testing.T) {
82 | buf := &closerBuffer{}
83 | tr := newTransport(buf, rand.Reader, true)
84 | huge := make([]byte, maxPacket+1)
85 | err := tr.writePacket(huge)
86 | if err == nil {
87 | t.Errorf("transport accepted write for a huge packet.")
88 | }
89 | }
90 |
91 | func TestTransportMaxPacketReader(t *testing.T) {
92 | var header [5]byte
93 | huge := make([]byte, maxPacket+128)
94 | binary.BigEndian.PutUint32(header[0:], uint32(len(huge)))
95 | // padding.
96 | header[4] = 0
97 |
98 | buf := &closerBuffer{}
99 | buf.Write(header[:])
100 | buf.Write(huge)
101 |
102 | tr := newTransport(buf, rand.Reader, true)
103 | _, err := tr.readPacket()
104 | if err == nil {
105 | t.Errorf("transport succeeded reading huge packet.")
106 | } else if !strings.Contains(err.Error(), "large") {
107 | t.Errorf("got %q, should mention %q", err.Error(), "large")
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Matt Bostock
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # SSH key checker
2 |
3 | A small SSH server written in Go that checks any public keys
4 | presented to it for:
5 |
6 | - [known weak keys][] vulnerable to the [Debian PRNG bug][]
7 | - potentially weak key lengths, e.g. 1024-bit RSA keys
8 | - DSA (ssh-dss) keys, which [OpenSSH no longer supports by default][]
9 |
10 | The results are output back to the user over the SSH session.
11 |
12 | ## Example output
13 |
14 | ```
15 | $ ssh keycheck.mattbostock.com
16 | This server checks your SSH public keys for known or potential
17 | security weaknesses.
18 |
19 | For more information, please see:
20 | https://github.com/mattbostock/sshkeycheck
21 |
22 | The public keys presented by your SSH client are:
23 |
24 | Bits Type Fingerprint Issues
25 | 4096 ssh-rsa ed:9a:d2:5d:7b:c0:e5:cf:b9:bc:5c:6b:ce:3a:db:20 No known issues
26 | 1024 ssh-dss 4a:0d:9b:b7:92:ba:0a:93:2a:2f:27:d7:58:73:74:91 DSA KEY
27 | 384 ecdsa-sha2-nistp384 d8:99:74:7a:0b:d0:e0:be:d0:b1:93:ee:ee:0f:b5:a4 No known issues
28 |
29 | WARNING: You are using DSA (ssh-dss) key(s), which are no longer supported by
30 | default in OpenSSH 7.0 and above.
31 | Consider replacing them with a new RSA or ECDSA key.
32 |
33 | Connection to keycheck.mattbostock.com closed.
34 | ```
35 |
36 | ## Inspiration
37 |
38 | This toy project is heavily inspired by [Filippo Valsorda][]'s [whosthere][] server,
39 | which infers your name from the SSH public keys associated with your GitHub account.
40 |
41 | I wanted to provide an easy way for anyone to check if the SSH key they are using
42 | is reasonably secure, in so far as we can define 'secure' from the key length
43 | and from lists of known weak keys.
44 |
45 | Kudos to [Ben Cox][] for raising awareness of [weak SSH keys on GitHub][].
46 |
47 | ## Disclaimer
48 |
49 | I'm not a cryptographer, nor am I an expert in SSH. Use at your own risk and discretion.
50 |
51 | If you spot any problems, please raise an issue. Pull requests are also welcome.
52 |
53 | [known weak keys]: https://github.com/g0tmi1k/debian-ssh
54 | [Debian PRNG bug]: https://www.debian.org/security/2008/dsa-1571
55 | [Filippo Valsorda]: https://twitter.com/FiloSottile
56 | [whosthere]: https://github.com/FiloSottile/whosthere
57 | [Ben Cox]: https://twitter.com/Benjojo12
58 | [weak SSH keys on GitHub]: https://blog.benjojo.co.uk/post/auditing-github-users-keys
59 | [OpenSSH no longer supports by default]: http://www.openssh.com/txt/release-7.0
60 |
--------------------------------------------------------------------------------
/blacklist.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "bufio"
5 | "io/ioutil"
6 | "log"
7 | "os"
8 | "path/filepath"
9 | "strings"
10 |
11 | "golang.org/x/crypto/ssh"
12 | )
13 |
14 | const blacklistPath = "blacklist"
15 |
16 | var blacklist = make(map[string]bool)
17 |
18 | func loadBlacklistedKeys() {
19 | files, err := ioutil.ReadDir(blacklistPath)
20 | if err != nil {
21 | log.Fatal(err)
22 | }
23 |
24 | for _, f := range files {
25 | if f.IsDir() {
26 | log.Fatalf("Subdirectories not supported in %q directory\n", blacklistPath)
27 | }
28 |
29 | file, err := os.Open(filepath.Join(blacklistPath, f.Name()))
30 | if err != nil {
31 | log.Fatal(err)
32 | }
33 | defer file.Close()
34 |
35 | scanner := bufio.NewScanner(file)
36 | for scanner.Scan() {
37 | key := strings.TrimSpace(scanner.Text())
38 | blacklist[key] = true
39 | }
40 |
41 | if err := scanner.Err(); err != nil {
42 | log.Fatal(err)
43 | }
44 | }
45 |
46 | return
47 | }
48 |
49 | func markBlacklistedKeys(keys []*publicKey) {
50 |
51 | for _, k := range keys {
52 | key := strings.TrimSpace(string(ssh.MarshalAuthorizedKey(k.key)))
53 | if blacklist[key] {
54 | k.blacklisted = true
55 | }
56 | }
57 |
58 | return
59 | }
60 |
--------------------------------------------------------------------------------
/key.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "crypto/ecdsa"
5 | "crypto/elliptic"
6 | "crypto/md5"
7 | "errors"
8 | "fmt"
9 | "math/big"
10 | "strings"
11 |
12 | "golang.org/x/crypto/ssh"
13 | )
14 |
15 | type publicKey struct {
16 | key ssh.PublicKey
17 | blacklisted bool
18 | }
19 |
20 | func (p *publicKey) BitLen() (int, error) {
21 | var (
22 | length int
23 | err error
24 | )
25 |
26 | switch p.key.Type() {
27 | case ssh.KeyAlgoRSA:
28 | length, err = rsaKeyLength(p.key)
29 | case ssh.KeyAlgoDSA:
30 | length, err = dsaKeyLength(p.key)
31 | case ssh.KeyAlgoECDSA256, ssh.KeyAlgoECDSA384, ssh.KeyAlgoECDSA521:
32 | length, err = ecdsaKeyLength(p.key)
33 | default:
34 | err = errors.New("Key type not supported: " + p.key.Type())
35 | }
36 |
37 | return length, err
38 | }
39 |
40 | func (p *publicKey) Fingerprint() string {
41 | return md5HexString(md5.Sum(p.key.Marshal()))
42 | }
43 |
44 | func rsaKeyLength(key ssh.PublicKey) (int, error) {
45 | var w struct {
46 | Name string
47 | E *big.Int
48 | N *big.Int
49 | Rest []byte `ssh:"rest"`
50 | }
51 |
52 | err := ssh.Unmarshal(key.Marshal(), &w)
53 | if err != nil {
54 | return 0, err
55 | }
56 |
57 | return w.N.BitLen(), nil
58 | }
59 |
60 | func dsaKeyLength(key ssh.PublicKey) (int, error) {
61 | var w struct {
62 | Name string
63 | P, Q, G, Y *big.Int
64 | Rest []byte `ssh:"rest"`
65 | }
66 | err := ssh.Unmarshal(key.Marshal(), &w)
67 | if err != nil {
68 | return 0, err
69 | }
70 |
71 | return w.P.BitLen(), nil
72 | }
73 |
74 | func ecdsaKeyLength(key ssh.PublicKey) (int, error) {
75 | var w struct {
76 | Name string
77 | Curve string
78 | KeyBytes []byte
79 | Rest []byte `ssh:"rest"`
80 | }
81 |
82 | err := ssh.Unmarshal(key.Marshal(), &w)
83 | if err != nil {
84 | return 0, err
85 | }
86 |
87 | k := new(ecdsa.PublicKey)
88 | switch w.Curve {
89 | case "nistp256":
90 | k.Curve = elliptic.P256()
91 | case "nistp384":
92 | k.Curve = elliptic.P384()
93 | case "nistp521":
94 | k.Curve = elliptic.P521()
95 | default:
96 | return 0, fmt.Errorf("ECSDA curve not supported: %q", w.Curve)
97 | }
98 |
99 | k.X, k.Y = elliptic.Unmarshal(k.Curve, w.KeyBytes)
100 | if k.X == nil || k.Y == nil {
101 | return 0, fmt.Errorf("ECDSA X or Y points were nil: %q, %q", k.X, k.Y)
102 | }
103 |
104 | return k.Params().BitSize, nil
105 | }
106 |
107 | // md5HexString returns a formatted string representing the given md5 sum in hex
108 | func md5HexString(md5 [16]byte) (s string) {
109 | s = fmt.Sprintf("% x", md5)
110 | s = strings.Replace(s, " ", ":", -1)
111 | return s
112 | }
113 |
--------------------------------------------------------------------------------
/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "net"
5 | "os"
6 |
7 | log "github.com/Sirupsen/logrus"
8 | "golang.org/x/crypto/ssh"
9 | )
10 |
11 | func main() {
12 | log.SetOutput(os.Stderr)
13 |
14 | config := &ssh.ServerConfig{
15 | KeyboardInteractiveCallback: keyboardInteractiveCallback,
16 | PublicKeyCallback: publicKeyCallback,
17 | }
18 |
19 | loadBlacklistedKeys()
20 |
21 | private, err := ssh.ParsePrivateKey([]byte(os.Getenv("HOST_PRIVATE_KEY")))
22 | if err != nil {
23 | log.Fatalln("Failed to parse host private key")
24 | }
25 | config.AddHostKey(private)
26 |
27 | addr := os.Getenv("ADDR")
28 | if addr == "" {
29 | addr = "localhost:2022"
30 | }
31 |
32 | listener, err := net.Listen("tcp", addr)
33 | if err != nil {
34 | log.Fatalf("Failed to listen for connection on %s, perhaps that port is already in use", addr)
35 | }
36 |
37 | log.Infoln("Listening on", addr)
38 |
39 | for {
40 | conn, err := listener.Accept()
41 | if err != nil {
42 | log.Warnln("Accept failed:", err)
43 | continue
44 | }
45 |
46 | go serve(config, conn)
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/server.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "bytes"
5 | "errors"
6 | "fmt"
7 | "net"
8 | "strings"
9 | "sync"
10 | "text/tabwriter"
11 | "time"
12 |
13 | log "github.com/Sirupsen/logrus"
14 |
15 | "golang.org/x/crypto/ssh"
16 | )
17 |
18 | var sessions = struct {
19 | mu sync.RWMutex
20 | keys map[string][]*publicKey
21 | }{
22 | keys: make(map[string][]*publicKey),
23 | }
24 |
25 | func serve(config *ssh.ServerConfig, nConn net.Conn) {
26 | // Before use, a handshake must be performed on the incoming net.Conn
27 | conn, chans, reqs, err := ssh.NewServerConn(nConn, config)
28 | if err != nil {
29 | log.Warnln("Failed to handshake:", err)
30 | return
31 | }
32 |
33 | defer func() {
34 | sessions.mu.Lock()
35 | delete(sessions.keys, string(conn.SessionID()))
36 | sessions.mu.Unlock()
37 | conn.Close()
38 | }()
39 |
40 | // The incoming Request channel must be serviced
41 | go ssh.DiscardRequests(reqs)
42 |
43 | sessions.mu.RLock()
44 | keys := sessions.keys[string(conn.SessionID())]
45 | sessions.mu.RUnlock()
46 |
47 | // Service the incoming Channel channel
48 | for n := range chans {
49 | // Channels have a type, depending on the application level
50 | // protocol intended. In the case of a shell, the type is
51 | // "session" and ServerShell may be used to present a simple
52 | // terminal interface.
53 | if n.ChannelType() != "session" {
54 | n.Reject(ssh.UnknownChannelType, "unknown channel type")
55 | continue
56 | }
57 |
58 | channel, requests, err := n.Accept()
59 | if err != nil {
60 | log.Warnln("Could not accept channel:", err)
61 | continue
62 | }
63 |
64 | agentFwd, x11 := false, false
65 | reqLock := &sync.Mutex{}
66 | reqLock.Lock()
67 | timeout := time.AfterFunc(30*time.Second, func() { reqLock.Unlock() })
68 |
69 | go func(in <-chan *ssh.Request) {
70 | for req := range in {
71 | ok := false
72 | switch req.Type {
73 | case "shell":
74 | fallthrough
75 | case "pty-req":
76 | ok = true
77 |
78 | // "auth-agent-req@openssh.com" and "x11-req" always arrive
79 | // before the "pty-req", so we can go ahead now
80 | if timeout.Stop() {
81 | reqLock.Unlock()
82 | }
83 |
84 | case "auth-agent-req@openssh.com":
85 | agentFwd = true
86 | case "x11-req":
87 | x11 = true
88 | }
89 |
90 | if req.WantReply {
91 | req.Reply(ok, nil)
92 | }
93 | }
94 | }(requests)
95 |
96 | markBlacklistedKeys(keys)
97 |
98 | channel.Write([]byte(welcomeMsg))
99 |
100 | var table bytes.Buffer
101 | tabWriter := new(tabwriter.Writer)
102 | tabWriter.Init(&table, 5, 2, 2, ' ', 0)
103 | // Note that using tabwriter, columns are tab-terminated,
104 | // not tab-delimited
105 | fmt.Fprint(tabWriter, "Bits\tType\tFingerprint\tIssues\n")
106 |
107 | var issues string
108 | var blacklisted, weak, dsa bool
109 | for _, k := range keys {
110 | issues = "No known issues"
111 | length, err := k.BitLen()
112 |
113 | if err != nil {
114 | log.Errorf("Failed to determine key length for %s key: %s", k.key.Type(), err)
115 | }
116 |
117 | if k.key.Type() == ssh.KeyAlgoDSA {
118 | issues = "DSA KEY"
119 | dsa = true
120 | }
121 |
122 | if length < 2048 && k.key.Type() == ssh.KeyAlgoRSA {
123 | issues = "WEAK KEY LENGTH"
124 | weak = true
125 | }
126 |
127 | if k.blacklisted {
128 | // being blacklisted takes priority of any key length weaknesses
129 | issues = "BLACKLISTED"
130 | blacklisted = true
131 | }
132 |
133 | fmt.Fprintf(tabWriter, "%d\t%s\t%s\t%s\t\n", length, k.key.Type(), k.Fingerprint(), issues)
134 | }
135 |
136 | err = tabWriter.Flush()
137 | if err != nil {
138 | log.Errorln("Error when flushing tab writer:", err)
139 | }
140 | channel.Write([]byte(
141 | strings.Replace(table.String(), "\n", "\n\r", -1) +
142 | "\n\r"))
143 |
144 | if blacklisted {
145 | channel.Write([]byte(blacklistMsg))
146 | }
147 |
148 | if dsa {
149 | channel.Write([]byte(dsaMsg))
150 | }
151 |
152 | if weak {
153 | channel.Write([]byte(weakMsg))
154 | }
155 |
156 | reqLock.Lock()
157 | if agentFwd {
158 | channel.Write([]byte(agentMsg))
159 | }
160 | if x11 {
161 | channel.Write([]byte(x11Msg))
162 | }
163 |
164 | // Explicitly close the channel to end the session
165 | channel.Close()
166 | }
167 |
168 | }
169 |
170 | func publicKeyCallback(conn ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error) {
171 | sessions.mu.Lock()
172 | sessionID := string(conn.SessionID())
173 | sessions.keys[sessionID] = append(sessions.keys[sessionID], &publicKey{key: key})
174 | sessions.mu.Unlock()
175 |
176 | // Never succeed a key, or we might not see the next. See KeyboardInteractiveCallback.
177 | return nil, errors.New("")
178 | }
179 |
180 | func keyboardInteractiveCallback(ssh.ConnMetadata, ssh.KeyboardInteractiveChallenge) (*ssh.Permissions, error) {
181 | // keyboard-interactive is tried when all public keys failed, and
182 | // since it's server-driven we can just pass without user
183 | // interaction to let the user in once we got all the public keys
184 | return nil, nil
185 | }
186 |
187 | var (
188 | agentMsg = strings.Replace(`CRITICAL: SSH agent forwarding is enabled; it is dangerous to enable agent forwarding
189 | for servers you do not trust as it allows them to log in to other servers as you.
190 |
191 | `, "\n", "\n\r", -1)
192 |
193 | blacklistMsg = strings.Replace(`CRITICAL: You are using blacklisted key(s) that are known to be insecure.
194 | You should replace them immediately.
195 | See: https://www.debian.org/security/2008/dsa-1576
196 |
197 | `, "\n", "\n\r", -1)
198 |
199 | dsaMsg = strings.Replace(`WARNING: You are using DSA (ssh-dss) key(s), which are no longer supported by
200 | default in OpenSSH version 7.0 and above.
201 | Consider replacing them with a new RSA or ECDSA key.
202 |
203 | `, "\n", "\n\r", -1)
204 |
205 | weakMsg = strings.Replace(`WARNING: You are using RSA key(s) with a length of less than 2048 bits.
206 | Consider replacing them with a new key of 2048 bits or more.
207 |
208 | `, "\n", "\n\r", -1)
209 |
210 | welcomeMsg = strings.Replace(`This server checks your SSH public keys for known or potential
211 | security weaknesses.
212 |
213 | For more information, please see:
214 | https://github.com/mattbostock/sshkeycheck
215 |
216 | The public keys presented by your SSH client are:
217 |
218 | `, "\n", "\n\r", -1)
219 |
220 | x11Msg = strings.Replace(`CRITICAL: X11 forwarding is enabled; it is dangerous to allow X11 forwarding
221 | for servers you do not trust as it allows them to access your desktop.
222 |
223 | `, "\n", "\n\r", -1)
224 | )
225 |
--------------------------------------------------------------------------------