Created
November 17, 2014 04:42
-
-
Save jordanorelli/ffe9d3352c24baed9d94 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"code.google.com/p/go.crypto/ssh" | |
"code.google.com/p/go.crypto/ssh/terminal" | |
"flag" | |
"fmt" | |
"io" | |
"io/ioutil" | |
"log" | |
"net" | |
"os" | |
) | |
const ( | |
E_Ok int = iota | |
E_BadPrivateKey | |
E_ListenError | |
E_HandshakeError | |
) | |
var ( | |
info_log *log.Logger | |
error_log *log.Logger | |
) | |
var options struct { | |
privateKeyPath string | |
} | |
func handlePassword(conn ssh.ConnMetadata, password []byte) (*ssh.Permissions, error) { | |
log_info("saw password request from connection: %v", conn) | |
log_info("client remote address: %v", conn.RemoteAddr()) | |
log_info("client local address: %v", conn.LocalAddr()) | |
log_info("client has server version: %s", conn.ServerVersion()) | |
log_info("client version: %s", conn.ClientVersion()) | |
log_info("client has session id: %v", conn.SessionID()) | |
log_info("user: %s", conn.User()) | |
log_info("password sent: %s", password) | |
var perms ssh.Permissions | |
return &perms, nil | |
} | |
// func handlePublicKey(conn ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error) { | |
// | |
// } | |
// func handleKeyboardAuth(conn ssh.ConnMetadata, client ssh.KeyboardInteractiveChallenge) (*ssh.Permissions, error) { | |
// | |
// } | |
// func logAuth(conn ssh.ConnMetadata, method string, err error) { | |
// | |
// } | |
func bail(status int, template string, args ...interface{}) { | |
if status == 0 { | |
fmt.Fprintf(os.Stdout, template, args...) | |
} else { | |
fmt.Fprintf(os.Stderr, template, args...) | |
} | |
os.Exit(status) | |
} | |
func log_error(template string, args ...interface{}) { | |
error_log.Printf(template, args...) | |
} | |
func log_info(template string, args ...interface{}) { | |
info_log.Printf(template, args...) | |
} | |
func handleConnection(conn net.Conn, config *ssh.ServerConfig) { | |
serverConn, newChan, requestChan, err := ssh.NewServerConn(conn, config) | |
if err != nil { | |
log_error("error in client handshake: %v", err) | |
return | |
} | |
go func() { | |
for request := range requestChan { | |
log_info("received request: %v", request) | |
} | |
}() | |
go func() { | |
for request := range newChan { | |
log_info("request to create a new channel of type: %v with extra data: %v", request.ChannelType(), request.ExtraData()) | |
sshChan, requestChan, err := request.Accept() | |
if err != nil { | |
log_error("error accepting request to create new ssh channel: %v", err) | |
return | |
} | |
defer sshChan.Close() | |
go func() { | |
for req := range requestChan { | |
log_info("saw out of band request: %v", req) | |
} | |
}() | |
log_info("I don't know what to do with this ssh chan: %v", sshChan) | |
term := terminal.NewTerminal(sshChan, "> ") | |
for { | |
line, err := term.ReadLine() | |
switch err { | |
case io.EOF: | |
fmt.Fprintln(term, "bye") | |
return | |
case nil: | |
default: | |
log_error("error reading line from terminal: %v", err) | |
} | |
log_info(line) | |
} | |
} | |
}() | |
log_info("server conn: %v\n", serverConn) | |
log_info("newchan: %v\n", newChan) | |
log_info("requestchan: %v\n", requestChan) | |
if err := serverConn.Wait(); err != nil { | |
log_error("server conn exited with error: %v", err) | |
} | |
} | |
func main() { | |
flag.Parse() | |
// load up private key file | |
pemBytes, err := ioutil.ReadFile(options.privateKeyPath) | |
if err != nil { | |
bail(E_BadPrivateKey, "unable to read private key file: %v", err) | |
} | |
log_info("read %d pem bytes\n", len(pemBytes)) | |
// parse private key file data | |
signer, err := ssh.ParsePrivateKey(pemBytes) | |
if err != nil { | |
bail(E_BadPrivateKey, "unable to parse private key data: %v", err) | |
} | |
log_info("parsed private key\n") | |
config := &ssh.ServerConfig{ | |
NoClientAuth: false, | |
PasswordCallback: handlePassword, | |
// PublicKeyCallback: handlePublicKey, | |
// KeyboardInteractiveCallback: handleKeyboardAuth, | |
// AuthLogCallback: logAuth, | |
} | |
config.AddHostKey(signer) | |
listener, err := net.Listen("tcp", "0.0.0.0:9000") | |
if err != nil { | |
bail(E_ListenError, "unable to open tcp listener: %v", err) | |
} | |
log_info("listening on tcp port 9000\n") | |
for { | |
conn, err := listener.Accept() | |
if err != nil { | |
bail(E_ListenError, "unable to open receive connection: %v", err) | |
} | |
log_info("received incoming connection\n") | |
go handleConnection(conn, config) | |
} | |
} | |
func init() { | |
flag.StringVar(&options.privateKeyPath, "private-key", "test_rsa", "rsa private key") | |
info_log = log.New(os.Stdout, "[INFO] ", 0) | |
error_log = log.New(os.Stderr, "[ERROR] ", 0) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment