internal void Clear()
        {
            var    args   = Settings.GetCommandLineArgs();
            string url    = null;
            bool   forced = false;

            if (args.Length <= 2)
            {
                if (!StandardInputIsTty)
                {
                    _context.Trace.WriteLine("standard input is not TTY, abandoning prompt.");

                    return;
                }

                _context.Trace.WriteLine("prompting user for url.");

                WriteLine(" Target Url:");
                url = In.ReadLine();
            }
            else
            {
                url = args[2];

                if (args.Length > 3)
                {
                    bool.TryParse(args[3], out forced);
                }
            }

            Uri uri;

            if (Uri.TryCreate(url, UriKind.Absolute, out uri))
            {
                _context.Trace.WriteLine($"converted '{url}' to '{uri.AbsoluteUri}'.");

                var operationArguments = new OperationArguments(_context);

                operationArguments.SetTargetUri(uri);

                if (operationArguments.TargetUri is null)
                {
                    var inner = new ArgumentNullException(nameof(operationArguments.TargetUri));
                    throw new ArgumentException(inner.Message, nameof(operationArguments), inner);
                }

                Task.Run(async() =>
                {
                    await LoadOperationArguments(operationArguments);
                    EnableTraceLogging(operationArguments);

                    if (operationArguments.PreserveCredentials && !forced)
                    {
                        _context.Trace.WriteLine("attempting to delete preserved credentials without force, prompting user for interactivity.");

                        if (!StandardInputIsTty || !StandardErrorIsTty)
                        {
                            _context.Trace.WriteLine("standard input is not TTY, abandoning prompt.");
                            return;
                        }

                        WriteLine(" credentials are protected by preserve flag, clear anyways? [Y]es, [N]o.");

                        ConsoleKeyInfo key;
                        while ((key = ReadKey(true)).Key != ConsoleKey.Escape)
                        {
                            if (key.KeyChar == 'N' || key.KeyChar == 'n')
                            {
                                return;
                            }

                            if (key.KeyChar == 'Y' || key.KeyChar == 'y')
                            {
                                break;
                            }
                        }
                    }

                    await DeleteCredentials(operationArguments);
                }).Wait();
            }
            else
            {
                _context.Trace.WriteLine($"unable to parse input '{url}'.");
            }
        }
        internal void Delete()
        {
            string[] args = Settings.GetCommandLineArgs();

            if (args.Length < 3)
            {
                goto error_parse;
            }

            string url = args[2];
            Uri    uri = null;

            if (Uri.IsWellFormedUriString(url, UriKind.Absolute))
            {
                if (!Uri.TryCreate(url, UriKind.Absolute, out uri))
                {
                    goto error_parse;
                }
            }
            else
            {
                url = string.Format("{0}://{1}", Uri.UriSchemeHttps, url);
                if (!Uri.TryCreate(url, UriKind.Absolute, out uri))
                {
                    goto error_parse;
                }
            }

            var operationArguments = new OperationArguments(_context);

            operationArguments.SetTargetUri(uri);

            if (operationArguments.TargetUri is null)
            {
                var inner = new ArgumentNullException(nameof(operationArguments.TargetUri));
                throw new ArgumentException(inner.Message, nameof(operationArguments), inner);
            }

            Task.Run(async() =>
            {
                // Load operation arguments.
                await LoadOperationArguments(operationArguments);
                EnableTraceLogging(operationArguments);

                // Set the parent window handle.
                ParentHwnd = operationArguments.ParentHwnd;

                BaseAuthentication authentication = await CreateAuthentication(operationArguments);

                switch (operationArguments.Authority)
                {
                default:
                case AuthorityType.Basic:
                    _context.Trace.WriteLine($"deleting basic credentials for '{operationArguments.TargetUri}'.");
                    break;

                case AuthorityType.AzureDirectory:
                case AuthorityType.MicrosoftAccount:
                    _context.Trace.WriteLine($"deleting VSTS credentials for '{operationArguments.TargetUri}'.");
                    break;

                case AuthorityType.GitHub:
                    _context.Trace.WriteLine($"deleting GitHub credentials for '{operationArguments.TargetUri}'.");
                    break;

                case AuthorityType.Ntlm:
                    _context.Trace.WriteLine($"deleting NTLM credentials for '{operationArguments.TargetUri}'.");
                    break;

                case AuthorityType.Bitbucket:
                    _context.Trace.WriteLine($"deleting Bitbucket credentials for '{operationArguments.Username}@{operationArguments.TargetUri}'.");
                    break;
                }

                await authentication.DeleteCredentials(operationArguments.TargetUri, operationArguments.Username);
            }).Wait();

            return;

error_parse:
            Die("Unable to parse target URI.");
        }
        internal void Config()
        {
            string[] args = Settings.GetCommandLineArgs();

            // Attempt to parse a target URI from the command line arguments.
            if (args.Length < 3 || !Uri.TryCreate(args[2], UriKind.Absolute, out Uri targetUri))
            {
                targetUri = new Uri("file://localhost");
            }

            // Create operation arguments, and load configuration data.
            var operationArguments = new OperationArguments(_context);

            operationArguments.SetTargetUri(targetUri);

            if (operationArguments.TargetUri is null)
            {
                var inner = new ArgumentNullException(nameof(operationArguments.TargetUri));
                throw new ArgumentException(inner.Message, nameof(operationArguments), inner);
            }

            Task.Run(async() =>
            {
                await LoadOperationArguments(operationArguments);
                EnableTraceLogging(operationArguments);

                // Create a set of irrelevant environment variable entries.
                var irrelevantEntries = new HashSet <string>(StringComparer.OrdinalIgnoreCase)
                {
                    "ToastSettings"
                };

                // Write out the environment variables.
                WriteLine("Environment Variables:");
                foreach (var entry in operationArguments.EnvironmentVariables)
                {
                    // Skip well-known, irrelevant entries.
                    if (irrelevantEntries.Contains(entry.Key))
                    {
                        continue;
                    }

                    WriteLine($"  {entry.Key} = {entry.Value}");
                }
                WriteLine();

                // Write out the Git configuration.
                WriteLine("Git Configuration:");
                foreach (var entry in operationArguments.GitConfiguration)
                {
                    WriteLine($"  [{entry.Level}] {entry.Key} = {entry.Value}");
                }
                WriteLine();

                // Write out the effective settings for GCM.
                WriteLine($"Effective Manager Configuration for {operationArguments.QueryUri.ToString()}:");
                WriteLine($"  Executable = {AssemblyTitle} v{Version.ToString(4)} ({ExecutablePath})");
                WriteLine($"  Authority = {operationArguments.Authority}");
                WriteLine($"  CustomNamespace = {operationArguments.CustomNamespace}");
                WriteLine($"  Interactivity = {operationArguments.Interactivity}");
                WriteLine($"  PreserveCredentials = {operationArguments.PreserveCredentials}");
                WriteLine($"  QueryUri = {operationArguments.QueryUri}");
                WriteLine($"  TargetUri = {operationArguments.TargetUri}");
                WriteLine($"  TokenDuration = {operationArguments.TokenDuration}");
                WriteLine($"  UseConfigLocal = {operationArguments.UseConfigLocal}");
                WriteLine($"  UseConfigSystem = {operationArguments.UseConfigSystem}");
                WriteLine($"  UseHttpPath = {operationArguments.UseHttpPath}");
                WriteLine($"  UseModalUi = {operationArguments.UseModalUi}");
                WriteLine($"  ValidateCredentials = {operationArguments.ValidateCredentials}");
                WriteLine($"  VstsTokenScope = {operationArguments.VstsTokenScope}");
                WriteLine($"  WriteLog = {operationArguments.WriteLog}");
            }).Wait();
        }
Exemple #4
0
        internal void Askpass(string[] args)
        {
            if (args == null || args.Length == 0)
            {
                throw new ArgumentException("Arguments cannot be empty.");
            }

            Gui.UserPromptKind promptKind = Gui.UserPromptKind.SshPassphrase;

            Match match;

            if ((match = AskPasswordRegex.Match(args[0])).Success)
            {
                promptKind = Gui.UserPromptKind.CredentialsPassword;
            }
            else if ((match = AskPassphraseRegex.Match(args[0])).Success)
            {
                promptKind = Gui.UserPromptKind.SshPassphrase;
            }

            if (match.Success)
            {
                _context.Trace.WriteLine("querying for passphrase key.");

                if (match.Groups.Count < 2)
                {
                    throw new ArgumentException("Unable to understand command.");
                }

                // string request = match.Groups[0].Value;
                string resource = match.Groups[1].Value;

                _context.Trace.WriteLine($"open dialog for '{resource}'.");

                // Load operation arguments.
                OperationArguments operationArguments = new OperationArguments(_context);
                Task.Run(async() => await operationArguments.LoadConfiguration()).Wait();

                // Set the parent window handle.
                ParentHwnd = operationArguments.ParentHwnd;

                System.Windows.Application application = new System.Windows.Application();
                Gui.UserPromptDialog       prompt      = new Gui.UserPromptDialog(promptKind, resource, operationArguments.ParentHwnd);
                application.Run(prompt);

                if (!prompt.Failed && !string.IsNullOrEmpty(prompt.Response))
                {
                    string passphase = prompt.Response;

                    _context.Trace.WriteLine("passphase acquired.");

                    Out.Write(passphase + "\n");
                    return;
                }

                Die("failed to interactively acquire credentials.");
            }

            if ((match = AskCredentialRegex.Match(args[0])).Success)
            {
                _context.Trace.WriteLine("querying for basic credentials.");

                if (match.Groups.Count < 3)
                {
                    throw new ArgumentException("Unable to understand command.");
                }

                string seeking   = match.Groups[1].Value;
                string targetUrl = match.Groups[2].Value;

                string username  = string.Empty;
                string password  = string.Empty;
                Uri    targetUri = null;

                // Since we're looking for HTTP(s) credentials, we can use NetFx `Uri` class.
                if (Uri.TryCreate(targetUrl, UriKind.Absolute, out targetUri))
                {
                    _context.Trace.WriteLine($"success parsing URL, targetUri = '{targetUri}'.");

                    if (TryParseUrlCredentials(targetUrl, out username, out password))
                    {
                        if (password != null &&
                            seeking.Equals("Password", StringComparison.OrdinalIgnoreCase))
                        {
                            Out.Write(password + '\n');
                            return;
                        }

                        // print the username if it sought
                        if (seeking.Equals("Username", StringComparison.OrdinalIgnoreCase))
                        {
                            Out.Write(username + '\n');
                            return;
                        }
                    }

                    // create a target Url with the credential portion stripped, because Git doesn't
                    // report hosts with credentials
                    targetUrl = targetUri.Scheme + "://";

                    // Add the username@ portion of the url if it exists
                    if (username != null)
                    {
                        targetUrl += Uri.EscapeDataString(username);

                        targetUrl += '@';
                    }

                    targetUrl += targetUri.Host;

                    // Retain the port if specified.
                    if (!targetUri.IsDefaultPort)
                    {
                        targetUrl += $":{targetUri.Port}";
                    }

                    // Retain the path if specified.
                    if (!string.IsNullOrWhiteSpace(targetUri.LocalPath))
                    {
                        targetUrl += targetUri.LocalPath;
                    }

                    if (Uri.TryCreate(targetUrl, UriKind.Absolute, out targetUri))
                    {
                        _context.Trace.WriteLine($"success parsing URL, targetUri = '{targetUri}'.");

                        var operationArguments = new OperationArguments(_context);
                        operationArguments.SetTargetUri(targetUri);
                        operationArguments.SetCredentials(username ?? string.Empty, password ?? string.Empty);

                        // Load up the operation arguments, enable tracing, and query for credentials.
                        Task.Run(async() =>
                        {
                            await LoadOperationArguments(operationArguments);
                            EnableTraceLogging(operationArguments);

                            Credential credentials;
                            if ((credentials = await QueryCredentials(operationArguments)) != null)
                            {
                                if (seeking.Equals("Username", StringComparison.OrdinalIgnoreCase))
                                {
                                    _context.Trace.WriteLine($"username for '{targetUrl}' asked for and found.");

                                    Out.Write(credentials.Username + '\n');
                                    return;
                                }

                                if (seeking.Equals("Password", StringComparison.OrdinalIgnoreCase))
                                {
                                    _context.Trace.WriteLine($"password for '{targetUrl}' asked for and found.");

                                    Out.Write(credentials.Password + '\n');
                                    return;
                                }
                            }
                            else
                            {
                                _context.Trace.WriteLine($"user cancelled credential dialog.");
                                return;
                            }
                        }).Wait();
                    }
                    else
                    {
                        _context.Trace.WriteLine("error: unable to parse target URL.");
                    }
                }
                else
                {
                    _context.Trace.WriteLine("error: unable to parse supplied URL.");
                }

                Die($"failed to detect {seeking} in target URL.");
            }

            if ((match = AskAuthenticityRegex.Match(args[0])).Success)
            {
                string host        = match.Groups[1].Value;
                string fingerprint = match.Groups[2].Value;

                _context.Trace.WriteLine($"requesting authorization to add {host} ({fingerprint}) to known hosts.");

                // Load operation arguments.
                OperationArguments operationArguments = new OperationArguments(_context);
                Task.Run(async() => await operationArguments.LoadConfiguration()).Wait();

                // Set the parent window handle.
                ParentHwnd = operationArguments.ParentHwnd;

                System.Windows.Application application = new System.Windows.Application();
                Gui.UserPromptDialog       prompt      = new Gui.UserPromptDialog(host, fingerprint, operationArguments.ParentHwnd);
                application.Run(prompt);

                if (prompt.Failed)
                {
                    _context.Trace.WriteLine("denied authorization of host.");
                    Out.Write("no\n");
                }
                else
                {
                    _context.Trace.WriteLine("approved authorization of host.");
                    Out.Write("yes\n");
                }

                return;
            }

            Die("failed to acquire credentials.");
        }