public static extern SafeFileHandle CreateFile(
     string lpFileName,
     [MarshalAs(UnmanagedType.U4)] NativeMethods.FileAccess dwDesiredAccess,
     [MarshalAs(UnmanagedType.U4)] NativeMethods.FileShare dwShareMode,
     IntPtr lpSecurityAttributes,
     [MarshalAs(UnmanagedType.U4)] NativeMethods.CreationDisposition dwCreationDisposition,
     [MarshalAs(UnmanagedType.U4)] NativeMethods.FileAttributes dwFlagsAndAttributes,
     IntPtr hTemplateFile);
예제 #2
0
        public static bool AuthCodePrompt(Program program, TargetUri targetUri, Github.GitHubAuthenticationResultType resultType, string username, out string authenticationCode)
        {
            // ReadConsole 32768 fail, 32767 ok @linquize [https://github.com/Microsoft/Git-Credential-Manager-for-Windows/commit/a62b9a19f430d038dcd85a610d97e5f763980f85]
            const int BufferReadSize = 16 * 1024;

            Debug.Assert(targetUri != null);

            StringBuilder buffer  = new StringBuilder(BufferReadSize);
            uint          read    = 0;
            uint          written = 0;

            authenticationCode = null;

            NativeMethods.FileAccess              fileAccessFlags         = NativeMethods.FileAccess.GenericRead | NativeMethods.FileAccess.GenericWrite;
            NativeMethods.FileAttributes          fileAttributes          = NativeMethods.FileAttributes.Normal;
            NativeMethods.FileCreationDisposition fileCreationDisposition = NativeMethods.FileCreationDisposition.OpenExisting;
            NativeMethods.FileShare fileShareFlags = NativeMethods.FileShare.Read | NativeMethods.FileShare.Write;

            using (SafeFileHandle stdout = NativeMethods.CreateFile(NativeMethods.ConsoleOutName, fileAccessFlags, fileShareFlags, IntPtr.Zero, fileCreationDisposition, fileAttributes, IntPtr.Zero))
                using (SafeFileHandle stdin = NativeMethods.CreateFile(NativeMethods.ConsoleInName, fileAccessFlags, fileShareFlags, IntPtr.Zero, fileCreationDisposition, fileAttributes, IntPtr.Zero))
                {
                    string type = resultType == Github.GitHubAuthenticationResultType.TwoFactorApp
                    ? "app"
                    : "sms";

                    Git.Trace.WriteLine($"2fa type = '{type}'.");

                    buffer.AppendLine()
                    .Append("authcode (")
                    .Append(type)
                    .Append("): ");

                    if (!NativeMethods.WriteConsole(stdout, buffer, (uint)buffer.Length, out written, IntPtr.Zero))
                    {
                        int error = Marshal.GetLastWin32Error();
                        throw new Win32Exception(error, "Unable to write to standard output (" + NativeMethods.Win32Error.GetText(error) + ").");
                    }
                    buffer.Clear();

                    // read input from the user
                    if (!NativeMethods.ReadConsole(stdin, buffer, BufferReadSize, out read, IntPtr.Zero))
                    {
                        int error = Marshal.GetLastWin32Error();
                        throw new Win32Exception(error, "Unable to read from standard input (" + NativeMethods.Win32Error.GetText(error) + ").");
                    }

                    authenticationCode = buffer.ToString(0, (int)read);
                    authenticationCode = authenticationCode.Trim(Program.NewLineChars);
                }

            return(authenticationCode != null);
        }
예제 #3
0
        /// <summary>
        /// Removes read only attribute from file or directory if it has one
        /// </summary>
        /// <param name="filename"></param>
        /// <param name="currentAttributes"></param>
        private static unsafe void RemoveReadonlyAttribute(string filename, NativeMethods.FileAttributes currentAttributes)
        {
            NativeMethods.FileAttributes attributesToRemove = NativeMethods.FileAttributes.Readonly;

            if (((uint)currentAttributes & (uint)attributesToRemove) != 0)
            {
                var newAttributes = (uint)(currentAttributes & (~attributesToRemove));

                if (!NativeMethods.SetFileAttributesW(EnsureFileName(filename), newAttributes))
                {
                    ThrowLastErrorException("Failed to remove {0} attribute on {1}", (currentAttributes & attributesToRemove), filename);
                }
            }
        }
예제 #4
0
        public override Stream OpenFileStream(string path, FileMode fileMode, FileAccess fileAccess, NativeMethods.FileAttributes attributes, FileShare shareMode)
        {
            MockFile file = this.RootDirectory.FindFile(path);

            if (fileMode == FileMode.OpenOrCreate)
            {
                if (file == null)
                {
                    return(this.CreateAndOpenFileStream(path));
                }
            }
            else
            {
                file.ShouldNotBeNull();
            }

            return(file.GetContentStream());
        }
예제 #5
0
 public override Stream OpenFileStream(string path, FileMode fileMode, FileAccess fileAccess, NativeMethods.FileAttributes attributes, FileShare shareMode)
 {
     return(new MemoryStream());
 }
        public static Credential CredentialPrompt(Program program, TargetUri targetUri, string titleMessage)
        {
            // ReadConsole 32768 fail, 32767 OK @linquize [https://github.com/Microsoft/Git-Credential-Manager-for-Windows/commit/a62b9a19f430d038dcd85a610d97e5f763980f85]
            const int BufferReadSize = 16 * 1024;

            if (program is null)
            {
                throw new ArgumentNullException(nameof(program));
            }
            if (targetUri is null)
            {
                throw new ArgumentNullException(nameof(targetUri));
            }

            titleMessage = titleMessage ?? "Please enter your credentials for ";

            StringBuilder buffer  = new StringBuilder(BufferReadSize);
            uint          read    = 0;
            uint          written = 0;

            NativeMethods.ConsoleMode             consoleMode             = 0;
            NativeMethods.FileAccess              fileAccessFlags         = NativeMethods.FileAccess.GenericRead | NativeMethods.FileAccess.GenericWrite;
            NativeMethods.FileAttributes          fileAttributes          = NativeMethods.FileAttributes.Normal;
            NativeMethods.FileCreationDisposition fileCreationDisposition = NativeMethods.FileCreationDisposition.OpenExisting;
            NativeMethods.FileShare fileShareFlags = NativeMethods.FileShare.Read | NativeMethods.FileShare.Write;

            using (SafeFileHandle stdout = NativeMethods.CreateFile(NativeMethods.ConsoleOutName, fileAccessFlags, fileShareFlags, IntPtr.Zero, fileCreationDisposition, fileAttributes, IntPtr.Zero))
                using (SafeFileHandle stdin = NativeMethods.CreateFile(NativeMethods.ConsoleInName, fileAccessFlags, fileShareFlags, IntPtr.Zero, fileCreationDisposition, fileAttributes, IntPtr.Zero))
                {
                    // Read the current console mode.
                    if (stdin.IsInvalid || stdout.IsInvalid)
                    {
                        program.Trace.WriteLine("not a tty detected, abandoning prompt.");
                        return(null);
                    }
                    else if (!NativeMethods.GetConsoleMode(stdin, out consoleMode))
                    {
                        int error = Marshal.GetLastWin32Error();
                        throw new Win32Exception(error, "Unable to determine console mode (" + NativeMethods.Win32Error.GetText(error) + ").");
                    }

                    program.Trace.WriteLine($"console mode = '{consoleMode}'.");

                    string username = null;
                    string password = null;

                    // Instruct the user as to what they are expected to do.
                    buffer.Append(titleMessage)
                    .Append(targetUri)
                    .AppendLine();
                    if (!NativeMethods.WriteConsole(stdout, buffer, (uint)buffer.Length, out written, IntPtr.Zero))
                    {
                        int error = Marshal.GetLastWin32Error();
                        throw new Win32Exception(error, "Unable to write to standard output (" + NativeMethods.Win32Error.GetText(error) + ").");
                    }

                    // Clear the buffer for the next operation.
                    buffer.Clear();

                    // Prompt the user for the username wanted.
                    buffer.Append("username: "******"Unable to write to standard output (" + NativeMethods.Win32Error.GetText(error) + ").");
                    }

                    // Clear the buffer for the next operation.
                    buffer.Clear();

                    // Read input from the user.
                    if (!NativeMethods.ReadConsole(stdin, buffer, BufferReadSize, out read, IntPtr.Zero))
                    {
                        int error = Marshal.GetLastWin32Error();
                        throw new Win32Exception(error, "Unable to read from standard input (" + NativeMethods.Win32Error.GetText(error) + ").");
                    }

                    // Record input from the user into local storage, stripping any EOL chars.
                    username = buffer.ToString(0, (int)read);
                    username = username.Trim(program.Settings.NewLine.ToCharArray());

                    // Clear the buffer for the next operation.
                    buffer.Clear();

                    // Set the console mode to current without echo input.
                    NativeMethods.ConsoleMode consoleMode2 = consoleMode ^ NativeMethods.ConsoleMode.EchoInput;

                    try
                    {
                        if (!NativeMethods.SetConsoleMode(stdin, consoleMode2))
                        {
                            int error = Marshal.GetLastWin32Error();
                            throw new Win32Exception(error, "Unable to set console mode (" + NativeMethods.Win32Error.GetText(error) + ").");
                        }

                        program.Trace.WriteLine($"console mode = '{(consoleMode2 & NativeMethods.ConsoleMode.AllFlags)}'.");

                        // Prompt the user for password.
                        buffer.Append("password: "******"Unable to write to standard output (" + NativeMethods.Win32Error.GetText(error) + ").");
                        }

                        // Clear the buffer for the next operation.
                        buffer.Clear();

                        // Read input from the user.
                        if (!NativeMethods.ReadConsole(stdin, buffer, BufferReadSize, out read, IntPtr.Zero))
                        {
                            int error = Marshal.GetLastWin32Error();
                            throw new Win32Exception(error, "Unable to read from standard input (" + NativeMethods.Win32Error.GetText(error) + ").");
                        }

                        // Record input from the user into local storage, stripping any EOL chars.
                        password = buffer.ToString(0, (int)read);
                        password = password.Trim(program.Settings.NewLine.ToCharArray());
                    }
                    finally
                    {
                        // Restore the console mode to its original value.
                        NativeMethods.SetConsoleMode(stdin, consoleMode);

                        program.Trace.WriteLine($"console mode = '{consoleMode}'.");
                    }

                    if (username != null && password != null)
                    {
                        return(new Credential(username, password));
                    }
                }

            return(null);
        }
예제 #7
0
        public virtual Stream OpenFileStream(string path, FileMode fileMode, FileAccess fileAccess, NativeMethods.FileAttributes attributes, FileShare shareMode)
        {
            FileAccess access = fileAccess & FileAccess.ReadWrite;

            return(new FileStream((SafeFileHandle)this.OpenFile(path, fileMode, fileAccess, (FileAttributes)attributes, shareMode), access, DefaultStreamBufferSize, true));
        }
예제 #8
0
        private static void DeleteFolder(string folderPath, bool bypassAclCheck, NativeMethods.FileAttributes parentAttributes)
        {
            var baseFolderPath = EnsureFileName(folderPath);
            var searchTerm     = Path.Combine(baseFolderPath, "*");

            var directories = new List <DirectoryWithAttributes>();

            NativeMethods.WIN32_FIND_DATAW   findInfo;
            NativeMethods.FindFileSafeHandle searchHandle = NativeMethods.FindFirstFileW(searchTerm, out findInfo);
            if (searchHandle.IsInvalid)
            {
                ThrowLastErrorException("Error locating files in {0}", searchTerm);
            }

            using (searchHandle)
            {
                do
                {
                    var isDirectory  = ((uint)findInfo.dwFileAttributes & (uint)NativeMethods.FileAttributes.Directory) == (uint)NativeMethods.FileAttributes.Directory;
                    var fullFilePath = Path.Combine(folderPath, findInfo.cFileName);

                    if ((findInfo.dwFileAttributes & NativeMethods.FileAttributes.ReparsePoint) != 0)
                    {
                        // reparse points can be removed directly. If we attempt to follow down into the reprase
                        // point, then we start getting weird error messages when unexpected files get deleted
                        // or permissions cannot be obtained.

                        if (!NativeMethods.RemoveDirectoryW(fullFilePath))
                        {
                            ThrowLastErrorException("Failed to remove reparse point {0}", fullFilePath);
                        }
                    }
                    else if (isDirectory)
                    {
                        if (string.Compare(findInfo.cFileName, ".", StringComparison.InvariantCultureIgnoreCase) == 0 ||
                            string.Compare(findInfo.cFileName, "..", StringComparison.InvariantCultureIgnoreCase) == 0)
                        {
                            continue;
                        }

                        directories.Add(new DirectoryWithAttributes {
                            Directory = fullFilePath, Attributes = findInfo.dwFileAttributes
                        });
                    }
                    else
                    {
                        RemoveReadonlyAttribute(fullFilePath, findInfo.dwFileAttributes);

                        DeleteSingleFile(fullFilePath, bypassAclCheck);
                    }
                } while (NativeMethods.FindNextFileW(searchHandle, out findInfo));
            }

            foreach (var directory in directories)
            {
                RemoveReadonlyAttribute(directory.Directory, directory.Attributes);

                DeleteFolder(directory.Directory, bypassAclCheck, directory.Attributes);
            }

            ProgressTracker.Instance.LogEntry(baseFolderPath, true);
            if (!NativeMethods.RemoveDirectoryW(baseFolderPath))
            {
                ThrowLastErrorException("Failed to remove directory {0}", baseFolderPath);
            }
        }
예제 #9
0
        /// <summary>
        /// <para></para>
        /// <para>Tokens acquired are stored in the secure secret store provided during
        /// initialization.</para>
        /// </summary>
        /// <param name="targetUri">The unique identifier for the resource for which access is to
        /// be acquired.</param>
        /// <param name="credentials">(out) Credentials when acquision is successful; null otherwise.</param>
        /// <returns>True if success; otherwise false.</returns>
        public bool InteractiveLogon(Uri targetUri, out Credential credentials)
        {
            // ReadConsole 32768 fail, 32767 ok
            // @linquize [https://github.com/Microsoft/Git-Credential-Manager-for-Windows/commit/a62b9a19f430d038dcd85a610d97e5f763980f85]
            const int BufferReadSize = 32 * 1024 - 7;

            StringBuilder buffer  = new StringBuilder(BufferReadSize);
            uint          read    = 0;
            uint          written = 0;

            NativeMethods.FileAccess              fileAccessFlags         = NativeMethods.FileAccess.GenericRead | NativeMethods.FileAccess.GenericWrite;
            NativeMethods.FileAttributes          fileAttributes          = NativeMethods.FileAttributes.Normal;
            NativeMethods.FileCreationDisposition fileCreationDisposition = NativeMethods.FileCreationDisposition.OpenExisting;
            NativeMethods.FileShare fileShareFlags = NativeMethods.FileShare.Read | NativeMethods.FileShare.Write;

            using (SafeFileHandle stdout = NativeMethods.CreateFile("CONOUT$", fileAccessFlags, fileShareFlags, IntPtr.Zero, fileCreationDisposition, fileAttributes, IntPtr.Zero))
                using (SafeFileHandle stdin = NativeMethods.CreateFile("CONIN$", fileAccessFlags, fileShareFlags, IntPtr.Zero, fileCreationDisposition, fileAttributes, IntPtr.Zero))
                {
                    // read the current console mode
                    NativeMethods.ConsoleMode consoleMode;
                    if (!NativeMethods.GetConsoleMode(stdin, out consoleMode))
                    {
                        int error = Marshal.GetLastWin32Error();
                        throw new Win32Exception(error, "Unable to determine console mode (" + error + ").");
                    }

                    // instruct the user as to what they are expected to do
                    buffer.Append("Please enter your GitHub credentials for ")
                    .Append(targetUri.Scheme)
                    .Append("://")
                    .Append(targetUri.DnsSafeHost)
                    .Append("/")
                    .Append(targetUri.PathAndQuery)
                    .AppendLine();
                    if (!NativeMethods.WriteConsole(stdout, buffer, (uint)buffer.Length, out written, IntPtr.Zero))
                    {
                        int error = Marshal.GetLastWin32Error();
                        throw new Win32Exception(error, "Unable to write to standard output (" + error + ").");
                    }

                    // clear the buffer for the next operation
                    buffer.Clear();

                    // prompt the user for the username wanted
                    buffer.Append("username: "******"Unable to write to standard output (" + error + ").");
                    }

                    // clear the buffer for the next operation
                    buffer.Clear();

                    // read input from the user
                    if (!NativeMethods.ReadConsole(stdin, buffer, BufferReadSize, out read, IntPtr.Zero))
                    {
                        int error = Marshal.GetLastWin32Error();
                        throw new Win32Exception(error, "Unable to read from standard input (" + error + ").");
                    }

                    // record input from the user into local storage, stripping any eol chars
                    string username = buffer.ToString(0, (int)read);
                    username = username.Trim(Environment.NewLine.ToCharArray());

                    // clear the buffer for the next operation
                    buffer.Clear();

                    // set the console mode to current without echo input
                    NativeMethods.ConsoleMode consoleMode2 = consoleMode ^ NativeMethods.ConsoleMode.EchoInput;

                    if (!NativeMethods.SetConsoleMode(stdin, consoleMode2))
                    {
                        int error = Marshal.GetLastWin32Error();
                        throw new Win32Exception(error, "Unable to set console mode (" + error + ").");
                    }

                    // prompt the user for password
                    buffer.Append("password: "******"Unable to write to standard output (" + error + ").");
                    }

                    // clear the buffer for the next operation
                    buffer.Clear();

                    // read input from the user
                    if (!NativeMethods.ReadConsole(stdin, buffer, BufferReadSize, out read, IntPtr.Zero))
                    {
                        int error = Marshal.GetLastWin32Error();
                        throw new Win32Exception(error, "Unable to read from standard input (" + error + ").");
                    }

                    // record input from the user into local storage, stripping any eol chars
                    string password = buffer.ToString(0, (int)read);
                    password = password.Trim(Environment.NewLine.ToCharArray());

                    // clear the buffer for the next operation
                    buffer.Clear();

                    // restore the console mode to its original value
                    if (!NativeMethods.SetConsoleMode(stdin, consoleMode))
                    {
                        int error = Marshal.GetLastWin32Error();
                        throw new Win32Exception(error, "Unable to set console mode (" + error + ").");
                    }

                    GithubAuthenticationResult result;

                    if (result = GithubAuthority.AcquireToken(targetUri, username, password, null, this.TokenScope).Result)
                    {
                        Trace.WriteLine("   token aquisition succeeded");

                        credentials = (Credential)result.Token;
                        this.PersonalAccessTokenStore.WriteCredentials(targetUri, credentials);

                        return(true);
                    }
                    else if (result == GithubAuthenticationResultType.TwoFactorApp ||
                             result == GithubAuthenticationResultType.TwoFactorSms)
                    {
                        buffer.Clear()
                        .AppendLine()
                        .Append("authcode: ");
                        if (!NativeMethods.WriteConsole(stdout, buffer, (uint)buffer.Length, out written, IntPtr.Zero))
                        {
                            int error = Marshal.GetLastWin32Error();
                            throw new Win32Exception(error, "Unable to write to standard output (" + error + ").");
                        }
                        buffer.Clear();

                        // read input from the user
                        if (!NativeMethods.ReadConsole(stdin, buffer, BufferReadSize, out read, IntPtr.Zero))
                        {
                            int error = Marshal.GetLastWin32Error();
                            throw new Win32Exception(error, "Unable to read from standard input (" + error + ").");
                        }

                        string authenticationCode = buffer.ToString(0, (int)read);
                        authenticationCode = authenticationCode.Trim(Environment.NewLine.ToCharArray());

                        if (result = GithubAuthority.AcquireToken(targetUri, username, password, authenticationCode, this.TokenScope).Result)
                        {
                            Trace.WriteLine("   token aquisition succeeded");

                            credentials = (Credential)result.Token;
                            this.PersonalAccessTokenStore.WriteCredentials(targetUri, credentials);

                            return(true);
                        }
                    }
                }

            Trace.WriteLine("   interactive logon failed");
            credentials = null;
            return(false);
        }