This breaks the dependency of libplugin on x/crypto, enabling people to use libplugin without having conflicts over the crypto module.
178 lines
3.7 KiB
Go
178 lines
3.7 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"path"
|
|
"path/filepath"
|
|
|
|
log "github.com/sirupsen/logrus"
|
|
"github.com/tg123/sshpiper/libplugin"
|
|
"github.com/tg123/sshpiper/libplugin/skel"
|
|
)
|
|
|
|
type workdingdirFactory struct {
|
|
root string
|
|
allowBadUsername bool
|
|
noPasswordAuth bool
|
|
noCheckPerm bool
|
|
strictHostKey bool
|
|
recursiveSearch bool
|
|
}
|
|
|
|
type skelpipeWrapper struct {
|
|
dir *workingdir
|
|
|
|
host string
|
|
username string
|
|
}
|
|
|
|
type skelpipeFromWrapper struct {
|
|
skelpipeWrapper
|
|
}
|
|
|
|
type skelpipePasswordWrapper struct {
|
|
skelpipeFromWrapper
|
|
}
|
|
|
|
type skelpipePublicKeyWrapper struct {
|
|
skelpipeFromWrapper
|
|
}
|
|
|
|
type skelpipeToWrapper struct {
|
|
skelpipeWrapper
|
|
}
|
|
|
|
type skelpipeToPasswordWrapper struct {
|
|
skelpipeToWrapper
|
|
}
|
|
|
|
type skelpipeToPrivateKeyWrapper struct {
|
|
skelpipeToWrapper
|
|
}
|
|
|
|
func (s *skelpipeWrapper) From() []skel.SkelPipeFrom {
|
|
w := skelpipeFromWrapper{
|
|
skelpipeWrapper: *s,
|
|
}
|
|
|
|
if s.dir.Exists(userAuthorizedKeysFile) && s.dir.Exists(userKeyFile) {
|
|
return []skel.SkelPipeFrom{&skelpipePublicKeyWrapper{
|
|
skelpipeFromWrapper: w,
|
|
}}
|
|
} else {
|
|
return []skel.SkelPipeFrom{&skelpipePasswordWrapper{
|
|
skelpipeFromWrapper: w,
|
|
}}
|
|
}
|
|
}
|
|
|
|
func (s *skelpipeToWrapper) User(conn libplugin.ConnMetadata) string {
|
|
return s.username
|
|
}
|
|
|
|
func (s *skelpipeToWrapper) Host(conn libplugin.ConnMetadata) string {
|
|
return s.host
|
|
}
|
|
|
|
func (s *skelpipeToWrapper) IgnoreHostKey(conn libplugin.ConnMetadata) bool {
|
|
return !s.dir.Strict
|
|
}
|
|
|
|
func (s *skelpipeToWrapper) KnownHosts(conn libplugin.ConnMetadata) ([]byte, error) {
|
|
return s.dir.Readfile(userKnownHosts)
|
|
}
|
|
|
|
func (s *skelpipeFromWrapper) MatchConn(conn libplugin.ConnMetadata) (skel.SkelPipeTo, error) {
|
|
if s.dir.Exists(userKeyFile) {
|
|
return &skelpipeToPrivateKeyWrapper{
|
|
skelpipeToWrapper: skelpipeToWrapper(*s),
|
|
}, nil
|
|
}
|
|
|
|
return &skelpipeToPasswordWrapper{
|
|
skelpipeToWrapper: skelpipeToWrapper(*s),
|
|
}, nil
|
|
}
|
|
|
|
func (s *skelpipePasswordWrapper) TestPassword(conn libplugin.ConnMetadata, password []byte) (bool, error) {
|
|
return true, nil // TODO support later
|
|
}
|
|
|
|
func (s *skelpipePublicKeyWrapper) AuthorizedKeys(conn libplugin.ConnMetadata) ([]byte, error) {
|
|
return s.dir.Readfile(userAuthorizedKeysFile)
|
|
}
|
|
|
|
func (s *skelpipePublicKeyWrapper) TrustedUserCAKeys(conn libplugin.ConnMetadata) ([]byte, error) {
|
|
return nil, nil // TODO support this
|
|
}
|
|
|
|
func (s *skelpipeToPrivateKeyWrapper) PrivateKey(conn libplugin.ConnMetadata) ([]byte, []byte, error) {
|
|
k, err := s.dir.Readfile(userKeyFile)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
|
|
return k, nil, nil
|
|
}
|
|
|
|
func (s *skelpipeToPasswordWrapper) OverridePassword(conn libplugin.ConnMetadata) ([]byte, error) {
|
|
return nil, nil
|
|
}
|
|
|
|
func (wf *workdingdirFactory) listPipe(conn libplugin.ConnMetadata) ([]skel.SkelPipe, error) {
|
|
user := conn.User()
|
|
|
|
if !wf.allowBadUsername {
|
|
if !isUsernameSecure(user) {
|
|
return nil, fmt.Errorf("bad username: %s", user)
|
|
}
|
|
}
|
|
|
|
var pipes []skel.SkelPipe
|
|
userdir := path.Join(wf.root, conn.User())
|
|
|
|
_ = filepath.Walk(userdir, func(path string, info os.FileInfo, err error) (stop error) {
|
|
log.Infof("search upstreams in path: %v", path)
|
|
if err != nil {
|
|
log.Infof("error walking path: %v", err)
|
|
return
|
|
}
|
|
|
|
if !info.IsDir() {
|
|
return
|
|
}
|
|
|
|
if !wf.recursiveSearch {
|
|
stop = fmt.Errorf("stop")
|
|
}
|
|
|
|
w := &workingdir{
|
|
Path: path,
|
|
NoCheckPerm: wf.noCheckPerm,
|
|
Strict: wf.strictHostKey,
|
|
}
|
|
|
|
data, err := w.Readfile(userUpstreamFile)
|
|
if err != nil {
|
|
log.Infof("error reading upstream file: %v in %v", err, w.Path)
|
|
return
|
|
}
|
|
|
|
host, user, err := parseUpstreamFile(string(data))
|
|
if err != nil {
|
|
log.Infof("ignore upstream folder %v due to: %v", w.Path, err)
|
|
return
|
|
}
|
|
|
|
pipes = append(pipes, &skelpipeWrapper{
|
|
dir: w,
|
|
host: host,
|
|
username: user,
|
|
})
|
|
|
|
return
|
|
})
|
|
|
|
return pipes, nil
|
|
}
|