Skip to content

Instantly share code, notes, and snippets.

@mickael-kerjean
Last active August 26, 2022 08:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mickael-kerjean/4d5aa508d45df5e1bfacb14432b83e62 to your computer and use it in GitHub Desktop.
Save mickael-kerjean/4d5aa508d45df5e1bfacb14432b83e62 to your computer and use it in GitHub Desktop.
sftp
/*
* Build steps:
* 1. go generate -x ./index.go
* 2. go build -o sftp.bin index.go
*/
package main
import (
_ "embed"
"fmt"
"github.com/pkg/sftp"
"golang.org/x/crypto/ssh"
"net"
"os"
)
//go:generate sh -c "ssh-keygen -t rsa -f id_rsa"
var CREDENTIALS [][]string = [][]string{
[]string{"anonymous", "anonymous"},
// []string{"username", "password"},
}
//go:embed id_rsa
var id_rsa []byte
func main() {
conn := func() net.Conn {
listener, err := net.Listen("tcp", "0.0.0.0:2022")
fatalError("net.Listen::error", err)
fmt.Printf("Listening on %v\n", listener.Addr())
nConn, err := listener.Accept()
fatalError("listener.Accept::error", err)
return nConn
}()
serverConfig := func() *ssh.ServerConfig {
config := &ssh.ServerConfig{
PasswordCallback: func(c ssh.ConnMetadata, pass []byte) (*ssh.Permissions, error) {
for i := range CREDENTIALS {
if string(c.User()) == CREDENTIALS[i][0] && string(pass) == CREDENTIALS[i][1] {
return nil, nil
}
}
return nil, fmt.Errorf("password rejected for %q", c.User())
},
}
config.AddHostKey(func() ssh.Signer {
private, err := ssh.ParsePrivateKey(id_rsa)
fatalError("ssh.ParsePrivateKey::error", err)
return private
}())
return config
}()
_, chans, reqs, err := ssh.NewServerConn(conn, serverConfig)
fatalError("ssh.NewServerConn::error", err)
go ssh.DiscardRequests(reqs)
for newChannel := range chans {
if newChannel.ChannelType() != "session" {
newChannel.Reject(ssh.UnknownChannelType, "unknown channel type")
continue
}
channel, requests, err := newChannel.Accept()
fatalError("newChannel.Accept::error", err)
go func(in <-chan *ssh.Request) {
for req := range in {
switch req.Type {
case "subsystem":
if string(req.Payload[4:]) == "sftp" {
req.Reply(true, nil)
}
}
}
}(requests)
server, err := sftp.NewServer(channel, []sftp.ServerOption{
// sftp.ReadOnly(),
// sftp.WithDebug(os.Stderr),
}...)
fatalError("sftp.NewServer::error", err)
server.Serve()
}
}
func fatalError(s string, err error) {
if err == nil {
return
}
fmt.Printf(s+" - %s", err.Error())
os.Exit(1)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment