aboutsummaryrefslogblamecommitdiff
path: root/sshwincs.go
blob: 383031e7c6d805172832b336341f97d257eebf35 (plain) (tree)






















































































































































































































                                                                                                                                                                                                                                                                                                                              
package main

import (
	"fmt"
	"os"
	"os/exec"
	"regexp"

	"github.com/lxn/walk"
	"github.com/lxn/walk/declarative"
)

// RemoteSSHShell struct type to store ssh data
type RemoteSSHShell struct {
	AuthMthd   int
	HostAddr   string
	HostPort   int
	PreVTKEY   string // private key path
	PassPhrase string
	PassWord   string
	UserName   string
}

func startSSHsession(owner walk.Form, sendipaddr string) (int, error) {
	const regexSingle = `^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$|^(([a-zA-Z]{1})|([a-zA-Z]{1}[a-zA-Z]{1})|([a-zA-Z]{1}[0-9]{1})|([0-9]{1}[a-zA-Z]{1})|([a-zA-Z0-9][a-zA-Z0-9-_]{1,61}[a-zA-Z0-9]))\.([a-zA-Z]{2,6}|[a-zA-Z0-9-]{2,30}\.[a-zA-Z]{2,3})$`

	var sshClientguiwindow struct {
		dlgSSHAccwin                  *walk.Dialog
		dbindersshx                   *walk.DataBinder
		acceptPB, cancelPB            *walk.PushButton
		mapLineEd, pkLineEd, pKandPHm *walk.LineEdit
		passGBOXm, pKeyGBOXm          *walk.GroupBox
	}

	sshstatset := &RemoteSSHShell{
		AuthMthd: 1,
		HostPort: 22,
		UserName: "root",
		HostAddr: sendipaddr,
	}
	return declarative.Dialog{
		AssignTo:      &sshClientguiwindow.dlgSSHAccwin,
		FixedSize:     true,
		Title:         "SSH Client",
		DefaultButton: &sshClientguiwindow.acceptPB,
		CancelButton:  &sshClientguiwindow.cancelPB,
		DataBinder: declarative.DataBinder{
			AssignTo:       &sshClientguiwindow.dbindersshx,
			Name:           "sshClient",
			DataSource:     sshstatset,
			ErrorPresenter: declarative.ToolTipErrorPresenter{},
		},
		MinSize: declarative.Size{Width: 320, Height: 300},
		Layout:  declarative.VBox{},
		Children: []declarative.Widget{
			declarative.GroupBox{
				Title:  "SSH Client Options",
				Layout: declarative.HBox{},
				Children: []declarative.Widget{
					declarative.Composite{
						Layout: declarative.Grid{Columns: 1},
						Children: []declarative.Widget{
							declarative.GroupBox{
								Title:  "Host Address To Connect",
								Layout: declarative.Grid{Columns: 4},
								Children: []declarative.Widget{
									declarative.LineEdit{
										ToolTipText: "username for ssh connection",
										CueBanner:   "User",
										MaxSize:     declarative.Size{Width: 55},
										Text:        declarative.Bind("UserName"),
									},

									declarative.LineEdit{
										AssignTo:    &sshClientguiwindow.mapLineEd,
										ToolTipText: "format: IP|Domain",
										CueBanner:   "IP or Domain",
										Text:        declarative.Bind("HostAddr"),
									},

									declarative.NumberEdit{
										ToolTipText: "port number",
										MaxSize:     declarative.Size{Width: 40},
										MinSize:     declarative.Size{Width: 40},
										Value:       declarative.Bind("HostPort"),
										MinValue:    1,
										MaxValue:    65535,
									},
								},
							},
							declarative.RadioButtonGroupBox{
								Title:      "Authentication",
								Layout:     declarative.HBox{},
								DataMember: "AuthMthd",
								Buttons: []declarative.RadioButton{
									{MaxSize: declarative.Size{Width: 90}, Text: "Password", Value: 1, OnClicked: func() {
										sshClientguiwindow.passGBOXm.SetVisible(true)
										sshClientguiwindow.pKeyGBOXm.SetVisible(false)
										sshClientguiwindow.pKandPHm.SetVisible(false)
									}},
									{MaxSize: declarative.Size{Width: 90}, Text: "PrivateK", Value: 2, OnClicked: func() {
										sshClientguiwindow.passGBOXm.SetVisible(false)
										sshClientguiwindow.pKeyGBOXm.SetVisible(true)
										sshClientguiwindow.pKandPHm.SetVisible(false)
									}},
									{MaxSize: declarative.Size{Width: 90}, Text: "PK+PasPh", Value: 3, OnClicked: func() {
										sshClientguiwindow.passGBOXm.SetVisible(false)
										sshClientguiwindow.pKeyGBOXm.SetVisible(true)
										sshClientguiwindow.pKandPHm.SetVisible(true)
									}},
								},
							},
							declarative.GroupBox{
								AssignTo: &sshClientguiwindow.passGBOXm,
								Title:    "Login With Password",
								Layout:   declarative.Grid{Columns: 1},
								Children: []declarative.Widget{
									declarative.LineEdit{
										CueBanner:    "Password ...",
										PasswordMode: true,
										Text:         declarative.Bind("PassWord"),
									},
								},
							},
							declarative.GroupBox{
								AssignTo: &sshClientguiwindow.pKeyGBOXm,
								Title:    "Login With Private Key",
								Visible:  false,
								Layout:   declarative.VBox{},
								Children: []declarative.Widget{
									declarative.LineEdit{
										AssignTo:  &sshClientguiwindow.pkLineEd,
										CueBanner: "Private Key File Path ...",
										ReadOnly:  true,
										Text:      declarative.Bind("PreVTKEY"),
									},
									declarative.PushButton{
										Text:        "Open Key File",
										ToolTipText: "open ssh key file",
										OnClicked: func() {
											filePth, err := openPkFile(sshClientguiwindow.dlgSSHAccwin)
											if err != nil {
												walk.MsgBox(sshClientguiwindow.dlgSSHAccwin, "OS file error", fmt.Sprint(err), walk.MsgBoxIconError)
												return
											}
											sshClientguiwindow.pkLineEd.SetText(filePth)
										},
									},
									declarative.LineEdit{
										AssignTo:     &sshClientguiwindow.pKandPHm,
										CueBanner:    "Passphrase for Key ...",
										PasswordMode: true,
										Text:         declarative.Bind("PassPhrase"),
									},
								},
							},
						},
					},
				},
			},
			declarative.Composite{
				Layout: declarative.HBox{},
				Children: []declarative.Widget{
					declarative.HSpacer{},
					declarative.PushButton{
						AssignTo: &sshClientguiwindow.acceptPB,
						Text:     "Connect",
						OnClicked: func() {
							if err := sshClientguiwindow.dbindersshx.Submit(); err != nil {
								return
							}
							if sshstatset.HostAddr == "" {
								sshClientguiwindow.mapLineEd.SetFocus()
								return
							}
							if match, _ := regexp.MatchString(regexSingle, sshstatset.HostAddr); !match {
								walk.MsgBox(sshClientguiwindow.dlgSSHAccwin, "Host syntax error", "Invalid IPv4 or Domain address, format: IPv4|Domain\nExample: slc.snix.ir", walk.MsgBoxIconError)
								return
							}
							if exeErr := exec.Command("cmd", "/c", "start",
								os.Args[0],
								"-auth", fmt.Sprint(sshstatset.AuthMthd),
								"-addr", fmt.Sprintf("%v:%v", sshstatset.HostAddr, sshstatset.HostPort),
								"-user", sshstatset.UserName,
								"-pass", sshstatset.PassWord,
								"-prvk", sshstatset.PreVTKEY,
								"-prph", sshstatset.PassPhrase).Start(); exeErr != nil {
								walk.MsgBox(sshClientguiwindow.dlgSSHAccwin, "Internal System Err", fmt.Sprintf("%v", exeErr), walk.MsgBoxIconError)
								return
							}

						},
					},
					declarative.PushButton{
						AssignTo:  &sshClientguiwindow.cancelPB,
						Text:      "Cancel",
						OnClicked: func() { sshClientguiwindow.dlgSSHAccwin.Cancel() },
					},
				},
			},
		},
	}.Run(owner)
}

func openPkFile(dlgwinad walk.Form) (string, error) {
	openSSHfile := new(walk.FileDialog)
	openSSHfile.Filter = "PEM Files (*.pem)|*.pem|All Files (*.*)|*.*"
	openSSHfile.Title = "Open SSH Key File"
	if okfile, err := openSSHfile.ShowOpen(dlgwinad); err != nil {
		return openSSHfile.FilePath, err
	} else if !okfile {
		return openSSHfile.FilePath, err
	}
	return openSSHfile.FilePath, nil
}

Snix LLC Git Repository Holder Copyright(C) 2022 All Rights Reserved Email To Snix.IR