Skip to content

Commit 8e506f7

Browse files
authored
Merge pull request #25 from jaksi/update
Update
2 parents 7ef7bd5 + 113f03b commit 8e506f7

File tree

9 files changed

+133
-84
lines changed

9 files changed

+133
-84
lines changed

.github/workflows/pr-check.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ jobs:
99
runs-on: ubuntu-latest
1010
steps:
1111
- uses: actions/checkout@v3
12-
- uses: golangci/golangci-lint-action@v3
12+
- uses: golangci/golangci-lint-action@v6
1313
test:
1414
name: Test
1515
strategy:
@@ -21,7 +21,7 @@ jobs:
2121
runs-on: ${{ matrix.os }}
2222
steps:
2323
- uses: actions/checkout@v3
24-
- uses: actions/setup-go@v3
24+
- uses: actions/setup-go@v5
2525
with:
26-
go-version: ^1.19
26+
go-version: ^1.22
2727
- run: go test -race -timeout 1m

conn.go

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,36 @@ package sshutils
22

33
import (
44
"encoding/hex"
5-
"errors"
65
"fmt"
76
"net"
7+
"strconv"
88

99
"golang.org/x/crypto/ssh"
1010
)
1111

12-
var (
13-
ErrEstablishSSH = errors.New("failed to establish SSH connection")
14-
ErrSendRequest = errors.New("failed to send request")
15-
ErrChannelOpen = errors.New("failed to open channel")
16-
)
12+
type EstablishError struct {
13+
err error
14+
}
15+
16+
func (e EstablishError) Error() string {
17+
return fmt.Sprintf("failed to establish SSH connection: %v", e.err)
18+
}
19+
20+
type SendRequestError struct {
21+
err error
22+
}
23+
24+
func (e SendRequestError) Error() string {
25+
return fmt.Sprintf("failed to send request: %v", e.err)
26+
}
27+
28+
type ChannelOpenError struct {
29+
err error
30+
}
31+
32+
func (e ChannelOpenError) Error() string {
33+
return fmt.Sprintf("failed to open channel: %v", e.err)
34+
}
1735

1836
type Listener struct {
1937
net.Listener
@@ -28,7 +46,7 @@ func (listener *Listener) Accept() (*Conn, error) {
2846
sshConn, sshNewChannels, sshRequests, err := ssh.NewServerConn(conn, &listener.config)
2947
if err != nil {
3048
conn.Close()
31-
return nil, fmt.Errorf("%w: %v", ErrEstablishSSH, err)
49+
return nil, EstablishError{err}
3250
}
3351
return handleConn(sshConn, sshNewChannels, sshRequests), nil
3452
}
@@ -51,7 +69,7 @@ type Conn struct {
5169
func (conn *Conn) RawChannel(name string, payload []byte) (*Channel, error) {
5270
sshChannel, sshRequests, err := conn.Conn.OpenChannel(name, payload)
5371
if err != nil {
54-
return nil, fmt.Errorf("%w: %v", ErrChannelOpen, err)
72+
return nil, ChannelOpenError{err}
5573
}
5674
return handleChannel(sshChannel, sshRequests, conn, name), nil
5775
}
@@ -67,7 +85,7 @@ func (conn *Conn) Channel(name string, payload Payload) (*Channel, error) {
6785
func (conn *Conn) RawRequest(name string, wantReply bool, payload []byte) (bool, []byte, error) {
6886
accepted, reply, err := conn.SendRequest(name, wantReply, payload)
6987
if err != nil {
70-
return false, nil, fmt.Errorf("%w: %v", ErrSendRequest, err)
88+
return false, nil, SendRequestError{err}
7189
}
7290
return accepted, reply, nil
7391
}
@@ -92,7 +110,7 @@ func Dial(address string, config *ssh.ClientConfig) (*Conn, error) {
92110
sshConn, sshNewChannels, sshRequests, err := ssh.NewClientConn(conn, address, config)
93111
if err != nil {
94112
conn.Close()
95-
return nil, fmt.Errorf("%w: %v", ErrEstablishSSH, err)
113+
return nil, EstablishError{err}
96114
}
97115
return handleConn(sshConn, sshNewChannels, sshRequests), nil
98116
}
@@ -137,7 +155,7 @@ type NewChannel struct {
137155
func (newChannel *NewChannel) AcceptChannel() (*Channel, error) {
138156
sshChannel, sshRequests, err := newChannel.Accept()
139157
if err != nil {
140-
return nil, fmt.Errorf("%w: %v", ErrChannelOpen, err)
158+
return nil, ChannelOpenError{err}
141159
}
142160
return handleChannel(sshChannel, sshRequests, newChannel.conn, newChannel.ChannelType()), nil
143161
}
@@ -177,7 +195,7 @@ func (channel *Channel) ConnMetadata() ssh.ConnMetadata {
177195
func (channel *Channel) RawRequest(name string, wantReply bool, payload []byte) (bool, error) {
178196
accepted, err := channel.SendRequest(name, wantReply, payload)
179197
if err != nil {
180-
return false, fmt.Errorf("%w: %v", ErrSendRequest, err)
198+
return false, SendRequestError{err}
181199
}
182200
return accepted, nil
183201
}
@@ -196,7 +214,7 @@ func (channel *Channel) String() string {
196214

197215
func handleChannel(sshChannel ssh.Channel, sshRequests <-chan *ssh.Request, conn *Conn, name string) *Channel {
198216
requests := make(chan *ChannelRequest)
199-
channel := &Channel{sshChannel, requests, fmt.Sprint(conn.nextChannelID), name, conn}
217+
channel := &Channel{sshChannel, requests, strconv.FormatInt(int64(conn.nextChannelID), 10), name, conn}
200218
go func() {
201219
for request := range sshRequests {
202220
requests <- &ChannelRequest{request, channel}

conn_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"sync"
77
"testing"
88

9+
//nolint:depguard
910
"github.com/jaksi/sshutils"
1011
"golang.org/x/crypto/ssh"
1112
)

go.mod

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
module github.com/jaksi/sshutils
22

3-
go 1.19
3+
go 1.22
44

5-
require golang.org/x/crypto v0.5.0
5+
require golang.org/x/crypto v0.25.0
66

7-
require golang.org/x/sys v0.4.0 // indirect
7+
require golang.org/x/sys v0.22.0 // indirect

go.sum

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
golang.org/x/crypto v0.5.0 h1:U/0M97KRkSFvyD/3FSmdP5W5swImpNgle/EHFhOsQPE=
2-
golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU=
3-
golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18=
4-
golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
5-
golang.org/x/term v0.4.0 h1:O7UWfv5+A2qiuulQk30kVinPoMtoIPeVaKLEgLpVkvg=
1+
golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30=
2+
golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M=
3+
golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
4+
golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
5+
golang.org/x/term v0.22.0 h1:BbsgPEJULsl2fV/AT3v15Mjva5yXKQDyKf+TbDz7QJk=
6+
golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4=

host_keys.go

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import (
77
"crypto/rsa"
88
"crypto/x509"
99
"encoding/pem"
10-
"errors"
1110
"fmt"
1211
"io"
1312
"os"
@@ -20,11 +19,29 @@ const (
2019
hostKeyFilePerms = 0o600
2120
)
2221

23-
var (
24-
ErrInvalidKey = errors.New("invalid key")
25-
ErrInvalidKeyFile = errors.New("invalid key file")
26-
ErrUnsupportedKeyType = errors.New("unsupported key type")
27-
)
22+
type InvalidKeyError struct {
23+
err error
24+
}
25+
26+
func (e InvalidKeyError) Error() string {
27+
return fmt.Sprintf("invalid key: %v", e.err)
28+
}
29+
30+
type InvalidKeyFileError struct {
31+
err error
32+
}
33+
34+
func (e InvalidKeyFileError) Error() string {
35+
return fmt.Sprintf("invalid key file: %v", e.err)
36+
}
37+
38+
type UnsupportedKeyTypeError struct {
39+
t KeyType
40+
}
41+
42+
func (e UnsupportedKeyTypeError) Error() string {
43+
return fmt.Sprintf("unsupported key type: %v", e.t)
44+
}
2845

2946
type KeyType int
3047

@@ -59,7 +76,7 @@ func (key *HostKey) String() string {
5976
func hostKeyFromKey(key interface{}) (*HostKey, error) {
6077
signer, err := ssh.NewSignerFromKey(key)
6178
if err != nil {
62-
return nil, fmt.Errorf("%w: %v", ErrInvalidKey, err)
79+
return nil, InvalidKeyError{err}
6380
}
6481
return &HostKey{
6582
Signer: signer,
@@ -78,42 +95,42 @@ func GenerateHostKey(rand io.Reader, t KeyType) (*HostKey, error) {
7895
case Ed25519:
7996
_, key, err = ed25519.GenerateKey(rand)
8097
default:
81-
return nil, fmt.Errorf("%w: %v", ErrUnsupportedKeyType, t)
98+
return nil, UnsupportedKeyTypeError{t}
8299
}
83100
if err != nil {
84-
return nil, fmt.Errorf("%w: %v", ErrInvalidKey, err)
101+
return nil, InvalidKeyError{err}
85102
}
86103
return hostKeyFromKey(key)
87104
}
88105

89106
func LoadHostKey(fileName string) (*HostKey, error) {
90107
keyBytes, err := os.ReadFile(fileName)
91108
if err != nil {
92-
return nil, fmt.Errorf("%w: %v", ErrInvalidKeyFile, err)
109+
return nil, InvalidKeyFileError{err}
93110
}
94111
key, err := ssh.ParseRawPrivateKey(keyBytes)
95112
if err != nil {
96-
return nil, fmt.Errorf("%w: %v", ErrInvalidKeyFile, err)
113+
return nil, InvalidKeyFileError{err}
97114
}
98115
return hostKeyFromKey(key)
99116
}
100117

101118
func (key *HostKey) Save(fileName string) error {
102119
file, err := os.OpenFile(fileName, os.O_WRONLY|os.O_CREATE|os.O_EXCL, hostKeyFilePerms) //nolint:nosnakecase
103120
if err != nil {
104-
return fmt.Errorf("%w: %v", ErrInvalidKeyFile, err)
121+
return InvalidKeyFileError{err}
105122
}
106123
defer file.Close()
107124
keyBytes, err := x509.MarshalPKCS8PrivateKey(key.key)
108125
if err != nil {
109-
return fmt.Errorf("%w: %v", ErrInvalidKey, err)
126+
return InvalidKeyError{err}
110127
}
111128
if _, err = file.Write(pem.EncodeToMemory(&pem.Block{
112129
Type: "PRIVATE KEY",
113130
Headers: nil,
114131
Bytes: keyBytes,
115132
})); err != nil {
116-
return fmt.Errorf("%w: %v", ErrInvalidKeyFile, err)
133+
return InvalidKeyFileError{err}
117134
}
118135
return nil
119136
}

host_keys_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"strings"
99
"testing"
1010

11+
//nolint:depguard
1112
"github.com/jaksi/sshutils"
1213
"golang.org/x/crypto/ssh"
1314
)
@@ -50,7 +51,6 @@ func TestGenerateHostKey(t *testing.T) {
5051
"unsupported key type: unknown type (42)",
5152
},
5253
} {
53-
tt := tt
5454
t.Run(tt.name, func(t *testing.T) {
5555
t.Parallel()
5656
if tt.keyType.String() != tt.keyTypeString {

0 commit comments

Comments
 (0)