Skip to content

Commit c6b2e6e

Browse files
committed
Support of --publickey-auth-script (#2)
1 parent b6084ac commit c6b2e6e

File tree

5 files changed

+65
-18
lines changed

5 files changed

+65
-18
lines changed

auth.go

+41-10
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ package ssh2docker
33
import (
44
"encoding/json"
55
"fmt"
6+
"os"
67
"os/exec"
8+
"strings"
79

810
"github.com/moul/ssh2docker/vendor/github.com/Sirupsen/logrus"
911
"github.com/moul/ssh2docker/vendor/golang.org/x/crypto/ssh"
@@ -37,7 +39,7 @@ func (s *Server) CheckConfig(config *ClientConfig) error {
3739
func (s *Server) PublicKeyCallback(conn ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error) {
3840
username := conn.User()
3941
clientID := conn.RemoteAddr().String()
40-
keyText := string(ssh.MarshalAuthorizedKey(key))
42+
keyText := strings.TrimSpace(string(ssh.MarshalAuthorizedKey(key)))
4143
logrus.Debugf("PublicKeyCallback: %q %q", username, keyText)
4244
// sessionID := conn.SessionID()
4345

@@ -63,17 +65,44 @@ func (s *Server) KeyboardInteractiveCallback(conn ssh.ConnMetadata, challenge ss
6365

6466
config := s.ClientConfigs[clientID]
6567
if config == nil {
66-
config := &ClientConfig{
68+
s.ClientConfigs[clientID] = &ClientConfig{
6769
RemoteUser: username,
6870
ImageName: username,
71+
Keys: []string{},
6972
Env: make(Environment, 0),
7073
}
71-
s.ClientConfigs[clientID] = config
7274
}
75+
config = s.ClientConfigs[clientID]
7376

74-
if len(config.Keys) > 0 {
75-
logrus.Debugf("%d keys received, trying to authenticate")
76-
// FIXME: authenticate here
77+
if len(config.Keys) == 0 {
78+
logrus.Warnf("No user keys, continuing with password authentication")
79+
return nil, s.CheckConfig(config)
80+
}
81+
82+
if s.PublicKeyAuthScript != "" {
83+
logrus.Debugf("%d keys received, trying to authenticate using hook script", len(config.Keys))
84+
script, err := expandUser(s.PublicKeyAuthScript)
85+
if err != nil {
86+
logrus.Warnf("Failed to expandUser: %v", err)
87+
return nil, err
88+
}
89+
args := append([]string{username}, config.Keys...)
90+
cmd := exec.Command(script, args...)
91+
// FIXME: redirect stderr to logrus
92+
cmd.Stderr = os.Stderr
93+
output, err := cmd.Output()
94+
if err != nil {
95+
logrus.Warnf("Failed to execute publickey-auth-script: %v", err)
96+
return nil, err
97+
}
98+
99+
err = json.Unmarshal(output, &config)
100+
if err != nil {
101+
logrus.Warnf("Failed to unmarshal json %q: %v", string(output), err)
102+
return nil, err
103+
}
104+
} else {
105+
logrus.Debugf("%d keys received, but no hook script, continuing", len(config.Keys))
77106
}
78107

79108
return nil, s.CheckConfig(config)
@@ -88,24 +117,26 @@ func (s *Server) PasswordCallback(conn ssh.ConnMetadata, password []byte) (*ssh.
88117

89118
config := s.ClientConfigs[clientID]
90119
if config == nil {
91-
config := &ClientConfig{
120+
s.ClientConfigs[clientID] = &ClientConfig{
92121
//Allowed: true,
93122
RemoteUser: username,
94123
ImageName: username,
124+
Keys: []string{},
95125
Env: make(Environment, 0),
96126
}
97-
s.ClientConfigs[clientID] = config
98127
}
128+
config = s.ClientConfigs[clientID]
99129

100130
if s.PasswordAuthScript != "" {
101-
// Using a hook script
102131
script, err := expandUser(s.PasswordAuthScript)
103132
if err != nil {
104133
logrus.Warnf("Failed to expandUser: %v", err)
105134
return nil, err
106135
}
107136
cmd := exec.Command(script, username, string(password))
108-
output, err := cmd.CombinedOutput()
137+
// FIXME: redirect stderr to logrus
138+
cmd.Stderr = os.Stderr
139+
output, err := cmd.Output()
109140
if err != nil {
110141
logrus.Warnf("Failed to execute password-auth-script: %v", err)
111142
return nil, err

cmd/ssh2docker/main.go

+5
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,10 @@ func main() {
9797
Name: "password-auth-script",
9898
Usage: "Password auth hook file",
9999
},
100+
cli.StringFlag{
101+
Name: "publickey-auth-script",
102+
Usage: "Public-key auth hook file",
103+
},
100104
cli.StringFlag{
101105
Name: "local-user",
102106
Usage: "If setted, you can spawn a local shell (not withing docker) by SSHing to this user",
@@ -141,6 +145,7 @@ func Action(c *cli.Context) {
141145
server.NoJoin = c.Bool("no-join")
142146
server.CleanOnStartup = c.Bool("clean-on-startup")
143147
server.PasswordAuthScript = c.String("password-auth-script")
148+
server.PublicKeyAuthScript = c.String("publickey-auth-script")
144149
server.LocalUser = c.String("local-user")
145150
server.Banner = c.String("banner")
146151

examples/password-auth-script

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#!/bin/sh
2+
3+
echo "password-auth-script: $@" >&2
4+
5+
echo '{"allowed":true}'

examples/publickey-auth-script

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#!/bin/sh
2+
3+
echo "password-auth-script: $@" >&2
4+
5+
echo '{"allowed":true}'

server.go

+9-8
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,15 @@ type Server struct {
1313
// Clients map[string]Client
1414
ClientConfigs map[string]*ClientConfig
1515

16-
AllowedImages []string
17-
DefaultShell string
18-
DockerRunArgs []string
19-
NoJoin bool
20-
CleanOnStartup bool
21-
PasswordAuthScript string
22-
LocalUser string
23-
Banner string
16+
AllowedImages []string
17+
DefaultShell string
18+
DockerRunArgs []string
19+
NoJoin bool
20+
CleanOnStartup bool
21+
PasswordAuthScript string
22+
PublicKeyAuthScript string
23+
LocalUser string
24+
Banner string
2425

2526
initialized bool
2627
}

0 commit comments

Comments
 (0)