Пример #1
0
func (d *ESX5Driver) connect() error {
	address := fmt.Sprintf("%s:%d", d.Host, d.Port)

	auth := []gossh.AuthMethod{
		gossh.Password(d.Password),
		gossh.KeyboardInteractive(
			ssh.PasswordKeyboardInteractive(d.Password)),
	}

	if d.PrivateKey != "" {
		signer, err := commonssh.FileSigner(d.PrivateKey)
		if err != nil {
			return err
		}

		auth = append(auth, gossh.PublicKeys(signer))
	}

	sshConfig := &ssh.Config{
		Connection: ssh.ConnectFunc("tcp", address),
		SSHConfig: &gossh.ClientConfig{
			User: d.Username,
			Auth: auth,
		},
	}

	comm, err := ssh.New(address, sshConfig)
	if err != nil {
		return err
	}

	d.comm = comm
	return nil
}
Пример #2
0
// SSHConfig returns a function that can be used for the SSH communicator
// config for connecting to the instance created over SSH using the private key
// or password.
func SSHConfig(username, password string) func(multistep.StateBag) (*ssh.ClientConfig, error) {
	return func(state multistep.StateBag) (*ssh.ClientConfig, error) {

		privateKey, hasKey := state.GetOk("privateKey")
		if hasKey {

			signer, err := ssh.ParsePrivateKey([]byte(privateKey.(string)))
			if err != nil {
				return nil, fmt.Errorf("Error setting up SSH config: %s", err)
			}
			return &ssh.ClientConfig{
				User: username,
				Auth: []ssh.AuthMethod{
					ssh.PublicKeys(signer),
				},
			}, nil

		} else {
			return &ssh.ClientConfig{
				User: username,
				Auth: []ssh.AuthMethod{
					ssh.Password(password),
					ssh.KeyboardInteractive(
						packerssh.PasswordKeyboardInteractive(password)),
				}}, nil
		}
	}
}
Пример #3
0
func (d *ESX5Driver) connect() error {
	address := fmt.Sprintf("%s:%d", d.Host, d.Port)

	auth := []gossh.AuthMethod{
		gossh.Password(d.Password),
		gossh.KeyboardInteractive(
			ssh.PasswordKeyboardInteractive(d.Password)),
	}

	// TODO(dougm) KeyPath support
	sshConfig := &ssh.Config{
		Connection: ssh.ConnectFunc("tcp", address),
		SSHConfig: &gossh.ClientConfig{
			User: d.Username,
			Auth: auth,
		},
	}

	comm, err := ssh.New(address, sshConfig)
	if err != nil {
		return err
	}

	d.comm = comm
	return nil
}
Пример #4
0
Файл: ssh.go Проект: calmh/mole
func sshOnConn(conn net.Conn, h conf.Host) (*ssh.Client, error) {
	var auths []ssh.AuthMethod

	if h.Pass != "" {
		auths = append(auths, ssh.Password(h.Pass))
		auths = append(auths, ssh.KeyboardInteractive(kbdInteractive(h.Pass)))
	}

	if h.Key != "" {
		k := &keyring{}
		err := k.loadPEM([]byte(h.Key))
		if err != nil {
			return nil, err
		}
		for _, k := range k.keys {
			s, _ := ssh.NewSignerFromKey(k)
			auths = append(auths, ssh.PublicKeys(s))
		}
	}

	config := &ssh.ClientConfig{
		User: h.User,
		Auth: auths,
	}

	debugln("handshake & authenticate")
	cc, nc, reqs, err := ssh.NewClientConn(conn, conn.RemoteAddr().String(), config)
	if err != nil {
		return nil, err
	}
	client := ssh.NewClient(cc, nc, reqs)
	return client, nil
}
Пример #5
0
func buildSSHClientConfig(opts sshClientConfigOpts) (*ssh.ClientConfig, error) {
	conf := &ssh.ClientConfig{
		User: opts.user,
	}

	if opts.privateKey != "" {
		pubKeyAuth, err := readPrivateKey(opts.privateKey)
		if err != nil {
			return nil, err
		}
		conf.Auth = append(conf.Auth, pubKeyAuth)
	}

	if opts.password != "" {
		conf.Auth = append(conf.Auth, ssh.Password(opts.password))
		conf.Auth = append(conf.Auth, ssh.KeyboardInteractive(
			PasswordKeyboardInteractive(opts.password)))
	}

	if opts.sshAgent != nil {
		conf.Auth = append(conf.Auth, opts.sshAgent.Auth())
	}

	return conf, nil
}
Пример #6
0
func sshConfig(state multistep.StateBag) (*gossh.ClientConfig, error) {
	config := state.Get("config").(*Config)
	var privateKey string

	var auth []gossh.AuthMethod

	if config.Comm.SSHPassword != "" {
		auth = []gossh.AuthMethod{
			gossh.Password(config.Comm.SSHPassword),
			gossh.KeyboardInteractive(
				ssh.PasswordKeyboardInteractive(config.Comm.SSHPassword)),
		}
	}

	if config.Comm.SSHPrivateKey != "" {
		if priv, ok := state.GetOk("privateKey"); ok {
			privateKey = priv.(string)
		}
		signer, err := gossh.ParsePrivateKey([]byte(privateKey))
		if err != nil {
			return nil, fmt.Errorf("Error setting up SSH config: %s", err)
		}
		if err != nil {
			return nil, err
		}

		auth = append(auth, gossh.PublicKeys(signer))
	}
	return &gossh.ClientConfig{
		User: config.Comm.SSHUsername,
		Auth: auth,
	}, nil
}
Пример #7
0
func sshConfig(comm *communicator.Config) func(state multistep.StateBag) (*gossh.ClientConfig, error) {
	return func(state multistep.StateBag) (*gossh.ClientConfig, error) {
		if comm.SSHPrivateKey != "" {
			// key based auth
			bytes, err := ioutil.ReadFile(comm.SSHPrivateKey)
			if err != nil {
				return nil, fmt.Errorf("Error setting up SSH config: %s", err)
			}
			privateKey := string(bytes)

			signer, err := gossh.ParsePrivateKey([]byte(privateKey))
			if err != nil {
				return nil, fmt.Errorf("Error setting up SSH config: %s", err)
			}

			return &gossh.ClientConfig{
				User: comm.SSHUsername,
				Auth: []gossh.AuthMethod{
					gossh.PublicKeys(signer),
				},
			}, nil
		} else {
			// password based auth
			return &gossh.ClientConfig{
				User: comm.SSHUsername,
				Auth: []gossh.AuthMethod{
					gossh.Password(comm.SSHPassword),
					gossh.KeyboardInteractive(
						ssh.PasswordKeyboardInteractive(comm.SSHPassword)),
				},
			}, nil
		}
	}
}
Пример #8
0
func connectToRemoteHost(auth ssh.AuthMethod, user, host string, port int64) (*ssh.Client, error) {
	clientConfig := &ssh.ClientConfig{
		User: user,
		Auth: []ssh.AuthMethod{auth, ssh.KeyboardInteractive(kic)},
	}

	return ssh.Dial("tcp", fmt.Sprintf("%s:%d", host, port), clientConfig)
}
Пример #9
0
func main() {
	listen := flag.String("listen", ":2022", "listen address")
	dest := flag.String("dest", ":22", "destination address")
	key := flag.String("key", "host_key", "rsa key to use")
	flag.Parse()

	privateBytes, err := ioutil.ReadFile(*key)
	if err != nil {
		panic("Failed to load private key")
	}

	private, err := ssh.ParsePrivateKey(privateBytes)
	if err != nil {
		panic("Failed to parse private key")
	}

	sessions := map[net.Addr]map[string]interface{}{}

	config := &ssh.ServerConfig{
		PasswordCallback: func(c ssh.ConnMetadata, pass []byte) (*ssh.Permissions, error) {
			fmt.Printf("Login attempt: %s, user %s password: %s\n", c.RemoteAddr(), c.User(), string(pass))

			sessions[c.RemoteAddr()] = map[string]interface{}{
				"username": c.User(),
				"password": string(pass),
			}

			clientConfig := &ssh.ClientConfig{
				User: c.User(),
				Auth: []ssh.AuthMethod{
					ssh.KeyboardInteractive(func(user, instruction string, questions []string, echos []bool) ([]string, error) {
						if len(questions) == 1 && questions[0] == "Password:"******"tcp", *dest, clientConfig)
			if err != nil {
				return nil, err
			}
			sessions[c.RemoteAddr()]["client"] = client
			return nil, nil
		},
	}
	config.AddHostKey(private)

	sshproxy.ListenAndServe(*listen, config, func(c ssh.ConnMetadata) (*ssh.Client, error) {
		meta, ok := sessions[c.RemoteAddr()]
		if !ok {
			return nil, fmt.Errorf("session not found")
		}
		client := meta["client"].(*ssh.Client)
		fmt.Printf("Connection accepted from: %s", c.RemoteAddr())
		return client, nil
	}, nil, nil)
}
Пример #10
0
// NewClientConfig creates a barebones ssh.ClientConfig to be used with ssh.Dial.
func NewClientConfig(name string) *ssh.ClientConfig {
	return &ssh.ClientConfig{
		User: name,
		Auth: []ssh.AuthMethod{
			ssh.KeyboardInteractive(func(user, instruction string, questions []string, echos []bool) (answers []string, err error) {
				return
			}),
		},
	}
}
Пример #11
0
func openLog(path string) (io.WriteCloser, error) {
	m := scpPathRe.FindStringSubmatch(path)
	if m == nil {
		return os.OpenFile(path, os.O_WRONLY|os.O_CREATE, 0600)
	} else {
		user, pass, host, port, path := m[1], m[2], m[3], m[4], m[5]
		if path == "" {
			return nil, errors.New("blank remote file path")
		}
		if port == "" {
			port = "22"
		} else {
			port = port[1:]
		}
		config := ssh.ClientConfig{
			User: user,
			Auth: []ssh.AuthMethod{ssh.KeyboardInteractive(sshKeyboardAuth)},
		}
		if pass != "" {
			config.Auth = append([]ssh.AuthMethod{ssh.Password(pass[1:])}, config.Auth...)
		} else {
			config.Auth = append([]ssh.AuthMethod{ssh.PasswordCallback(func() (string, error) {
				fmt.Printf("Password: "******"tcp", net.JoinHostPort(host, port), &config)
		if err != nil {
			return nil, err
		}
		session, err := client.NewSession()
		if err != nil {
			return nil, err
		}
		inputStream, err := session.StdinPipe()
		if err != nil {
			session.Close()
			return nil, err
		}
		cmd := fmt.Sprintf("cat > %s", shellEscape(path))
		if err := session.Start(cmd); err != nil {
			session.Close()
			return nil, err
		}
		return inputStream, nil
	}
}
Пример #12
0
// SSHConfig returns a function that can be used for the SSH communicator
// config for connecting to the instance created over SSH using the private key
// or password.
func SSHConfig(useAgent bool, username, password string) func(multistep.StateBag) (*ssh.ClientConfig, error) {
	return func(state multistep.StateBag) (*ssh.ClientConfig, error) {
		if useAgent {
			authSock := os.Getenv("SSH_AUTH_SOCK")
			if authSock == "" {
				return nil, fmt.Errorf("SSH_AUTH_SOCK is not set")
			}

			sshAgent, err := net.Dial("unix", authSock)
			if err != nil {
				return nil, fmt.Errorf("Cannot connect to SSH Agent socket %q: %s", authSock, err)
			}

			return &ssh.ClientConfig{
				User: username,
				Auth: []ssh.AuthMethod{
					ssh.PublicKeysCallback(agent.NewClient(sshAgent).Signers),
				},
			}, nil
		}

		privateKey, hasKey := state.GetOk("privateKey")
		if hasKey {

			signer, err := ssh.ParsePrivateKey([]byte(privateKey.(string)))
			if err != nil {
				return nil, fmt.Errorf("Error setting up SSH config: %s", err)
			}
			return &ssh.ClientConfig{
				User: username,
				Auth: []ssh.AuthMethod{
					ssh.PublicKeys(signer),
				},
			}, nil

		} else {
			return &ssh.ClientConfig{
				User: username,
				Auth: []ssh.AuthMethod{
					ssh.Password(password),
					ssh.KeyboardInteractive(
						packerssh.PasswordKeyboardInteractive(password)),
				}}, nil
		}
	}
}
Пример #13
0
func main() {

	// Show the current version:
	log.Println(`SSHTunnel v1.3.0`)

	// Allow Go to use all CPUs:
	runtime.GOMAXPROCS(runtime.NumCPU())

	// Read the configuration from the command-line args:
	readFlags()

	// Check if the password was provided:
	for true {
		if password == `` {
			// Promt for the password:
			fmt.Println(`Please provide the password for the connection:`)
			if pass, errPass := gopass.GetPasswd(); errPass != nil {
				log.Println(`There was an error reading the password securely: ` + errPass.Error())
				os.Exit(1)
				return
			} else {
				password = string(pass)
			}
		} else {
			break
		}
	}

	// Create the SSH configuration:
	Tunnel.SetPassword4Callback(password)
	config := &ssh.ClientConfig{
		User: username,
		Auth: []ssh.AuthMethod{
			ssh.Password(password),
			ssh.PasswordCallback(Tunnel.PasswordCallback),
			ssh.KeyboardInteractive(Tunnel.KeyboardInteractiveChallenge),
		},
	}

	// Create the local end-point:
	localListener := Tunnel.CreateLocalEndPoint(localAddrString)

	// Accept client connections (will block forever):
	Tunnel.AcceptClients(localListener, config, serverAddrString, remoteAddrString)
}
Пример #14
0
func sshConfig(state multistep.StateBag) (*gossh.ClientConfig, error) {
	config := state.Get("config").(*Config)

	auth := []gossh.AuthMethod{
		gossh.Password(config.Comm.SSHPassword),
		gossh.KeyboardInteractive(
			ssh.PasswordKeyboardInteractive(config.Comm.SSHPassword)),
	}

	if config.Comm.SSHPrivateKey != "" {
		signer, err := commonssh.FileSigner(config.Comm.SSHPrivateKey)
		if err != nil {
			return nil, err
		}

		auth = append(auth, gossh.PublicKeys(signer))
	}

	return &gossh.ClientConfig{
		User: config.Comm.SSHUsername,
		Auth: auth,
	}, nil
}
Пример #15
0
func sshBastionConfig(config *Config) (*gossh.ClientConfig, error) {
	auth := make([]gossh.AuthMethod, 0, 2)
	if config.SSHBastionPassword != "" {
		auth = append(auth,
			gossh.Password(config.SSHBastionPassword),
			gossh.KeyboardInteractive(
				ssh.PasswordKeyboardInteractive(config.SSHBastionPassword)))
	}

	if config.SSHBastionPrivateKey != "" {
		signer, err := commonssh.FileSigner(config.SSHBastionPrivateKey)
		if err != nil {
			return nil, err
		}

		auth = append(auth, gossh.PublicKeys(signer))
	}

	return &gossh.ClientConfig{
		User: config.SSHBastionUsername,
		Auth: auth,
	}, nil
}
Пример #16
0
func SSHConfigFunc(config SSHConfig) func(multistep.StateBag) (*gossh.ClientConfig, error) {
	return func(state multistep.StateBag) (*gossh.ClientConfig, error) {
		auth := []gossh.AuthMethod{
			gossh.Password(config.Comm.SSHPassword),
			gossh.KeyboardInteractive(
				ssh.PasswordKeyboardInteractive(config.Comm.SSHPassword)),
		}

		if config.SSHKeyPath != "" {
			signer, err := commonssh.FileSigner(config.Comm.SSHPrivateKey)
			if err != nil {
				return nil, err
			}

			auth = append(auth, gossh.PublicKeys(signer))
		}

		return &gossh.ClientConfig{
			User: config.Comm.SSHUsername,
			Auth: auth,
		}, nil
	}
}
Пример #17
0
func sshConfig(state multistep.StateBag) (*ssh.ClientConfig, error) {
	config := state.Get("config").(config)
	privateKey := state.Get("ssh_private_key").(string)

	auth := []ssh.AuthMethod{
		ssh.Password(config.SSHPassword),
		ssh.KeyboardInteractive(
			packerssh.PasswordKeyboardInteractive(config.SSHPassword)),
	}

	if privateKey != "" {
		signer, err := ssh.ParsePrivateKey([]byte(privateKey))
		if err != nil {
			return nil, fmt.Errorf("Error setting up SSH config: %s", err)
		}

		auth = append(auth, ssh.PublicKeys(signer))
	}

	return &ssh.ClientConfig{
		User: config.SSHUsername,
		Auth: auth,
	}, nil
}
Пример #18
0
func main() {
	flag.Parse()
	logger, cl := makeLogger()

	if flagTrace {
		cl.SetMinLevel(colog.LTrace)
	} else if flagVerbose {
		cl.SetMinLevel(colog.LDebug)
	} else if flagQuiet {
		cl.SetMinLevel(colog.LWarning)
	} else {
		cl.SetMinLevel(colog.LInfo)
	}

	if len(flagAllowedSourceIPs) > 0 {
		log.Println("info: Allowed source IPs:")
		for _, host := range flagAllowedSourceIPs {
			log.Printf("  - %s", host)
		}
	}

	if len(flagAllowedDestinationIPs) > 0 {
		log.Println("info: Allowed destination IPs:")
		for _, host := range flagAllowedDestinationIPs {
			log.Printf("  - %s", host)
		}
	}

	addr := fmt.Sprintf("%s:%d", flagHost, flagPort)

	// Create a SOCKS5 server
	conf := &socks5.Config{
		Rules:  Rules{},
		Logger: logger,
	}
	server, err := socks5.New(conf)
	if err != nil {
		log.Fatalf("error: could not create SOCKS server: %s", err)
	}

	// Create the listener
	var (
		l          net.Listener
		listenHost string
	)

	if flagRemoteListener != "" {
		u, err := url.Parse(flagRemoteListener)
		if err != nil {
			log.Fatalf("error: error parsing url: %s", err)
		}
		if u.Scheme != "ssh" {
			log.Fatalf("error: url is not an SSH url: %s", flagRemoteListener)
		}
		if u.User == nil {
			log.Fatalf("error: no username provided in remote listener", err)
		}
		if u.Path != "" || u.RawQuery != "" || u.Fragment != "" {
			log.Printf("warning: path, query, and fragment have no meaning in remote listener URL")
		}

		listenHost = u.Host

		// TODO: uber-hack atm find a better way, pass as cmd line argument
		answers := keyboardInteractive(map[string]string{
			"Verification code: ": "",
		})

		config := &ssh.ClientConfig{
			User: u.User.Username(),
			//User: "******",
			Auth: []ssh.AuthMethod{
				SSHAgent(),
				ssh.KeyboardInteractive(answers.Challenge),
			},
		}

		sshConn, err := ssh.Dial("tcp", u.Host, config)
		if err != nil {
			log.Fatalf("error: error dialing remote host: %s", err)
		}
		defer sshConn.Close()

		l, err = sshConn.Listen("tcp", addr)
		if err != nil {
			log.Fatalf("error: error listening on remote host: %s", err)
		}
	} else {
		// Listen on a local port
		listenHost = "localhost"
		l, err = net.Listen("tcp", addr)
	}

	defer l.Close()

	log.Printf("info: starting socks proxy on: %s (proxy addr: %s)", listenHost, addr)
	if err := server.Serve(l); err != nil {
		log.Fatalf("error: could not serve socks proxy: %s", err)
	}

	log.Println("debug: done")
}
Пример #19
0
func runMain(cmd *cobra.Command, args []string) {
	if len(args) != 1 {
		log.Printf("error: invalid number of arguments (expected 1, got %d)", len(args))
		os.Exit(1)
	}

	sshHost := args[0]

	// Add a default ':22' after the end if we don't have a colon.
	if !strings.Contains(sshHost, ":") {
		sshHost += ":22"
	}

	config := &ssh.ClientConfig{
		User: flagSSHUsername,
		Auth: nil,
	}

	// Password auth or prompt callback
	if flagSSHPassword != "" {
		log.Println("trace: adding password auth")
		config.Auth = append(config.Auth, ssh.Password(flagSSHPassword))
	} else {
		log.Println("trace: adding password callback auth")
		config.Auth = append(config.Auth, ssh.PasswordCallback(func() (string, error) {
			prompt := fmt.Sprintf("%s@%s's password: "******"" {
		auth, err := loadPrivateKey(flagSSHIdentityFile)
		if err != nil {
			log.Fatalf("error: could not load identity file '%s': %s",
				flagSSHIdentityFile, err)
		}

		log.Println("trace: adding identity file auth")
		config.Auth = append(config.Auth, auth)
	}

	// SSH agent auth
	if agentConn, err := net.Dial("unix", os.Getenv("SSH_AUTH_SOCK")); err != nil {
		log.Println("trace: adding ssh agent auth")
		config.Auth = append(config.Auth,
			ssh.PublicKeysCallback(agent.NewClient(agentConn).Signers))
	}

	config.Auth = append(config.Auth,
		ssh.KeyboardInteractive(func(user, instruction string, questions []string, echos []bool) (answers []string, err error) {
			var (
				ans string
				b   []byte
			)

			for i, q := range questions {
				prompt := fmt.Sprintf("[question %d/%d] %s", i+1, len(questions), q)

				if echos[i] {
					fmt.Print(prompt)
					bio := bufio.NewReader(os.Stdin)
					b, _, err = bio.ReadLine()
					ans = string(b)
				} else {
					ans, err = speakeasy.Ask(prompt)
				}
				if err != nil {
					return
				}

				answers = append(answers, ans)
			}

			return
		}))

	// TODO: keyboard-interactive auth, e.g. for two-factor

	// Dial the SSH connection
	log.Printf("debug: attempting %d authentication methods (%+v)", len(config.Auth), config.Auth)
	sshConn, err := ssh.Dial("tcp", sshHost, config)
	if err != nil {
		log.Fatalf("error: error dialing remote host: %s", err)
	}
	defer sshConn.Close()

	// Listen on remote
	l, err := sshConn.Listen("tcp", flagAddr)
	if err != nil {
		log.Fatalf("error: error listening on remote host: %s", err)
	}

	// Start accepting shell connections
	log.Printf("info: listening for connections on %s (remote listen address: %s)", sshHost, flagAddr)
	for {
		conn, err := l.Accept()
		if err != nil {
			log.Printf("error: error accepting connection: %s", err)
			continue
		}

		log.Printf("info: accepted connection from: %s", conn.RemoteAddr())
		go handleConnection(conn)
	}
}
Пример #20
0
func main() {

	// Show the current version:
	log.Println(`Sync v1.2.0`)

	// Allow Go to use all CPUs:
	runtime.GOMAXPROCS(runtime.NumCPU())

	// Read the configuration from the command-line args:
	readFlags()

	// Check if the directories are provided:
	if localDir == `` || remoteDir == `` {
		log.Println(`Please provide the local and remote directory.`)
		os.Exit(1)
		return
	}

	// Should I use the current working dir?
	if localDir == `.` {
		if currentWD, currentWDError := os.Getwd(); currentWDError != nil {
			log.Println("Cannot use the current working directory as local directory: " + currentWDError.Error())
			os.Exit(2)
			return
		} else {
			log.Println("I use the current working directory as local directory: " + currentWD)
			localDir = currentWD
		}
	}

	// Remove trailing separators from both directories
	localDir = correctPath(localDir)
	remoteDir = correctPath(remoteDir)

	// Check if local dir exist
	if dirInfo, dirError := os.Stat(localDir); dirError != nil {
		log.Println("There is an error with the local directory: " + dirError.Error())
		os.Exit(3)
		return
	} else {
		if !dirInfo.IsDir() {
			log.Println("There is an error with the local directory: You provided a file instead!")
			os.Exit(4)
			return
		}
	}

	// Check if the password was provided:
	for true {
		if password == `` {
			// Promt for the password:
			fmt.Print(`Please provide the password for the connection: `)
			if pass, errPass := gopass.GetPasswd(); errPass != nil {
				log.Println(`There was an error reading the password securely: ` + errPass.Error())
				os.Exit(5)
				return
			} else {
				password = string(pass)
			}
		} else {
			break
		}
	}

	// Give some information about the state
	if supervised {
		log.Println("I use the supervised mode.")
	} else {
		log.Println("I do not use the supervised mode.")
	}

	if pushOnly {
		log.Println("I use the push only mode i.e. backup mode. Any remote change will be ignored.")
	} else {
		log.Println("I use the full mode and consider also remote changes.")
	}

	// Create the SSH configuration:
	Sync.SetPassword4Callback(password)
	config := &ssh.ClientConfig{
		User: username,
		Auth: []ssh.AuthMethod{
			ssh.Password(password),
			ssh.PasswordCallback(Sync.PasswordCallback),
			ssh.KeyboardInteractive(Sync.KeyboardInteractiveChallenge),
		},
	}

	// Connect to the SSH server:
	ssh := Sync.ConnectSSH(config, serverAddrString)
	if ssh == nil {
		log.Println(`It was not possible to connect to the SSH server.`)
		os.Exit(6)
		return
	}

	defer ssh.Close()
	Sync.Synchronise(ssh, supervised, pushOnly, localDir, remoteDir)
	log.Println("Synchronising done.")
}
Пример #21
0
// PrepareConfig is used to turn the *SSHConfig provided into a
// usable *Config for client initialization.
func PrepareConfig(conf *SSHConfig) (*Config, error) {
	var conn net.Conn
	var err error

	sshConf := &ssh.ClientConfig{
		User: conf.User,
	}
	if conf.Agent {
		sshAuthSock := os.Getenv("SSH_AUTH_SOCK")

		if sshAuthSock == "" {
			return nil, fmt.Errorf("SSH Requested but SSH_AUTH_SOCK not-specified")
		}

		conn, err = net.Dial("unix", sshAuthSock)
		if err != nil {
			return nil, fmt.Errorf("Error connecting to SSH_AUTH_SOCK: %v", err)
		}
		// I need to close this but, later after all connections have been made
		// defer conn.Close()
		signers, err := agent.NewClient(conn).Signers()
		if err != nil {
			return nil, fmt.Errorf("Error getting keys from ssh agent: %v", err)
		}

		sshConf.Auth = append(sshConf.Auth, ssh.PublicKeys(signers...))
	}
	if conf.KeyFile != "" {
		fullPath, err := homedir.Expand(conf.KeyFile)
		if err != nil {
			return nil, fmt.Errorf("Failed to expand home directory: %v", err)
		}
		key, err := ioutil.ReadFile(fullPath)
		if err != nil {
			return nil, fmt.Errorf("Failed to read key file '%s': %v", conf.KeyFile, err)
		}

		// We parse the private key on our own first so that we can
		// show a nicer error if the private key has a password.
		block, _ := pem.Decode(key)
		if block == nil {
			return nil, fmt.Errorf(
				"Failed to read key '%s': no key found", conf.KeyFile)
		}
		if block.Headers["Proc-Type"] == "4,ENCRYPTED" {
			return nil, fmt.Errorf(
				"Failed to read key '%s': password protected keys are\n"+
					"not supported. Please decrypt the key prior to use.", conf.KeyFile)
		}

		signer, err := ssh.ParsePrivateKey(key)
		if err != nil {
			return nil, fmt.Errorf("Failed to parse key file '%s': %v", conf.KeyFile, err)
		}

		sshConf.Auth = append(sshConf.Auth, ssh.PublicKeys(signer))
	}
	if conf.Password != "" {
		sshConf.Auth = append(sshConf.Auth,
			ssh.Password(conf.Password))
		sshConf.Auth = append(sshConf.Auth,
			ssh.KeyboardInteractive(PasswordKeyboardInteractive(conf.Password)))
	}
	host := fmt.Sprintf("%s:%d", conf.Host, conf.Port)
	config := &Config{
		SSHConfig:    sshConf,
		Connection:   ConnectFunc("tcp", host),
		SSHAgentConn: conn,
	}
	return config, nil
}
Пример #22
0
func (s *sshTunnel) Start(readyErrCh chan<- error, errCh chan<- error) {
	authMethods := []ssh.AuthMethod{}

	if s.options.PrivateKey != "" {
		s.logger.Debug(s.logTag, "Reading private key file '%s'", s.options.PrivateKey)
		keyContents, err := ioutil.ReadFile(s.options.PrivateKey)
		if err != nil {
			readyErrCh <- bosherr.WrapErrorf(err, "Reading private key file '%s'", s.options.PrivateKey)
			return
		}

		s.logger.Debug(s.logTag, "Parsing private key file '%s'", s.options.PrivateKey)
		signer, err := ssh.ParsePrivateKey(keyContents)
		if err != nil {
			readyErrCh <- bosherr.WrapErrorf(err, "Parsing private key file '%s'", s.options.PrivateKey)
			return
		}

		authMethods = append(authMethods, ssh.PublicKeys(signer))
	}

	if s.options.Password != "" {
		s.logger.Debug(s.logTag, "Adding password auth method to ssh tunnel config")

		keyboardInteractiveChallenge := func(
			user,
			instruction string,
			questions []string,
			echos []bool,
		) (answers []string, err error) {
			if len(questions) == 0 {
				return []string{}, nil
			}
			return []string{s.options.Password}, nil
		}
		authMethods = append(authMethods, ssh.KeyboardInteractive(keyboardInteractiveChallenge))
		authMethods = append(authMethods, ssh.Password(s.options.Password))
	}

	sshConfig := &ssh.ClientConfig{
		User: s.options.User,
		Auth: authMethods,
	}

	s.logger.Debug(s.logTag, "Dialing remote server at %s:%d", s.options.Host, s.options.Port)
	remoteAddr := fmt.Sprintf("%s:%d", s.options.Host, s.options.Port)

	retryStrategy := &SSHRetryStrategy{
		TimeService:              s.timeService,
		ConnectionRefusedTimeout: s.connectionRefusedTimeout,
		AuthFailureTimeout:       s.authFailureTimeout,
	}

	var conn *ssh.Client
	var err error
	for i := 0; ; i++ {
		s.logger.Debug(s.logTag, "Making attempt #%d", i)
		conn, err = ssh.Dial("tcp", remoteAddr, sshConfig)

		if err == nil {
			break
		}

		if !retryStrategy.IsRetryable(err) {
			readyErrCh <- bosherr.WrapError(err, "Failed to connect to remote server")
			return
		}

		s.logger.Debug(s.logTag, "Attempt failed #%d: Dialing remote server: %s", i, err.Error())

		time.Sleep(s.startDialDelay)
	}

	remoteListenAddr := fmt.Sprintf("127.0.0.1:%d", s.options.RemoteForwardPort)
	s.logger.Debug(s.logTag, "Listening on remote server %s", remoteListenAddr)
	s.remoteListener, err = conn.Listen("tcp", remoteListenAddr)
	if err != nil {
		readyErrCh <- bosherr.WrapError(err, "Listening on remote server")
		return
	}

	readyErrCh <- nil
	for {
		remoteConn, err := s.remoteListener.Accept()
		s.logger.Debug(s.logTag, "Received connection")
		if err != nil {
			errCh <- bosherr.WrapError(err, "Accepting connection on remote server")
		}
		defer func() {
			if err = remoteConn.Close(); err != nil {
				s.logger.Warn(s.logTag, "Failed to close remote listener connection: %s", err.Error())
			}
		}()

		s.logger.Debug(s.logTag, "Dialing local server")
		localDialAddr := fmt.Sprintf("127.0.0.1:%d", s.options.LocalForwardPort)
		localConn, err := net.Dial("tcp", localDialAddr)
		if err != nil {
			errCh <- bosherr.WrapError(err, "Dialing local server")
			return
		}

		go func() {
			bytesNum, err := io.Copy(remoteConn, localConn)
			defer func() {
				if err = localConn.Close(); err != nil {
					s.logger.Warn(s.logTag, "Failed to close local dial connection: %s", err.Error())
				}
			}()
			s.logger.Debug(s.logTag, "Copying bytes from local to remote %d", bytesNum)
			if err != nil {
				errCh <- bosherr.WrapError(err, "Copying bytes from local to remote")
			}
		}()

		go func() {
			bytesNum, err := io.Copy(localConn, remoteConn)
			defer func() {
				if err = localConn.Close(); err != nil {
					s.logger.Warn(s.logTag, "Failed to close local dial connection: %s", err.Error())
				}
			}()
			s.logger.Debug(s.logTag, "Copying bytes from remote to local %d", bytesNum)
			if err != nil {
				errCh <- bosherr.WrapError(err, "Copying bytes from remote to local")
			}
		}()
	}
}
Пример #23
0
func SSHExec(ws *websocket.Conn) {
	var dump_out, dump_in io.WriteCloser
	defer func() {
		ws.Close()
		if nil != dump_out {
			dump_out.Close()
		}
		if nil != dump_in {
			dump_in.Close()
		}
	}()

	hostname := ws.Request().URL.Query().Get("hostname")
	port := ws.Request().URL.Query().Get("port")
	if "" == port {
		port = "22"
	}
	user := ws.Request().URL.Query().Get("user")
	pwd := ws.Request().URL.Query().Get("password")
	debug := *is_debug
	if "true" == strings.ToLower(ws.Request().URL.Query().Get("debug")) {
		debug = true
	}

	cmd := ws.Request().URL.Query().Get("cmd")
	cmd_alias := ws.Request().URL.Query().Get("dump_file")
	if "" == cmd_alias {
		cmd_alias = strings.Replace(cmd, " ", "_", -1)
	}

	password_count := 0
	empty_interactive_count := 0
	reader := bufio.NewReader(ws)
	// Dial code is taken from the ssh package example
	config := &ssh.ClientConfig{
		Config: ssh.Config{Ciphers: supportedCiphers},
		User:   user,
		Auth: []ssh.AuthMethod{
			ssh.Password(pwd),
			ssh.KeyboardInteractive(func(user, instruction string, questions []string, echos []bool) (answers []string, err error) {
				if len(questions) == 0 {
					empty_interactive_count++
					if empty_interactive_count++; empty_interactive_count > 50 {
						return nil, errors.New("interactive count is too much")
					}
					return []string{}, nil
				}
				for _, question := range questions {
					io.WriteString(ws, question)

					switch strings.ToLower(strings.TrimSpace(question)) {
					case "password:"******"password as":
						password_count++
						if password_count == 1 {
							answers = append(answers, pwd)
							break
						}
						fallthrough
					default:
						line, _, e := reader.ReadLine()
						if nil != e {
							return nil, e
						}
						answers = append(answers, string(line))
					}
				}
				return answers, nil
			})},
	}
	client, err := ssh.Dial("tcp", hostname+":"+port, config)
	if err != nil {
		logString(ws, "Failed to dial: "+err.Error())
		return
	}

	session, err := client.NewSession()
	if err != nil {
		logString(ws, "Failed to create session: "+err.Error())
		return
	}
	defer session.Close()

	var combinedOut io.Writer = ws
	if debug {
		dump_out, err = os.OpenFile(logs_dir+hostname+"_"+cmd_alias+".dump_ssh_out.txt", os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0666)
		if nil == err {
			fmt.Println("log to file", logs_dir+hostname+"_"+cmd_alias+".dump_ssh_out.txt")
			combinedOut = io.MultiWriter(dump_out, ws)
		} else {
			fmt.Println("failed to open log file,", err)
		}

		dump_in, err = os.OpenFile(logs_dir+hostname+"_"+cmd_alias+".dump_ssh_in.txt", os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0666)
		if nil != err {
			dump_in = nil
			fmt.Println("failed to open log file,", err)
		} else {
			fmt.Println("log to file", logs_dir+hostname+"_"+cmd_alias+".dump_ssh_in.txt")
		}
	}

	session.Stdout = combinedOut
	session.Stderr = combinedOut
	session.Stdin = warp(ws, dump_in)

	if err := session.Start(cmd); nil != err {
		logString(combinedOut, "Unable to execute command:"+err.Error())
		return
	}
	if err := session.Wait(); nil != err {
		logString(combinedOut, "Unable to execute command:"+err.Error())
		return
	}
	fmt.Println("exec ok")
}
Пример #24
0
func SSHShell(ws *websocket.Conn) {
	var dump_out, dump_in io.WriteCloser
	defer func() {
		ws.Close()
		if nil != dump_out {
			dump_out.Close()
		}
		if nil != dump_in {
			dump_in.Close()
		}
	}()

	hostname := ws.Request().URL.Query().Get("hostname")
	port := ws.Request().URL.Query().Get("port")
	if "" == port {
		port = "22"
	}
	user := ws.Request().URL.Query().Get("user")
	pwd := ws.Request().URL.Query().Get("password")
	columns := toInt(ws.Request().URL.Query().Get("columns"), 120)
	rows := toInt(ws.Request().URL.Query().Get("rows"), 80)
	debug := *is_debug
	if "true" == strings.ToLower(ws.Request().URL.Query().Get("debug")) {
		debug = true
	}

	password_count := 0
	empty_interactive_count := 0
	reader := bufio.NewReader(ws)
	// Dial code is taken from the ssh package example
	config := &ssh.ClientConfig{
		Config: ssh.Config{Ciphers: supportedCiphers},
		User:   user,
		Auth: []ssh.AuthMethod{
			ssh.Password(pwd),
			ssh.KeyboardInteractive(func(user, instruction string, questions []string, echos []bool) (answers []string, err error) {
				if len(questions) == 0 {
					empty_interactive_count++
					if empty_interactive_count++; empty_interactive_count > 50 {
						return nil, errors.New("interactive count is too much")
					}
					return []string{}, nil
				}
				for _, question := range questions {
					io.WriteString(ws, question)

					switch strings.ToLower(strings.TrimSpace(question)) {
					case "password:"******"password as":
						password_count++
						if password_count == 1 {
							answers = append(answers, pwd)
							break
						}
						fallthrough
					default:
						line, _, e := reader.ReadLine()
						if nil != e {
							return nil, e
						}
						answers = append(answers, string(line))
					}
				}
				return answers, nil
			}),
		},
	}
	client, err := ssh.Dial("tcp", hostname+":"+port, config)
	if err != nil {
		logString(ws, "Failed to dial: "+err.Error())
		return
	}

	session, err := client.NewSession()
	if err != nil {
		logString(ws, "Failed to create session: "+err.Error())
		return
	}
	defer session.Close()

	// Set up terminal modes
	modes := ssh.TerminalModes{
		ssh.ECHO:          1,     // disable echoing
		ssh.TTY_OP_ISPEED: 14400, // input speed = 14.4kbaud
		ssh.TTY_OP_OSPEED: 14400, // output speed = 14.4kbaud
	}
	// Request pseudo terminal
	if err = session.RequestPty("xterm", rows, columns, modes); err != nil {
		logString(ws, "request for pseudo terminal failed:"+err.Error())
		return
	}

	var combinedOut io.Writer = ws
	if debug {
		dump_out, err = os.OpenFile(logs_dir+hostname+".dump_ssh_out.txt", os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0666)
		if nil == err {
			combinedOut = io.MultiWriter(dump_out, ws)
		}

		dump_in, err = os.OpenFile(logs_dir+hostname+".dump_ssh_in.txt", os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0666)
		if nil != err {
			dump_in = nil
		}
	}

	session.Stdout = combinedOut
	session.Stderr = combinedOut
	session.Stdin = warp(ws, dump_in)
	if err := session.Shell(); nil != err {
		logString(ws, "Unable to execute command:"+err.Error())
		return
	}
	if err := session.Wait(); nil != err {
		logString(ws, "Unable to execute command:"+err.Error())
	}
}