private static string GetDefaultStore()
        {
            if (PlatformUtils.IsWindows())
            {
                return(StoreNames.WindowsCredentialManager);
            }

            if (PlatformUtils.IsMacOS())
            {
                return(StoreNames.MacOSKeychain);
            }

            // Other platforms have no default store
            return(null);
        }
        private void ValidateGpgPass(out string storeRoot, out string execPath)
        {
            if (!PlatformUtils.IsPosix())
            {
                throw new Exception(
                          $"Can only use the '{StoreNames.Gpg}' credential store on POSIX systems." +
                          Environment.NewLine +
                          $"See {Constants.HelpUrls.GcmCredentialStores} for more information."
                          );
            }

            execPath = GetGpgPath();

            // If we are in a headless environment, and don't have the GPG_TTY or SSH_TTY
            // variables set, then error - we need a TTY device path for pin-entry to work headless.
            if (!_context.SessionManager.IsDesktopSession &&
                !_context.Environment.Variables.ContainsKey("GPG_TTY") &&
                !_context.Environment.Variables.ContainsKey("SSH_TTY"))
            {
                throw new Exception(
                          "GPG_TTY is not set; add `export GPG_TTY=$(tty)` to your profile." +
                          Environment.NewLine +
                          $"See {Constants.HelpUrls.GcmCredentialStores} for more information."
                          );
            }

            // Check for a redirected pass store location
            if (!_context.Settings.TryGetSetting(
                    GpgPassCredentialStore.PasswordStoreDirEnvar,
                    null, null,
                    out storeRoot))
            {
                // Use default store root at ~/.password-store
                storeRoot = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".password-store");
            }

            // Check we have a GPG ID to sign credential files with
            string gpgIdFile = Path.Combine(storeRoot, ".gpg-id");

            if (!_context.FileSystem.FileExists(gpgIdFile))
            {
                throw new Exception(
                          $"Password store has not been initialized at '{storeRoot}'; run `pass init <gpg-id>` to initialize the store." +
                          Environment.NewLine +
                          $"See {Constants.HelpUrls.GcmCredentialStores} for more information."
                          );
            }
        }
        private string GetGitConfigAppPath()
        {
            string path = _appPath;

            // On Windows we must use UNIX style path separators
            if (PlatformUtils.IsWindows())
            {
                path = path.Replace('\\', '/');
            }

            // We must escape escape characters like ' ', '(', and ')'
            return(path
                   .Replace(" ", "\\ ")
                   .Replace("(", "\\(")
                   .Replace(")", "\\)"));;
        }
예제 #4
0
        private static string GetGitPath(IEnvironment environment, IFileSystem fileSystem)
        {
            string programName = PlatformUtils.IsWindows() ? "git.exe" : "git";

            // Use the GIT_EXEC_PATH environment variable if set
            if (environment.Variables.TryGetValue(Constants.EnvironmentVariables.GitExecutablePath,
                                                  out string gitExecPath))
            {
                string candidatePath = Path.Combine(gitExecPath, programName);
                if (fileSystem.FileExists(candidatePath))
                {
                    return(candidatePath);
                }
            }

            // Otherwise try to locate the git(.exe) on the current PATH
            return(environment.LocateExecutable(programName));
        }
예제 #5
0
        protected override async Task <int> RunInternalAsync(string[] args)
        {
            var rootCommand = new RootCommand();

            // Add standard commands
            rootCommand.AddCommand(new GetCommand(Context, _providerRegistry));
            rootCommand.AddCommand(new StoreCommand(Context, _providerRegistry));
            rootCommand.AddCommand(new EraseCommand(Context, _providerRegistry));
            rootCommand.AddCommand(new ConfigureCommand(Context, _configurationService));
            rootCommand.AddCommand(new UnconfigureCommand(Context, _configurationService));

            // Add any custom provider commands
            foreach (ProviderCommand providerCommand in _providerCommands)
            {
                rootCommand.AddCommand(providerCommand);
            }

            // Trace the current version, OS, runtime, and program arguments
            PlatformInformation info = PlatformUtils.GetPlatformInformation();

            Context.Trace.WriteLine($"Version: {Constants.GcmVersion}");
            Context.Trace.WriteLine($"Runtime: {info.ClrVersion}");
            Context.Trace.WriteLine($"Platform: {info.OperatingSystemType} ({info.CpuArchitecture})");
            Context.Trace.WriteLine($"AppPath: {_appPath}");
            Context.Trace.WriteLine($"Arguments: {string.Join(" ", args)}");

            try
            {
                return(await rootCommand.InvokeAsync(args));
            }
            catch (Exception e)
            {
                if (e is AggregateException ae)
                {
                    ae.Handle(WriteException);
                }
                else
                {
                    WriteException(e);
                }

                return(-1);
            }
        }
예제 #6
0
        private static string GetApplicationPath()
        {
            Assembly entryAssembly = Assembly.GetExecutingAssembly();

            if (entryAssembly is null)
            {
                throw new InvalidOperationException();
            }

            string candidatePath = entryAssembly.Location;

            // Strip the .dll from assembly name on Mac and Linux
            if (!PlatformUtils.IsWindows() && Path.HasExtension(candidatePath))
            {
                return(Path.ChangeExtension(candidatePath, null));
            }

            return(candidatePath);
        }
예제 #7
0
        protected override async Task <int> RunInternalAsync(string[] args)
        {
            var rootCommand     = new RootCommand();
            var diagnoseCommand = new DiagnoseCommand(Context);

            // Add standard commands
            rootCommand.AddCommand(new GetCommand(Context, _providerRegistry));
            rootCommand.AddCommand(new StoreCommand(Context, _providerRegistry));
            rootCommand.AddCommand(new EraseCommand(Context, _providerRegistry));
            rootCommand.AddCommand(new ConfigureCommand(Context, _configurationService));
            rootCommand.AddCommand(new UnconfigureCommand(Context, _configurationService));
            rootCommand.AddCommand(diagnoseCommand);

            // Add any custom provider commands
            foreach (ProviderCommand providerCommand in _providerCommands)
            {
                rootCommand.AddCommand(providerCommand);
            }

            // Add any custom provider diagnostic tests
            foreach (IDiagnostic providerDiagnostic in _diagnostics)
            {
                diagnoseCommand.AddDiagnostic(providerDiagnostic);
            }

            // Trace the current version, OS, runtime, and program arguments
            PlatformInformation info = PlatformUtils.GetPlatformInformation();

            Context.Trace.WriteLine($"Version: {Constants.GcmVersion}");
            Context.Trace.WriteLine($"Runtime: {info.ClrVersion}");
            Context.Trace.WriteLine($"Platform: {info.OperatingSystemType} ({info.CpuArchitecture})");
            Context.Trace.WriteLine($"OSVersion: {info.OperatingSystemVersion}");
            Context.Trace.WriteLine($"AppPath: {Context.ApplicationPath}");
            Context.Trace.WriteLine($"Arguments: {string.Join(" ", args)}");

            var parser = new CommandLineBuilder(rootCommand)
                         .UseDefaults()
                         .UseExceptionHandler(OnException)
                         .Build();

            return(await parser.InvokeAsync(args));
        }
        private void ValidateSecretService()
        {
            if (!PlatformUtils.IsLinux())
            {
                throw new Exception(
                          $"Can only use the '{StoreNames.SecretService}' credential store on Linux." +
                          Environment.NewLine +
                          $"See {Constants.HelpUrls.GcmCredentialStores} for more information."
                          );
            }

            if (!_context.SessionManager.IsDesktopSession)
            {
                throw new Exception(
                          $"Cannot use the '{StoreNames.SecretService}' credential backing store without a graphical interface present." +
                          Environment.NewLine +
                          $"See {Constants.HelpUrls.GcmCredentialStores} for more information."
                          );
            }
        }
        private void ValidateWindowsCredentialManager()
        {
            if (!PlatformUtils.IsWindows())
            {
                throw new Exception(
                          $"Can only use the '{StoreNames.WindowsCredentialManager}' credential store on Windows." +
                          Environment.NewLine +
                          $"See {Constants.HelpUrls.GcmCredentialStores} for more information."
                          );
            }

            if (!WindowsCredentialManager.CanPersist())
            {
                throw new Exception(
                          $"Unable to persist credentials with the '{StoreNames.WindowsCredentialManager}' credential store." +
                          Environment.NewLine +
                          $"See {Constants.HelpUrls.GcmCredentialStores} for more information."
                          );
            }
        }
예제 #10
0
        public CommandContext()
        {
            Streams = new StandardStreams();
            Trace   = new Trace();
            Git     = new LibGit2(Trace);

            if (PlatformUtils.IsWindows())
            {
                FileSystem      = new WindowsFileSystem();
                Environment     = new WindowsEnvironment(FileSystem);
                Terminal        = new WindowsTerminal(Trace);
                SessionManager  = new WindowsSessionManager();
                CredentialStore = WindowsCredentialManager.Open();
                SystemPrompts   = new WindowsSystemPrompts();
            }
            else if (PlatformUtils.IsPosix())
            {
                if (PlatformUtils.IsMacOS())
                {
                    FileSystem      = new MacOSFileSystem();
                    SessionManager  = new MacOSSessionManager();
                    CredentialStore = MacOSKeychain.Open();
                    SystemPrompts   = new MacOSSystemPrompts();
                }
                else if (PlatformUtils.IsLinux())
                {
                    throw new NotImplementedException();
                }

                Environment = new PosixEnvironment(FileSystem);
                Terminal    = new PosixTerminal(Trace);
            }

            string repoPath = Git.GetRepositoryPath(FileSystem.GetCurrentDirectory());

            Settings          = new Settings(Environment, Git, repoPath);
            HttpClientFactory = new HttpClientFactory(Trace, Settings, Streams);

            // Set the parent window handle/ID
            SystemPrompts.ParentWindowId = Settings.ParentWindowId;
        }
예제 #11
0
        public override async Task <ICredential> GenerateCredentialAsync(InputArguments input)
        {
            ThrowIfDisposed();

            Uri uri = GetUriFromInput(input);

            // Determine the if the host supports Windows Integration Authentication (WIA)
            if (IsWindowsAuthAllowed)
            {
                if (PlatformUtils.IsWindows())
                {
                    Context.Trace.WriteLine($"Checking host '{uri.AbsoluteUri}' for Windows Integrated Authentication...");
                    bool isWiaSupported = await _winAuth.GetIsSupportedAsync(uri);

                    if (!isWiaSupported)
                    {
                        Context.Trace.WriteLine("Host does not support WIA.");
                    }
                    else
                    {
                        Context.Trace.WriteLine("Host supports WIA - generating empty credential...");

                        // WIA is signaled to Git using an empty username/password
                        return(new GitCredential(string.Empty, string.Empty));
                    }
                }
                else
                {
                    string osType = PlatformUtils.GetPlatformInformation().OperatingSystemType;
                    Context.Trace.WriteLine($"Skipping check for Windows Integrated Authentication on {osType}.");
                }
            }
            else
            {
                Context.Trace.WriteLine("Windows Integrated Authentication detection has been disabled.");
            }

            Context.Trace.WriteLine("Prompting for basic credentials...");
            return(_basicAuth.GetCredentials(uri.AbsoluteUri, uri.UserInfo));
        }
        private void ValidateDpapi(out string storeRoot)
        {
            if (!PlatformUtils.IsWindows())
            {
                throw new Exception(
                          $"Can only use the '{StoreNames.Dpapi}' credential store on Windows." +
                          Environment.NewLine +
                          $"See {Constants.HelpUrls.GcmCredentialStores} for more information."
                          );
            }

            // Check for a redirected credential store location
            if (!_context.Settings.TryGetSetting(
                    Constants.EnvironmentVariables.GcmDpapiStorePath,
                    Constants.GitConfiguration.Credential.SectionName,
                    Constants.GitConfiguration.Credential.DpapiStorePath,
                    out storeRoot))
            {
                // Use default store root at ~/.gcm/dpapi_store
                storeRoot = Path.Combine(_context.FileSystem.UserDataDirectoryPath, "dpapi_store");
            }
        }
예제 #13
0
        /// <summary>
        /// Ensure the store root directory exists. If it does not, create a new directory with
        /// permissions that only permit the owner to read/write/execute. Permissions on an existing
        /// directory are not modified.
        /// </summary>
        private void EnsureStoreRoot()
        {
            if (FileSystem.DirectoryExists(StoreRoot))
            {
                // Don't touch the permissions on the existing directory
                return;
            }

            FileSystem.CreateDirectory(StoreRoot);

            // We only set file system permissions on POSIX platforms
            if (!PlatformUtils.IsPosix())
            {
                return;
            }

            // Set store root permissions such that only the owner can read/write/execute
            var mode = Interop.Posix.Native.NativeFileMode.S_IRUSR |
                       Interop.Posix.Native.NativeFileMode.S_IWUSR |
                       Interop.Posix.Native.NativeFileMode.S_IXUSR;

            // Ignore the return code.. this is a best effort only
            Interop.Posix.Native.Stat.chmod(StoreRoot, mode);
        }
        /// <summary>
        /// Get standard program header title for Git Credential Manager, including the current version and OS information.
        /// </summary>
        /// <returns>Standard program header.</returns>
        public static string GetProgramHeader()
        {
            PlatformInformation info = PlatformUtils.GetPlatformInformation();

            return($"Git Credential Manager version {GcmVersion} ({info.OperatingSystemType}, {info.ClrVersion})");
        }
예제 #15
0
        public CommandContext()
        {
            Streams = new StandardStreams();
            Trace   = new Trace();

            if (PlatformUtils.IsWindows())
            {
                FileSystem     = new WindowsFileSystem();
                SessionManager = new WindowsSessionManager();
                SystemPrompts  = new WindowsSystemPrompts();
                Environment    = new WindowsEnvironment(FileSystem);
                Terminal       = new WindowsTerminal(Trace);
                string gitPath = GetGitPath(Environment, FileSystem);
                Git = new GitProcess(
                    Trace,
                    gitPath,
                    FileSystem.GetCurrentDirectory()
                    );
                Settings        = new Settings(Environment, Git);
                CredentialStore = new WindowsCredentialManager(Settings.CredentialNamespace);
            }
            else if (PlatformUtils.IsMacOS())
            {
                FileSystem     = new MacOSFileSystem();
                SessionManager = new MacOSSessionManager();
                SystemPrompts  = new MacOSSystemPrompts();
                Environment    = new PosixEnvironment(FileSystem);
                Terminal       = new PosixTerminal(Trace);
                string gitPath = GetGitPath(Environment, FileSystem);
                Git = new GitProcess(
                    Trace,
                    gitPath,
                    FileSystem.GetCurrentDirectory()
                    );
                Settings        = new Settings(Environment, Git);
                CredentialStore = new MacOSKeychain(Settings.CredentialNamespace);
            }
            else if (PlatformUtils.IsLinux())
            {
                FileSystem = new LinuxFileSystem();
                // TODO: support more than just 'Posix' or X11
                SessionManager = new PosixSessionManager();
                SystemPrompts  = new LinuxSystemPrompts();
                Environment    = new PosixEnvironment(FileSystem);
                Terminal       = new PosixTerminal(Trace);
                string gitPath = GetGitPath(Environment, FileSystem);
                Git = new GitProcess(
                    Trace,
                    gitPath,
                    FileSystem.GetCurrentDirectory()
                    );
                Settings = new Settings(Environment, Git);
                IGpg gpg = new Gpg(
                    Environment.LocateExecutable("gpg"),
                    SessionManager
                    );
                CredentialStore = new LinuxCredentialStore(FileSystem, Settings, SessionManager, gpg, Environment);
            }
            else
            {
                throw new PlatformNotSupportedException();
            }

            HttpClientFactory = new HttpClientFactory(Trace, Settings, Streams);

            // Set the parent window handle/ID
            SystemPrompts.ParentWindowId = Settings.ParentWindowId;
        }
        public CommandContext(string appPath)
        {
            EnsureArgument.NotNullOrWhiteSpace(appPath, nameof(appPath));

            ApplicationPath = appPath;
            Streams         = new StandardStreams();
            Trace           = new Trace();

            if (PlatformUtils.IsWindows())
            {
                FileSystem     = new WindowsFileSystem();
                SessionManager = new WindowsSessionManager();
                SystemPrompts  = new WindowsSystemPrompts();
                Environment    = new WindowsEnvironment(FileSystem);
                Terminal       = new WindowsTerminal(Trace);
                string gitPath = GetGitPath(Environment, FileSystem, Trace);
                Git = new GitProcess(
                    Trace,
                    Environment,
                    gitPath,
                    FileSystem.GetCurrentDirectory()
                    );
                Settings = new WindowsSettings(Environment, Git, Trace);
            }
            else if (PlatformUtils.IsMacOS())
            {
                FileSystem     = new MacOSFileSystem();
                SessionManager = new MacOSSessionManager();
                SystemPrompts  = new MacOSSystemPrompts();
                Environment    = new PosixEnvironment(FileSystem);
                Terminal       = new MacOSTerminal(Trace);
                string gitPath = GetGitPath(Environment, FileSystem, Trace);
                Git = new GitProcess(
                    Trace,
                    Environment,
                    gitPath,
                    FileSystem.GetCurrentDirectory()
                    );
                Settings = new Settings(Environment, Git);
            }
            else if (PlatformUtils.IsLinux())
            {
                FileSystem = new LinuxFileSystem();
                // TODO: support more than just 'Posix' or X11
                SessionManager = new PosixSessionManager();
                SystemPrompts  = new LinuxSystemPrompts();
                Environment    = new PosixEnvironment(FileSystem);
                Terminal       = new LinuxTerminal(Trace);
                string gitPath = GetGitPath(Environment, FileSystem, Trace);
                Git = new GitProcess(
                    Trace,
                    Environment,
                    gitPath,
                    FileSystem.GetCurrentDirectory()
                    );
                Settings = new Settings(Environment, Git);
            }
            else
            {
                throw new PlatformNotSupportedException();
            }

            HttpClientFactory = new HttpClientFactory(FileSystem, Trace, Settings, Streams);
            CredentialStore   = new CredentialStore(this);

            // Set the parent window handle/ID
            SystemPrompts.ParentWindowId = Settings.ParentWindowId;
        }