package ssh import ( c "docker4ssh/config" "docker4ssh/database" "fmt" "golang.org/x/crypto/ssh" "io/ioutil" ) func NewSSHConfig(config *c.Config) (*ssh.ServerConfig, error) { db := database.GetDatabase() sshConfig := &ssh.ServerConfig{ MaxAuthTries: 3, PasswordCallback: func(conn ssh.ConnMetadata, password []byte) (*ssh.Permissions, error) { if containerID, exists := db.GetContainerByAuth(database.NewUnsafeAuth(conn.User(), password)); exists && containerID != "" { return &ssh.Permissions{ CriticalOptions: map[string]string{ "containerID": containerID, }, }, nil } else if profile, ok := profiles.Match(conn.User(), password); ok { return &ssh.Permissions{ CriticalOptions: map[string]string{ "profile": profile.Name(), }, }, nil } else if config.Profile.Dynamic.Enable && dynamicProfile.Match(conn.User(), password) { return &ssh.Permissions{ CriticalOptions: map[string]string{ "profile": "dynamic", "image": conn.User(), }, }, nil } // i think logging the wrong password is a bit unsafe. // if you have e.g. just a type in it isn't very well to see your nearly correct password in the logs return nil, fmt.Errorf("%s tried to connect with user %s but entered wrong a password", conn.RemoteAddr().String(), conn.User()) }, } sshConfig.SetDefaults() key, err := parseSSHPrivateKey(config.SSH.Keyfile, []byte(config.SSH.Passphrase)) if err != nil { return nil, err } sshConfig.AddHostKey(key) return sshConfig, nil } func parseSSHPrivateKey(path string, password []byte) (ssh.Signer, error) { keyBytes, err := ioutil.ReadFile(path) if err != nil { return nil, err } var key ssh.Signer if len(password) == 0 { key, err = ssh.ParsePrivateKey(keyBytes) } else { key, err = ssh.ParsePrivateKeyWithPassphrase(keyBytes, password) } if err != nil { return nil, err } return key, nil }