예제 #1
0
        private async void OnConnect(object obj)
        {
            if (GoldDrives.Count == 0 || string.IsNullOrEmpty(SelectedDrive.Host))
            {
                if (SelectedDrive != null)
                {
                    var drive = FreeDrives.ToList().Find(x => x.Name == SelectedDrive.Name);
                    if (drive == null)
                    {
                        FreeDrives.Add(SelectedDrive);
                    }
                    SelectedFreeDrive = SelectedDrive;
                }
                CurrentPage = Page.Host;
                return;
            }
            if (ConnectButtonText == "Connect")
            {
                ConnectAsync(SelectedDrive);
            }
            else
            {
                WorkStart("Disconnecting...");
                ReturnBox r = await Task.Run(() => _mountService.Unmount(SelectedDrive));

                WorkDone(r);
            }
        }
예제 #2
0
        public ReturnBox RunLocal(string cmd, string args,
                                  int timeout_secs = 30)
        {
            Logger.Log($"Running local command: {cmd} {args}");
            ReturnBox        r         = new ReturnBox();
            Process          process   = new Process();
            ProcessStartInfo startInfo = new ProcessStartInfo
            {
                WindowStyle            = ProcessWindowStyle.Hidden,
                CreateNoWindow         = true,
                RedirectStandardError  = true,
                RedirectStandardOutput = true,
                UseShellExecute        = false,
                FileName  = cmd,
                Arguments = args
            };

            process.StartInfo = startInfo;
            process.Start();
            process.WaitForExit(timeout_secs * 1000);
            r.Output   = process.StandardOutput.ReadToEnd();
            r.Error    = process.StandardError.ReadToEnd();
            r.ExitCode = process.ExitCode;
            r.Success  = r.ExitCode == 0;
            return(r);
        }
예제 #3
0
        ReturnBox TestPassword(Drive drive, string password)
        {
            ReturnBox r = new ReturnBox();

            if (string.IsNullOrEmpty(password))
            {
                r.MountStatus = MountStatus.BAD_PASSWORD;
                r.Error       = "Empty password";
                return(r);
            }
            try
            {
                SshClient client = new SshClient(drive.Host, drive.Port, drive.User, password);
                client.ConnectionInfo.Timeout = TimeSpan.FromSeconds(5);
                client.Connect();
                client.Disconnect();
                r.MountStatus = MountStatus.OK;
            }
            catch (Exception ex)
            {
                r.Error = ex.Message;
                if (ex is SshAuthenticationException)
                {
                    r.MountStatus = MountStatus.BAD_PASSWORD;
                }
                else if (ex is SocketException)
                {
                    r.MountStatus = MountStatus.BAD_HOST;
                }
                else
                {
                }
            }
            return(r);
        }
예제 #4
0
        public ReturnBox TestHost(Drive drive)
        {
            ReturnBox r = new ReturnBox();

            try
            {
                using (var client = new TcpClient())
                {
                    var result = client.BeginConnect(drive.Host,
                                                     drive.CurrentPort, null, null);
                    var success = result.AsyncWaitHandle.WaitOne(TimeSpan.FromSeconds(5));
                    if (!success)
                    {
                        throw new Exception("Timeout. Server unknown or does not respond.");
                    }
                    else
                    {
                        if (client.Connected)
                        {
                            r.MountStatus = MountStatus.OK;
                            r.Success     = true;
                        }
                    }
                    client.EndConnect(result);
                }
            }
            catch (Exception ex)
            {
                r.MountStatus = MountStatus.BAD_HOST;
                r.Error       = ex.Message;
            }

            return(r);
        }
예제 #5
0
        public ReturnBox TestHost(Drive drive)
        {
            ReturnBox r = new ReturnBox();

            try
            {
                using (var client = new TcpClient())
                {
                    var result  = client.BeginConnect(drive.Host, drive.Port, null, null);
                    var success = result.AsyncWaitHandle.WaitOne(5000);
                    if (!success)
                    {
                        r.MountStatus = MountStatus.BAD_HOST;
                    }
                    client.EndConnect(result);
                }
            }
            catch (Exception ex)
            {
                r.MountStatus = MountStatus.BAD_HOST;
                r.Error       = ex.Message;
            }
            r.MountStatus = MountStatus.OK;
            return(r);
        }
예제 #6
0
        string GenerateKeys(Drive drive)
        {
            string pubkey = "";

            try
            {
                string dotssh = $@"{drive.UserProfile}\.ssh";
                if (!Directory.Exists(dotssh))
                {
                    Directory.CreateDirectory(dotssh);
                }
                if (!File.Exists(drive.AppKey))
                {
                    ReturnBox r = RunLocal($@"""{AppPath}\ssh-keygen.exe""", $@"-N """" -f ""{drive.AppKey}""");
                }
                if (File.Exists(drive.AppPubKey))
                {
                    pubkey = File.ReadAllText(drive.AppPubKey).Trim();
                }
                else
                {
                    ReturnBox r = RunLocal($@"""{AppPath}\ssh-keygen.exe""", $@"-y -f ""{drive.AppKey}""");
                    pubkey = r.Output;
                }

                // TODO: set permissons
            }
            catch (Exception ex)
            {
                Logger.Log("Error generating keys: " + ex.Message);
            }
            return(pubkey);
        }
예제 #7
0
        ReturnBox TestPassword(Drive drive, string password)
        {
            ReturnBox r = new ReturnBox();

            if (string.IsNullOrEmpty(password))
            {
                r.MountStatus = MountStatus.BAD_PASSWORD;
                r.Error       = "Empty password";
                return(r);
            }
            try
            {
                SshClient client = new SshClient(drive.Host, drive.CurrentPort, drive.CurrentUser, password);
                client.ConnectionInfo.Timeout = TimeSpan.FromSeconds(TIMEOUT);
                client.Connect();
                client.Disconnect();
                r.MountStatus = MountStatus.OK;
            }
            catch (Exception ex)
            {
                r.Error = string.Format($"Failed to connect to { drive.CurrentUser}@{drive.Host}:{drive.CurrentPort}.\nError: {ex.Message}");
                if (ex is SshAuthenticationException)
                {
                    r.MountStatus = MountStatus.BAD_PASSWORD;
                }
                else if (ex is SocketException)
                {
                    r.MountStatus = MountStatus.BAD_HOST;
                }
                else
                {
                }
            }
            return(r);
        }
예제 #8
0
        private async void OnConnect(object obj)
        {
            if (IsWorking)
            {
                return;
            }

            Message = "";

            if (GoldDriveList.Count == 0 || string.IsNullOrEmpty(SelectedDrive.Host))
            {
                IsDriveNew    = true;
                SelectedDrive = FreeDriveList.First();
                CurrentPage   = Page.Host;
                return;
            }
            if (ConnectButtonText == "Connect")
            {
                ConnectAsync(SelectedDrive);
            }
            else
            {
                WorkStart("Disconnecting...");
                ReturnBox r = await Task.Run(() => _mountService.Unmount(SelectedDrive));

                WorkDone(r);
            }
        }
예제 #9
0
        private async void ConnectAsync(Drive drive)
        {
            WorkStart("Connecting");
            ReturnBox r = await Task.Run(() => _mountService.Connect(drive));

            WorkDone(r);
        }
예제 #10
0
        protected override void OnStartup(StartupEventArgs e)
        {
            base.OnStartup(e);

            //string apppath = System.Reflection.Assembly.GetEntryAssembly().Location;
            //string appdir = System.IO.Path.GetDirectoryName(apppath);
            //string args = "";
            bool ok = false;
            //Drive drive = null;
            ReturnBox rb = null;

            //MountService ms = new MountService();

            //if (e.Args.Length > 0)
            //{
            //    args = string.Join(" ", e.Args);
            //    Logger.Log($"Starting app: {apppath} {args}");
            //    // process args
            //    // golddrive.exe z: \\golddrive\host\path -ouid=-1,gid=-1
            //    drive = ms.GetDriveFromArgs(args);

            //    // check ssh auth
            //    rb = ms.TestSsh(drive);
            //    if (rb.MountStatus == MountStatus.OK)
            //    {
            //        ok = true;
            //    }
            //    //else
            //    //{
            //    //    rb = ms.TestSsh(drive, drive.UserKey);
            //    //    if (rb.MountStatus == MountStatus.OK)
            //    //    {
            //    //        rb = ms.SetupSshWithUserKey(drive, drive.UserKey);
            //    //        ok = rb.MountStatus == MountStatus.OK;
            //    //    }
            //    //}
            //}

            //if (ok)
            //{
            //    //string cmd = $"{appdir}\\golddrive.exe";
            //    //Logger.Log($"Starting cli: {cmd} {args}");
            //    //Process.Start(cmd, args);
            //    //Process.Start("net.exe", "use " + args);
            //    rb = ms.Connect(drive);
            //    if (rb.MountStatus != MountStatus.OK)
            //    {
            //        drive.Status = rb.DriveStatus;
            //        ok = false;
            //    }
            //}

            if (!ok)
            {
                new MainWindow(rb).ShowDialog();
            }

            this.Shutdown();
        }
예제 #11
0
        private async void OnConnectPassword(object obj)
        {
            CurrentPage = Page.Main;
            WorkStart("Connecting");
            ReturnBox r = await Task.Run(() => _mountService.ConnectPassword(SelectedDrive, password));

            WorkDone(r);
        }
예제 #12
0
        //public string GetVolumeName(string letter)
        //{
        //    var r = RunLocal($"vol {letter}:");
        //    foreach (var line in r.Output.Split('\n'))
        //    {
        //        try
        //        {
        //            Match match = Regex.Match(line, $@"^\s*Volume in drive {letter} is ([^ ]+)");
        //            if (match.Success)
        //                return match.Groups[1].Value.Trim();
        //        }
        //        catch (Exception ex)
        //        {

        //        }
        //    }
        //    return "";
        //}

        public ReturnBox CheckDriveStatus(Drive drive)
        {
            ReturnBox r = new ReturnBox
            {
                MountStatus = MountStatus.OK
            };

            if (drive == null ||
                (drive.Letter.ToCharArray()[0] < 'G' || drive.Letter.ToCharArray()[0] > 'Z'))
            {
                r.DriveStatus = DriveStatus.NOT_SUPPORTED;
            }
            else
            {
                Settings settings = LoadSettings();
                UpdateDrives(settings);
                var free         = FreeDrives.Find(x => x.Letter == drive.Letter) != null;
                var isGold       = GoldDrives.Find(x => x.Letter == drive.Letter) != null;
                var disconnected = GoldDrives.Find(x => x.Letter == drive.Letter && x.Status == DriveStatus.DISCONNECTED) != null;
                var pathUsed     = GoldDrives.Find(x => x.Letter != drive.Letter && x.MountPoint == drive.MountPoint &&
                                                   (x.Status != DriveStatus.DISCONNECTED &&
                                                    x.Status != DriveStatus.FREE)) != null;

                if (pathUsed)
                {
                    r.MountStatus = MountStatus.BAD_DRIVE;
                    r.DriveStatus = DriveStatus.MOUNTPOINT_IN_USE;
                    r.Error       = "Mount point in use";
                }
                else if (free)
                {
                    r.DriveStatus = DriveStatus.DISCONNECTED;
                }
                else if (disconnected)
                {
                    r.DriveStatus = DriveStatus.DISCONNECTED;
                }
                else if (!isGold)
                {
                    r.MountStatus = MountStatus.BAD_DRIVE;
                    r.DriveStatus = DriveStatus.IN_USE;
                    r.Error       = "Drive in use";
                }
                else if (!CheckIfDriveWorks(drive))
                {
                    r.MountStatus = MountStatus.BAD_DRIVE;
                    r.DriveStatus = DriveStatus.BROKEN;
                    r.Error       = "Drive is broken";
                }
                else
                {
                    r.DriveStatus = DriveStatus.CONNECTED;
                }
            }
            r.Drive = drive;
            return(r);
        }
예제 #13
0
        public MainWindowViewModel(ReturnBox rb)
        {
            _mountService = new MountService();
            //SelectedDrive = drive;

            //Messenger.Default.Register<string>(this, OnShowView);
            CurrentPage = Page.Main;
            LoadDrivesAsync();
            GetVersions();
        }
예제 #14
0
        private async void CheckDriveStatusAsync()
        {
            if (SelectedDrive != null)
            {
                WorkStart("Checking status...");
                ReturnBox r = await Task.Run(() => _mountService.CheckDriveStatus(SelectedDrive));

                WorkDone(r);
            }
        }
예제 #15
0
        private async void ConnectAsync(Drive drive)
        {
            WorkStart("Connecting...");
            var       status = new Progress <string>(ReportStatus);
            ReturnBox r      = await Task.Run(() => _mountService.Connect(drive, status));

            SkipComboChanged = true;
            UpdateObservableDrives();
            SkipComboChanged = false;
            WorkDone(r);
        }
예제 #16
0
        public ReturnBox SetupSsh(Drive drive, string password)
        {
            ReturnBox r = new ReturnBox();

            try
            {
                string pubkey = "";
                if (File.Exists(drive.AppKey) && File.Exists(drive.AppPubKey))
                {
                    pubkey = File.ReadAllText(drive.AppPubKey);
                }
                else
                {
                    pubkey = GenerateKeys(drive);
                }

                SshClient client = new SshClient(drive.Host, drive.CurrentPort, drive.CurrentUser, password);
                client.ConnectionInfo.Timeout = TimeSpan.FromSeconds(TIMEOUT);
                client.Connect();
                string cmd   = "";
                bool   linux = !client.ConnectionInfo.ServerVersion.ToLower().Contains("windows");
                if (linux)
                {
                    cmd = $"exec sh -c \"cd; mkdir -p .ssh; chmod 700 .ssh; touch .ssh/authorized_keys; chmod 744 .ssh/authorized_keys; echo '{pubkey}' >> .ssh/authorized_keys; chmod 644 .ssh/authorized_keys\"";
                }
                else
                {
                    ////cmd = "if not exists .ssh mkdir .ssh && ";
                    //cmd = $"echo {pubkey.Trim()} >> .ssh\\authorized_keys && ";
                    //cmd += $"icacls .ssh\\authorized_keys /inheritance:r && ";
                    //cmd += $"icacls .ssh\\authorized_keys /grant {drive.User}:f &&";
                    //cmd += $"icacls .ssh\\authorized_keys /grant SYSTEM:f";
                }
                SshCommand command = client.CreateCommand(cmd);
                command.CommandTimeout = TimeSpan.FromSeconds(TIMEOUT);
                r.Output   = command.Execute();
                r.Error    = command.Error;
                r.ExitCode = command.ExitStatus;
            }
            catch (Exception ex)
            {
                r.Error = ex.Message;
                return(r);
            }

            r = TestSsh(drive);
            if (r.MountStatus != MountStatus.OK)
            {
                return(r);
            }

            return(r);
        }
예제 #17
0
        public MainWindowViewModel(ReturnBox rb)
        {
            _mountService = new MountService();
            //Messenger.Default.Register<string>(this, OnShowView);

            CurrentPage = Page.Main;
            LoadDrivesAsync();
            GetVersionsAsync();
            if (rb != null)
            {
                Message = rb.Error;
            }
        }
예제 #18
0
        public ReturnBox ConnectPassword(Drive drive, string password)
        {
            ReturnBox r = TestPassword(drive, password);

            if (r.MountStatus != MountStatus.OK)
            {
                return(r);
            }

            r = SetupSshWithPassword(drive, password);
            if (r.MountStatus != MountStatus.OK)
            {
                return(r);
            }

            return(Mount(drive));
        }
예제 #19
0
        private async void OnConnectPassword(object obj)
        {
            if (SelectedDrive == null)
            {
                Message = "Invalid drive";
                return;
            }

            WorkStart("Connecting...");
            var       status = new Progress <string>(ReportStatus);
            ReturnBox r      = await Task.Run(() => _mountService.ConnectPassword(SelectedDrive, password, status));

            SkipComboChanged = true;
            UpdateObservableDrives();
            SkipComboChanged = false;
            WorkDone(r);
        }
예제 #20
0
        public ReturnBox ConnectPassword(Drive drive, string password, IProgress <string> status)
        {
            status?.Report("Connecting...");
            ReturnBox r = TestPassword(drive, password);

            if (r.MountStatus != MountStatus.OK)
            {
                return(r);
            }
            status?.Report("Generating ssh keys...");
            r = SetupSsh(drive, password);
            if (r.MountStatus != MountStatus.OK)
            {
                return(r);
            }
            status?.Report("Mouting drive...");
            return(Mount(drive));
        }
예제 #21
0
        public ReturnBox SetupSshWithPassword(Drive drive, string password)
        {
            ReturnBox r = new ReturnBox();

            try
            {
                string pubkey = "";
                if (File.Exists(drive.AppKey) && File.Exists(drive.AppPubKey))
                {
                    pubkey = File.ReadAllText(drive.AppPubKey);
                }
                else
                {
                    pubkey = GenerateKeys(drive);
                }
                SshClient client = new SshClient(drive.Host, drive.Port, drive.User, password);
                client.ConnectionInfo.Timeout = TimeSpan.FromSeconds(5);
                client.Connect();
                string cmd = "";
                //bool linux = false;
                //if(linux)
                cmd = $"exec sh -c \"cd; umask 077; mkdir -p .ssh; echo '{pubkey}' >> .ssh/authorized_keys\"";
                //else
                //    cmd = $"mkdir %USERPROFILE%\\.ssh 2>NUL || echo {pubkey.Trim()} >> %USERPROFILE%\\.ssh\\authorized_keys";
                SshCommand command = client.CreateCommand(cmd);
                command.CommandTimeout = TimeSpan.FromSeconds(5);
                r.Output   = command.Execute();
                r.Error    = command.Error;
                r.ExitCode = command.ExitStatus;
            }
            catch (Exception ex)
            {
                r.Error = ex.Message;
                return(r);
            }

            r = TestSsh(drive, drive.AppKey);
            if (r.MountStatus != MountStatus.OK)
            {
                return(r);
            }

            return(r);
        }
예제 #22
0
        private void WorkDone(ReturnBox r = null)
        {
            IsWorking = false;

            if (r == null)
            {
                Message = "";
                return;
            }
            DriveStatus = r.DriveStatus;
            MountStatus = r.MountStatus;
            Message     = r.Error;

            switch (r.MountStatus)
            {
            case MountStatus.BAD_CLI:
            case MountStatus.BAD_WINFSP:
            case MountStatus.BAD_DRIVE:
                CurrentPage = Page.Main;
                break;

            case MountStatus.BAD_HOST:
                CurrentPage = Page.Host;
                OnFocusRequested(nameof(SelectedDrive.Host));
                break;

            case MountStatus.BAD_PASSWORD:
            case MountStatus.BAD_KEY:
                CurrentPage = Page.Password;
                OnFocusRequested(nameof(Password));
                break;

            case MountStatus.OK:
                CurrentPage = Page.Main;
                Message     = r.DriveStatus.ToString();
                NotifyPropertyChanged("HasDrives");
                break;

            default:
                break;
            }
            IsWorking = false;
        }
예제 #23
0
        private void WorkDone(ReturnBox r = null)
        {
            IsWorking = false;
            if (r == null)
            {
                Message = "";
                return;
            }
            DriveStatus = r.DriveStatus;
            MountStatus = r.MountStatus;
            switch (r.MountStatus)
            {
            case MountStatus.BAD_DRIVE:
            case MountStatus.BAD_HOST:
                CurrentPage = Page.Host;
                Message     = r.Error;
                break;

            case MountStatus.BAD_PASSWORD:
            case MountStatus.BAD_KEY:
                CurrentPage = Page.Password;
                Message     = r.Error;
                break;

            case MountStatus.BAD_WINFSP:
                Message = "Winfsp is not installed\n";
                break;

            case MountStatus.OK:
                CurrentPage = Page.Main;
                Message     = r.DriveStatus.ToString();
                UpdateObservableDrives(r.Drive);
                NotifyPropertyChanged("HasDrives");
                break;

            default:
                //Message = DriveStatus.UNKNOWN.ToString();
                break;
            }
            IsWorking = false;
        }
예제 #24
0
        public ReturnBox Unmount(Drive drive)
        {
            ReturnBox r = RunLocal("net.exe", "use /d " + drive.Name);

            if (!r.Success)
            {
                r.Error = r.Error;
                r.Drive = drive;
                return(r);
            }
            // TODO: clenup drive name and registry
            CleanExplorerDriveLabel(drive);
            Settings settings = LoadSettings();

            SaveSettings(settings);
            UpdateDrives(settings);
            r.MountStatus = MountStatus.OK;
            r.DriveStatus = DriveStatus.DISCONNECTED;
            r.Drive       = drive;
            return(r);
        }
예제 #25
0
        public ReturnBox DownloadFile(string src, string dst)
        {
            ReturnBox r = new ReturnBox();

            if (Connected)
            {
                try
                {
                    using (Stream fs = File.Create(dst))
                    {
                        Sftp.DownloadFile(src, fs);
                    }
                    r.Success = true;
                }
                catch (Exception ex)
                {
                    r.Error = ex.Message;
                }
            }
            return(r);
        }
예제 #26
0
        public ReturnBox RunRemote(string cmd, int timeout_secs = 3600)
        {
            ReturnBox r = new ReturnBox();

            if (Connected)
            {
                try
                {
                    SshCommand command = Ssh.CreateCommand(cmd);
                    command.CommandTimeout = TimeSpan.FromSeconds(timeout_secs);
                    r.Output   = command.Execute();
                    r.Error    = command.Error;
                    r.ExitCode = command.ExitStatus;
                }
                catch (Exception ex)
                {
                    r.Error = ex.Message;
                }
            }
            r.Success = r.ExitCode == 0 && String.IsNullOrEmpty(r.Error);
            return(r);
        }
예제 #27
0
        public ReturnBox Mount(Drive drive)
        {
            ReturnBox r = RunLocal("net.exe", $"use { drive.Name } { drive.Remote } /persistent:yes");

            if (!r.Success)
            {
                r.MountStatus = MountStatus.UNKNOWN;
                r.Drive       = drive;
                return(r);
            }
            SetExplorerDriveLabel(drive);
            SetDriveIcon(drive, $@"{ AppPath }\golddrive.ico");
            Settings settings = LoadSettings();

            settings.AddDrive(drive);
            SaveSettings(settings);
            UpdateDrives(settings);
            r.MountStatus = MountStatus.OK;
            r.DriveStatus = DriveStatus.CONNECTED;
            r.Drive       = drive;
            return(r);
        }
예제 #28
0
        public ReturnBox UploadFile(string src, string dir, string filename)
        {
            ReturnBox r = new ReturnBox();

            if (Connected)
            {
                try
                {
                    using (var fs = new FileStream(src, FileMode.Open))
                    {
                        Sftp.BufferSize = 4 * 1024; // bypass Payload error large files
                        Sftp.ChangeDirectory(dir);
                        Sftp.UploadFile(fs, filename, true);
                    }
                    r.Success = true;
                }
                catch (Exception ex)
                {
                    r.Error = ex.Message;
                }
            }
            return(r);
        }
예제 #29
0
        public ReturnBox Connect(Drive drive, IProgress <string> status)
        {
            ReturnBox r = new ReturnBox();

            if (!IsWinfspInstalled())
            {
                r.MountStatus = MountStatus.BAD_WINFSP;
                r.Error       = "Winfsp is not installed\n";
                return(r);
            }
            if (!IsCliInstalled())
            {
                r.MountStatus = MountStatus.BAD_CLI;
                r.Error       = "Goldrive CLI is not installed\n";
                return(r);
            }
            r = CheckDriveStatus(drive);
            if (r.DriveStatus != DriveStatus.DISCONNECTED)
            {
                r.MountStatus = MountStatus.BAD_DRIVE;
                return(r);
            }
            status?.Report("Checking server...");
            r = TestHost(drive);
            if (r.MountStatus != MountStatus.OK)
            {
                return(r);
            }
            status?.Report("Authenticating...");
            r = TestSsh(drive);
            if (r.MountStatus != MountStatus.OK)
            {
                return(r);
            }
            status?.Report("Mounting drive...");
            return(Mount(drive));
        }
예제 #30
0
        public ReturnBox Connect(Drive drive)
        {
            ReturnBox r = new ReturnBox();

            if (!IsWinfspInstalled())
            {
                r.MountStatus = MountStatus.BAD_WINFSP;
                return(r);
            }
            r = CheckDriveStatus(drive);
            if (r.DriveStatus != DriveStatus.DISCONNECTED)
            {
                r.MountStatus = MountStatus.BAD_DRIVE;
                r.Error       = r.DriveStatus.ToString();
                return(r);
            }
            r = TestSsh(drive, drive.AppKey);
            if (r.MountStatus != MountStatus.OK)
            {
                return(r);
            }

            return(Mount(drive));
        }