Advertisement
Guest User

passss

a guest
Aug 10th, 2016
276
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. <#
  2. .Synopsis
  3.   Provides access to Windows CredMan basic functionality for client scripts
  4.  
  5. ****************** IMPORTANT ******************
  6. *
  7. * If you use this script from the PS console, you
  8. * should ALWAYS pass the Target, User and Password
  9. * parameters using single quotes:
  10. *
  11. *   .\CredMan.ps1 -AddCred -Target 'http://server' -User 'JoeSchmuckatelli' -Pass 'P@55w0rd!'
  12. *
  13. * to prevent PS misinterpreting special characters
  14. * you might use as PS reserved characters
  15. *
  16. ****************** IMPORTANT ******************
  17.  
  18. .Description
  19.   Provides the following API when dot-sourced
  20.   Del-Cred
  21.   Enum-Creds
  22.   Read-Cred
  23.   Write-Cred
  24.  
  25.   Supports the following cmd-line actions
  26.   AddCred (requires -User, -Pass; -Target is optional)
  27.   DelCred (requires -Target)
  28.   GetCred (requires -Target)
  29.   RunTests (no cmd-line opts)
  30.   ShoCred (optional -All parameter to dump cred objects to console)
  31.  
  32. .INPUTS
  33.   See function-level notes
  34.  
  35. .OUTPUTS
  36.   Cmd-line usage: console output relative to success or failure state
  37.   Dot-sourced usage:
  38.   ** Successful Action **
  39.   * Del-Cred   : Int = 0
  40.   * Enum-Cred  : PsUtils.CredMan+Credential[]
  41.   * Read-Cred  : PsUtils.CredMan+Credential
  42.   * Write-Cred : Int = 0
  43.   ** Failure **
  44.   * All API    : Management.Automation.ErrorRecord
  45.  
  46. .NOTES
  47.  
  48.   Author: Jim Harrison (jim@isatools.org)
  49.   Date  : 2012/05/20
  50.   Vers  : 1.5
  51.  
  52.   Updates:
  53.   2012/10/13
  54.         - Fixed a bug where the script would only read, write or delete GENERIC
  55.         credentials types.
  56.                 - Added #region blocks to clarify internal functionality
  57.                 - Added 'CredType' param to specify what sort of credential is to be read,
  58.                 created or deleted (not used for -ShoCred or Enum-Creds)
  59.                 - Added 'CredPersist' param to specify how the credential is to be stored;
  60.                 only used in Write-Cred
  61.                 - Added 'All' param for -ShoCreds to differentiate between creds summary
  62.                 list and detailed creds dump
  63.                 - Added CRED_FLAGS enum to make the credential struct flags values clearer
  64.                 - Improved parameter validation
  65.                 - Expanded internal help (used with Get-Help cmdlet)
  66.                 - Cmd-line functions better illustrate how to interpret the results when
  67.                 dot-sourcing the script
  68.  
  69. .PARAMETER AddCred
  70.     Specifies that you wish to add a new credential or update an existing credentials
  71.     -Target, -User and -Pass parameters are required for this action
  72.  
  73. .PARAMETER Comment
  74.     Specifies the information you wish to place in the credentials comment field
  75.  
  76. .PARAMETER CredPersist
  77.     Specifies the credentials storage persistence you wish to use
  78.     Valid values are: "SESSION", "LOCAL_MACHINE", "ENTERPRISE"
  79.     NOTE: if not specified, defaults to "ENTERPRISE"
  80.    
  81. .PARAMETER CredType
  82.     Specifies the type of credential object you want to store
  83.     Valid values are: "GENERIC", "DOMAIN_PASSWORD", "DOMAIN_CERTIFICATE",
  84.     "DOMAIN_VISIBLE_PASSWORD", "GENERIC_CERTIFICATE", "DOMAIN_EXTENDED",
  85.     "MAXIMUM", "MAXIMUM_EX"
  86.     NOTE: if not specified, defaults to "GENERIC"
  87.     ****************** IMPORTANT ******************
  88.     *
  89.     * I STRONGLY recommend that you become familiar
  90.     * with http://msdn.microsoft.com/en-us/library/windows/desktop/aa374788(v=vs.85).aspx
  91.     * before you create new credentials with -CredType other than "GENERIC"
  92.     *
  93.     ****************** IMPORTANT ******************
  94.  
  95.  
  96. .PARAMETER DelCred
  97.     Specifies that you wish to remove an existing credential
  98.     -CredType may be required to remove the correct credential if more than one is
  99.     specified for a target
  100.  
  101. .PARAMETER GetCred
  102.     Specifies that you wish to retrieve an existing credential
  103.     -CredType may be required to access the correct credential if more than one is
  104.     specified for a target
  105.  
  106. .PARAMETER Pass
  107.     Specifies the credentials password
  108.  
  109. .PARAMETER RunTests
  110.     Specifies that you wish to run built-in Win32 CredMan functionality tests
  111.  
  112. .PARAMETER ShoCred
  113.     Specifies that you wish to retrieve all credential stored for the interactive user
  114.     -All parameter may be used to indicate that you wish to view all credentials properties
  115.     (default display is a summary list)
  116.  
  117. .PARAMETER Target
  118.     Specifies the authentication target for the specified credentials
  119.     If not specified, the -User information is used
  120.  
  121. .PARAMETER User
  122.     Specifies the credentials username
  123.    
  124.  
  125. .LINK
  126.     http://msdn.microsoft.com/en-us/library/windows/desktop/aa374788(v=vs.85).aspx
  127.     http://stackoverflow.com/questions/7162604/get-cached-credentials-in-powershell-from-windows-7-credential-manager
  128.     http://msdn.microsoft.com/en-us/library/windows/desktop/aa374788(v=vs.85).aspx
  129.     http://blogs.msdn.com/b/peerchan/archive/2005/11/01/487834.aspx
  130.  
  131. .EXAMPLE
  132.     .\CredMan.ps1 -AddCred -Target 'http://aserver' -User 'UserName' -Password 'P@55w0rd!' -Comment 'cuziwanna'
  133.     Stores the credential for 'UserName' with a password of 'P@55w0rd!' for authentication against 'http://aserver' and adds a comment of 'cuziwanna'
  134.  
  135. .EXAMPLE
  136.     .\CredMan.ps1 -DelCred -Target 'http://aserver' -CredType 'DOMAIN_PASSWORD'
  137.     Removes the credential used for the target 'http://aserver' as credentials type 'DOMAIN_PASSWORD'
  138.  
  139. .EXAMPLE
  140.     .\CredMan.ps1 -GetCred -Target 'http://aserver'
  141.     Retreives the credential used for the target 'http://aserver'
  142.  
  143. .EXAMPLE
  144.     .\CredMan.ps1 -ShoCred
  145.     Retrieves a summary list of all credentials stored for the interactive user
  146.  
  147. .EXAMPLE
  148.     .\CredMan.ps1 -ShoCred -All
  149.     Retrieves a detailed list of all credentials stored for the interactive user
  150.  
  151. #>
  152.  
  153. #requires -version 2
  154.  
  155. Param
  156. (
  157.     [Parameter(Mandatory=$false)][Switch] $AddCred,
  158.     [Parameter(Mandatory=$false)][Switch] $DelCred,
  159.     [Parameter(Mandatory=$false)][Switch] $GetCred,
  160.     [Parameter(Mandatory=$false)][Switch] $ShoCred,
  161.     [Parameter(Mandatory=$false)][Switch] $RunTests,
  162.     [Parameter(Mandatory=$false)][ValidateLength(1,32767) <# CRED_MAX_GENERIC_TARGET_NAME_LENGTH #>][String] $Target,
  163.     [Parameter(Mandatory=$false)][ValidateLength(1,512) <# CRED_MAX_USERNAME_LENGTH #>][String] $User,
  164.     [Parameter(Mandatory=$false)][ValidateLength(1,512) <# CRED_MAX_CREDENTIAL_BLOB_SIZE #>][String] $Pass,
  165.     [Parameter(Mandatory=$false)][ValidateLength(1,256) <# CRED_MAX_STRING_LENGTH #>][String] $Comment,
  166.     [Parameter(Mandatory=$false)][Switch] $All,
  167.     [Parameter(Mandatory=$false)][ValidateSet("GENERIC",
  168.                                               "DOMAIN_PASSWORD",
  169.                                               "DOMAIN_CERTIFICATE",
  170.                                               "DOMAIN_VISIBLE_PASSWORD",
  171.                                               "GENERIC_CERTIFICATE",
  172.                                               "DOMAIN_EXTENDED",
  173.                                               "MAXIMUM",
  174.                                               "MAXIMUM_EX")][String] $CredType = "GENERIC",
  175.     [Parameter(Mandatory=$false)][ValidateSet("SESSION",
  176.                                               "LOCAL_MACHINE",
  177.                                               "ENTERPRISE")][String] $CredPersist = "ENTERPRISE"
  178. )
  179.  
  180. #region Pinvoke
  181. #region Inline C#
  182. [String] $PsCredmanUtils = @"
  183. using System;
  184. using System.Runtime.InteropServices;
  185.  
  186. namespace PsUtils
  187. {
  188.    public class CredMan
  189.    {
  190.        #region Imports
  191.        // DllImport derives from System.Runtime.InteropServices
  192.        [DllImport("Advapi32.dll", SetLastError = true, EntryPoint = "CredDeleteW", CharSet = CharSet.Unicode)]
  193.        private static extern bool CredDeleteW([In] string target, [In] CRED_TYPE type, [In] int reservedFlag);
  194.  
  195.        [DllImport("Advapi32.dll", SetLastError = true, EntryPoint = "CredEnumerateW", CharSet = CharSet.Unicode)]
  196.        private static extern bool CredEnumerateW([In] string Filter, [In] int Flags, out int Count, out IntPtr CredentialPtr);
  197.  
  198.        [DllImport("Advapi32.dll", SetLastError = true, EntryPoint = "CredFree")]
  199.        private static extern void CredFree([In] IntPtr cred);
  200.  
  201.        [DllImport("Advapi32.dll", SetLastError = true, EntryPoint = "CredReadW", CharSet = CharSet.Unicode)]
  202.        private static extern bool CredReadW([In] string target, [In] CRED_TYPE type, [In] int reservedFlag, out IntPtr CredentialPtr);
  203.  
  204.        [DllImport("Advapi32.dll", SetLastError = true, EntryPoint = "CredWriteW", CharSet = CharSet.Unicode)]
  205.        private static extern bool CredWriteW([In] ref Credential userCredential, [In] UInt32 flags);
  206.        #endregion
  207.  
  208.        #region Fields
  209.        public enum CRED_FLAGS : uint
  210.        {
  211.            NONE = 0x0,
  212.            PROMPT_NOW = 0x2,
  213.            USERNAME_TARGET = 0x4
  214.        }
  215.  
  216.        public enum CRED_ERRORS : uint
  217.        {
  218.            ERROR_SUCCESS = 0x0,
  219.            ERROR_INVALID_PARAMETER = 0x80070057,
  220.            ERROR_INVALID_FLAGS = 0x800703EC,
  221.            ERROR_NOT_FOUND = 0x80070490,
  222.            ERROR_NO_SUCH_LOGON_SESSION = 0x80070520,
  223.            ERROR_BAD_USERNAME = 0x8007089A
  224.        }
  225.  
  226.        public enum CRED_PERSIST : uint
  227.        {
  228.            SESSION = 1,
  229.            LOCAL_MACHINE = 2,
  230.            ENTERPRISE = 3
  231.        }
  232.  
  233.        public enum CRED_TYPE : uint
  234.        {
  235.            GENERIC = 1,
  236.            DOMAIN_PASSWORD = 2,
  237.            DOMAIN_CERTIFICATE = 3,
  238.            DOMAIN_VISIBLE_PASSWORD = 4,
  239.            GENERIC_CERTIFICATE = 5,
  240.            DOMAIN_EXTENDED = 6,
  241.            MAXIMUM = 7,      // Maximum supported cred type
  242.            MAXIMUM_EX = (MAXIMUM + 1000),  // Allow new applications to run on old OSes
  243.        }
  244.  
  245.        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
  246.        public struct Credential
  247.        {
  248.            public CRED_FLAGS Flags;
  249.            public CRED_TYPE Type;
  250.            public string TargetName;
  251.            public string Comment;
  252.            public DateTime LastWritten;
  253.            public UInt32 CredentialBlobSize;
  254.            public string CredentialBlob;
  255.            public CRED_PERSIST Persist;
  256.            public UInt32 AttributeCount;
  257.            public IntPtr Attributes;
  258.            public string TargetAlias;
  259.            public string UserName;
  260.        }
  261.  
  262.        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
  263.        private struct NativeCredential
  264.        {
  265.            public CRED_FLAGS Flags;
  266.            public CRED_TYPE Type;
  267.            public IntPtr TargetName;
  268.            public IntPtr Comment;
  269.            public System.Runtime.InteropServices.ComTypes.FILETIME LastWritten;
  270.            public UInt32 CredentialBlobSize;
  271.            public IntPtr CredentialBlob;
  272.            public UInt32 Persist;
  273.            public UInt32 AttributeCount;
  274.            public IntPtr Attributes;
  275.            public IntPtr TargetAlias;
  276.            public IntPtr UserName;
  277.        }
  278.        #endregion
  279.  
  280.        #region Child Class
  281.        private class CriticalCredentialHandle : Microsoft.Win32.SafeHandles.CriticalHandleZeroOrMinusOneIsInvalid
  282.        {
  283.            public CriticalCredentialHandle(IntPtr preexistingHandle)
  284.            {
  285.                SetHandle(preexistingHandle);
  286.            }
  287.  
  288.            private Credential XlateNativeCred(IntPtr pCred)
  289.            {
  290.                NativeCredential ncred = (NativeCredential)Marshal.PtrToStructure(pCred, typeof(NativeCredential));
  291.                Credential cred = new Credential();
  292.                cred.Type = ncred.Type;
  293.                cred.Flags = ncred.Flags;
  294.                cred.Persist = (CRED_PERSIST)ncred.Persist;
  295.  
  296.                long LastWritten = ncred.LastWritten.dwHighDateTime;
  297.                LastWritten = (LastWritten << 32) + ncred.LastWritten.dwLowDateTime;
  298.                cred.LastWritten = DateTime.FromFileTime(LastWritten);
  299.  
  300.                cred.UserName = Marshal.PtrToStringUni(ncred.UserName);
  301.                cred.TargetName = Marshal.PtrToStringUni(ncred.TargetName);
  302.                cred.TargetAlias = Marshal.PtrToStringUni(ncred.TargetAlias);
  303.                cred.Comment = Marshal.PtrToStringUni(ncred.Comment);
  304.                cred.CredentialBlobSize = ncred.CredentialBlobSize;
  305.                if (0 < ncred.CredentialBlobSize)
  306.                {
  307.                    cred.CredentialBlob = Marshal.PtrToStringUni(ncred.CredentialBlob, (int)ncred.CredentialBlobSize / 2);
  308.                }
  309.                return cred;
  310.            }
  311.  
  312.            public Credential GetCredential()
  313.            {
  314.                if (IsInvalid)
  315.                {
  316.                    throw new InvalidOperationException("Invalid CriticalHandle!");
  317.                }
  318.                Credential cred = XlateNativeCred(handle);
  319.                return cred;
  320.            }
  321.  
  322.            public Credential[] GetCredentials(int count)
  323.            {
  324.                if (IsInvalid)
  325.                {
  326.                    throw new InvalidOperationException("Invalid CriticalHandle!");
  327.                }
  328.                Credential[] Credentials = new Credential[count];
  329.                IntPtr pTemp = IntPtr.Zero;
  330.                for (int inx = 0; inx < count; inx++)
  331.                {
  332.                    pTemp = Marshal.ReadIntPtr(handle, inx * IntPtr.Size);
  333.                    Credential cred = XlateNativeCred(pTemp);
  334.                    Credentials[inx] = cred;
  335.                }
  336.                return Credentials;
  337.            }
  338.  
  339.            override protected bool ReleaseHandle()
  340.            {
  341.                if (IsInvalid)
  342.                {
  343.                    return false;
  344.                }
  345.                CredFree(handle);
  346.                SetHandleAsInvalid();
  347.                return true;
  348.            }
  349.        }
  350.        #endregion
  351.  
  352.        #region Custom API
  353.        public static int CredDelete(string target, CRED_TYPE type)
  354.        {
  355.            if (!CredDeleteW(target, type, 0))
  356.            {
  357.                return Marshal.GetHRForLastWin32Error();
  358.            }
  359.            return 0;
  360.        }
  361.  
  362.        public static int CredEnum(string Filter, out Credential[] Credentials)
  363.        {
  364.            int count = 0;
  365.            int Flags = 0x0;
  366.            if (string.IsNullOrEmpty(Filter) ||
  367.                "*" == Filter)
  368.            {
  369.                Filter = null;
  370.                if (6 <= Environment.OSVersion.Version.Major)
  371.                {
  372.                    Flags = 0x1; //CRED_ENUMERATE_ALL_CREDENTIALS; only valid is OS >= Vista
  373.                }
  374.            }
  375.            IntPtr pCredentials = IntPtr.Zero;
  376.            if (!CredEnumerateW(Filter, Flags, out count, out pCredentials))
  377.            {
  378.                Credentials = null;
  379.                return Marshal.GetHRForLastWin32Error();
  380.            }
  381.            CriticalCredentialHandle CredHandle = new CriticalCredentialHandle(pCredentials);
  382.            Credentials = CredHandle.GetCredentials(count);
  383.            return 0;
  384.        }
  385.  
  386.        public static int CredRead(string target, CRED_TYPE type, out Credential Credential)
  387.        {
  388.            IntPtr pCredential = IntPtr.Zero;
  389.            Credential = new Credential();
  390.            if (!CredReadW(target, type, 0, out pCredential))
  391.            {
  392.                return Marshal.GetHRForLastWin32Error();
  393.            }
  394.            CriticalCredentialHandle CredHandle = new CriticalCredentialHandle(pCredential);
  395.            Credential = CredHandle.GetCredential();
  396.            return 0;
  397.        }
  398.  
  399.        public static int CredWrite(Credential userCredential)
  400.        {
  401.            if (!CredWriteW(ref userCredential, 0))
  402.            {
  403.                return Marshal.GetHRForLastWin32Error();
  404.            }
  405.            return 0;
  406.        }
  407.  
  408.        #endregion
  409.  
  410.        private static int AddCred()
  411.        {
  412.            Credential Cred = new Credential();
  413.            string Password = "Password";
  414.            Cred.Flags = 0;
  415.            Cred.Type = CRED_TYPE.GENERIC;
  416.            Cred.TargetName = "Target";
  417.            Cred.UserName = "UserName";
  418.            Cred.AttributeCount = 0;
  419.            Cred.Persist = CRED_PERSIST.ENTERPRISE;
  420.            Cred.CredentialBlobSize = (uint)Password.Length;
  421.            Cred.CredentialBlob = Password;
  422.            Cred.Comment = "Comment";
  423.            return CredWrite(Cred);
  424.        }
  425.  
  426.        private static bool CheckError(string TestName, CRED_ERRORS Rtn)
  427.        {
  428.            switch(Rtn)
  429.            {
  430.                case CRED_ERRORS.ERROR_SUCCESS:
  431.                    Console.WriteLine(string.Format("'{0}' worked", TestName));
  432.                    return true;
  433.                case CRED_ERRORS.ERROR_INVALID_FLAGS:
  434.                case CRED_ERRORS.ERROR_INVALID_PARAMETER:
  435.                case CRED_ERRORS.ERROR_NO_SUCH_LOGON_SESSION:
  436.                case CRED_ERRORS.ERROR_NOT_FOUND:
  437.                case CRED_ERRORS.ERROR_BAD_USERNAME:
  438.                    Console.WriteLine(string.Format("'{0}' failed; {1}.", TestName, Rtn));
  439.                    break;
  440.                default:
  441.                    Console.WriteLine(string.Format("'{0}' failed; 0x{1}.", TestName, Rtn.ToString("X")));
  442.                    break;
  443.            }
  444.            return false;
  445.        }
  446.  
  447.        /*
  448.         * Note: the Main() function is primarily for debugging and testing in a Visual
  449.         * Studio session.  Although it will work from PowerShell, it's not very useful.
  450.         */
  451.        public static void Main()
  452.        {
  453.            Credential[] Creds = null;
  454.            Credential Cred = new Credential();
  455.            int Rtn = 0;
  456.  
  457.            Console.WriteLine("Testing CredWrite()");
  458.            Rtn = AddCred();
  459.            if (!CheckError("CredWrite", (CRED_ERRORS)Rtn))
  460.            {
  461.                return;
  462.            }
  463.            Console.WriteLine("Testing CredEnum()");
  464.            Rtn = CredEnum(null, out Creds);
  465.            if (!CheckError("CredEnum", (CRED_ERRORS)Rtn))
  466.            {
  467.                return;
  468.            }
  469.            Console.WriteLine("Testing CredRead()");
  470.            Rtn = CredRead("Target", CRED_TYPE.GENERIC, out Cred);
  471.            if (!CheckError("CredRead", (CRED_ERRORS)Rtn))
  472.            {
  473.                return;
  474.            }
  475.            Console.WriteLine("Testing CredDelete()");
  476.            Rtn = CredDelete("Target", CRED_TYPE.GENERIC);
  477.            if (!CheckError("CredDelete", (CRED_ERRORS)Rtn))
  478.            {
  479.                return;
  480.            }
  481.            Console.WriteLine("Testing CredRead() again");
  482.            Rtn = CredRead("Target", CRED_TYPE.GENERIC, out Cred);
  483.            if (!CheckError("CredRead", (CRED_ERRORS)Rtn))
  484.            {
  485.                Console.WriteLine("if the error is 'ERROR_NOT_FOUND', this result is OK.");
  486.            }
  487.        }
  488.    }
  489. }
  490. "@
  491. #endregion
  492.  
  493. $PsCredMan = $null
  494. try
  495. {
  496.     $PsCredMan = [PsUtils.CredMan]
  497. }
  498. catch
  499. {
  500.     #only remove the error we generate
  501.     $Error.RemoveAt($Error.Count-1)
  502. }
  503. if($null -eq $PsCredMan)
  504. {
  505.     Add-Type $PsCredmanUtils
  506. }
  507. #endregion
  508.  
  509. #region Internal Tools
  510. [HashTable] $ErrorCategory = @{0x80070057 = "InvalidArgument";
  511.                                0x800703EC = "InvalidData";
  512.                                0x80070490 = "ObjectNotFound";
  513.                                0x80070520 = "SecurityError";
  514.                                0x8007089A = "SecurityError"}
  515.  
  516. function Get-CredType
  517. {
  518.     Param
  519.     (
  520.         [Parameter(Mandatory=$true)][ValidateSet("GENERIC",
  521.                                                   "DOMAIN_PASSWORD",
  522.                                                   "DOMAIN_CERTIFICATE",
  523.                                                   "DOMAIN_VISIBLE_PASSWORD",
  524.                                                   "GENERIC_CERTIFICATE",
  525.                                                   "DOMAIN_EXTENDED",
  526.                                                   "MAXIMUM",
  527.                                                   "MAXIMUM_EX")][String] $CredType
  528.     )
  529.    
  530.     switch($CredType)
  531.     {
  532.         "GENERIC" {return [PsUtils.CredMan+CRED_TYPE]::GENERIC}
  533.         "DOMAIN_PASSWORD" {return [PsUtils.CredMan+CRED_TYPE]::DOMAIN_PASSWORD}
  534.         "DOMAIN_CERTIFICATE" {return [PsUtils.CredMan+CRED_TYPE]::DOMAIN_CERTIFICATE}
  535.         "DOMAIN_VISIBLE_PASSWORD" {return [PsUtils.CredMan+CRED_TYPE]::DOMAIN_VISIBLE_PASSWORD}
  536.         "GENERIC_CERTIFICATE" {return [PsUtils.CredMan+CRED_TYPE]::GENERIC_CERTIFICATE}
  537.         "DOMAIN_EXTENDED" {return [PsUtils.CredMan+CRED_TYPE]::DOMAIN_EXTENDED}
  538.         "MAXIMUM" {return [PsUtils.CredMan+CRED_TYPE]::MAXIMUM}
  539.         "MAXIMUM_EX" {return [PsUtils.CredMan+CRED_TYPE]::MAXIMUM_EX}
  540.     }
  541. }
  542.  
  543. function Get-CredPersist
  544. {
  545.     Param
  546.     (
  547.         [Parameter(Mandatory=$true)][ValidateSet("SESSION",
  548.                                                   "LOCAL_MACHINE",
  549.                                                   "ENTERPRISE")][String] $CredPersist
  550.     )
  551.    
  552.     switch($CredPersist)
  553.     {
  554.         "SESSION" {return [PsUtils.CredMan+CRED_PERSIST]::SESSION}
  555.         "LOCAL_MACHINE" {return [PsUtils.CredMan+CRED_PERSIST]::LOCAL_MACHINE}
  556.         "ENTERPRISE" {return [PsUtils.CredMan+CRED_PERSIST]::ENTERPRISE}
  557.     }
  558. }
  559. #endregion
  560.  
  561. #region Dot-Sourced API
  562. function Del-Creds
  563. {
  564. <#
  565. .Synopsis
  566.   Deletes the specified credentials
  567.  
  568. .Description
  569.   Calls Win32 CredDeleteW via [PsUtils.CredMan]::CredDelete
  570.  
  571. .INPUTS
  572.   See function-level notes
  573.  
  574. .OUTPUTS
  575.   0 or non-0 according to action success
  576.   [Management.Automation.ErrorRecord] if error encountered
  577.  
  578. .PARAMETER Target
  579.   Specifies the URI for which the credentials are associated
  580.  
  581. .PARAMETER CredType
  582.   Specifies the desired credentials type; defaults to
  583.   "CRED_TYPE_GENERIC"
  584. #>
  585.  
  586.     Param
  587.     (
  588.         [Parameter(Mandatory=$true)][ValidateLength(1,32767)][String] $Target,
  589.         [Parameter(Mandatory=$false)][ValidateSet("GENERIC",
  590.                                                   "DOMAIN_PASSWORD",
  591.                                                   "DOMAIN_CERTIFICATE",
  592.                                                   "DOMAIN_VISIBLE_PASSWORD",
  593.                                                   "GENERIC_CERTIFICATE",
  594.                                                   "DOMAIN_EXTENDED",
  595.                                                   "MAXIMUM",
  596.                                                   "MAXIMUM_EX")][String] $CredType = "GENERIC"
  597.     )
  598.    
  599.     [Int] $Results = 0
  600.     try
  601.     {
  602.         $Results = [PsUtils.CredMan]::CredDelete($Target, $(Get-CredType $CredType))
  603.     }
  604.     catch
  605.     {
  606.         return $_
  607.     }
  608.     if(0 -ne $Results)
  609.     {
  610.         [String] $Msg = "Failed to delete credentials store for target '$Target'"
  611.         [Management.ManagementException] $MgmtException = New-Object Management.ManagementException($Msg)
  612.         [Management.Automation.ErrorRecord] $ErrRcd = New-Object Management.Automation.ErrorRecord($MgmtException, $Results.ToString("X"), $ErrorCategory[$Results], $null)
  613.         return $ErrRcd
  614.     }
  615.     return $Results
  616. }
  617.  
  618. function Enum-Creds
  619. {
  620. <#
  621. .Synopsis
  622.   Enumerates stored credentials for operating user
  623.  
  624. .Description
  625.   Calls Win32 CredEnumerateW via [PsUtils.CredMan]::CredEnum
  626.  
  627. .INPUTS
  628.  
  629.  
  630. .OUTPUTS
  631.   [PsUtils.CredMan+Credential[]] if successful
  632.   [Management.Automation.ErrorRecord] if unsuccessful or error encountered
  633.  
  634. .PARAMETER Filter
  635.   Specifies the filter to be applied to the query
  636.   Defaults to [String]::Empty
  637.  
  638. #>
  639.  
  640.     Param
  641.     (
  642.         [Parameter(Mandatory=$false)][AllowEmptyString()][String] $Filter = [String]::Empty
  643.     )
  644.    
  645.     [PsUtils.CredMan+Credential[]] $Creds = [Array]::CreateInstance([PsUtils.CredMan+Credential], 0)
  646.     [Int] $Results = 0
  647.     try
  648.     {
  649.         $Results = [PsUtils.CredMan]::CredEnum($Filter, [Ref]$Creds)
  650.     }
  651.     catch
  652.     {
  653.         return $_
  654.     }
  655.     switch($Results)
  656.     {
  657.         0 {break}
  658.         0x80070490 {break} #ERROR_NOT_FOUND
  659.         default
  660.         {
  661.             [String] $Msg = "Failed to enumerate credentials store for user '$Env:UserName'"
  662.             [Management.ManagementException] $MgmtException = New-Object Management.ManagementException($Msg)
  663.             [Management.Automation.ErrorRecord] $ErrRcd = New-Object Management.Automation.ErrorRecord($MgmtException, $Results.ToString("X"), $ErrorCategory[$Results], $null)
  664.             return $ErrRcd
  665.         }
  666.     }
  667.     return $Creds
  668. }
  669.  
  670. function Read-Creds
  671. {
  672. <#
  673. .Synopsis
  674.   Reads specified credentials for operating user
  675.  
  676. .Description
  677.   Calls Win32 CredReadW via [PsUtils.CredMan]::CredRead
  678.  
  679. .INPUTS
  680.  
  681. .OUTPUTS
  682.   [PsUtils.CredMan+Credential] if successful
  683.   [Management.Automation.ErrorRecord] if unsuccessful or error encountered
  684.  
  685. .PARAMETER Target
  686.   Specifies the URI for which the credentials are associated
  687.   If not provided, the username is used as the target
  688.  
  689. .PARAMETER CredType
  690.   Specifies the desired credentials type; defaults to
  691.   "CRED_TYPE_GENERIC"
  692. #>
  693.  
  694.     Param
  695.     (
  696.         [Parameter(Mandatory=$true)][ValidateLength(1,32767)][String] $Target,
  697.         [Parameter(Mandatory=$false)][ValidateSet("GENERIC",
  698.                                                   "DOMAIN_PASSWORD",
  699.                                                   "DOMAIN_CERTIFICATE",
  700.                                                   "DOMAIN_VISIBLE_PASSWORD",
  701.                                                   "GENERIC_CERTIFICATE",
  702.                                                   "DOMAIN_EXTENDED",
  703.                                                   "MAXIMUM",
  704.                                                   "MAXIMUM_EX")][String] $CredType = "GENERIC"
  705.     )
  706.    
  707.     if("GENERIC" -ne $CredType -and 337 -lt $Target.Length) #CRED_MAX_DOMAIN_TARGET_NAME_LENGTH
  708.     {
  709.         [String] $Msg = "Target field is longer ($($Target.Length)) than allowed (max 337 characters)"
  710.         [Management.ManagementException] $MgmtException = New-Object Management.ManagementException($Msg)
  711.         [Management.Automation.ErrorRecord] $ErrRcd = New-Object Management.Automation.ErrorRecord($MgmtException, 666, 'LimitsExceeded', $null)
  712.         return $ErrRcd
  713.     }
  714.     [PsUtils.CredMan+Credential] $Cred = New-Object PsUtils.CredMan+Credential
  715.     [Int] $Results = 0
  716.     try
  717.     {
  718.         $Results = [PsUtils.CredMan]::CredRead($Target, $(Get-CredType $CredType), [Ref]$Cred)
  719.     }
  720.     catch
  721.     {
  722.         return $_
  723.     }
  724.    
  725.     switch($Results)
  726.     {
  727.         0 {break}
  728.         0x80070490 {return $null} #ERROR_NOT_FOUND
  729.         default
  730.         {
  731.             [String] $Msg = "Error reading credentials for target '$Target' from '$Env:UserName' credentials store"
  732.             [Management.ManagementException] $MgmtException = New-Object Management.ManagementException($Msg)
  733.             [Management.Automation.ErrorRecord] $ErrRcd = New-Object Management.Automation.ErrorRecord($MgmtException, $Results.ToString("X"), $ErrorCategory[$Results], $null)
  734.             return $ErrRcd
  735.         }
  736.     }
  737.     return $Cred
  738. }
  739.  
  740. function Write-Creds
  741. {
  742. <#
  743. .Synopsis
  744.   Saves or updates specified credentials for operating user
  745.  
  746. .Description
  747.   Calls Win32 CredWriteW via [PsUtils.CredMan]::CredWrite
  748.  
  749. .INPUTS
  750.  
  751. .OUTPUTS
  752.   [Boolean] true if successful
  753.   [Management.Automation.ErrorRecord] if unsuccessful or error encountered
  754.  
  755. .PARAMETER Target
  756.   Specifies the URI for which the credentials are associated
  757.   If not provided, the username is used as the target
  758.  
  759. .PARAMETER UserName
  760.   Specifies the name of credential to be read
  761.  
  762. .PARAMETER Password
  763.   Specifies the password of credential to be read
  764.  
  765. .PARAMETER Comment
  766.   Allows the caller to specify the comment associated with
  767.   these credentials
  768.  
  769. .PARAMETER CredType
  770.   Specifies the desired credentials type; defaults to
  771.   "CRED_TYPE_GENERIC"
  772.  
  773. .PARAMETER CredPersist
  774.   Specifies the desired credentials storage type;
  775.   defaults to "CRED_PERSIST_ENTERPRISE"
  776. #>
  777.  
  778.     Param
  779.     (
  780.         [Parameter(Mandatory=$false)][ValidateLength(0,32676)][String] $Target,
  781.         [Parameter(Mandatory=$true)][ValidateLength(1,512)][String] $UserName,
  782.         [Parameter(Mandatory=$true)][ValidateLength(1,512)][String] $Password,
  783.         [Parameter(Mandatory=$false)][ValidateLength(0,256)][String] $Comment = [String]::Empty,
  784.         [Parameter(Mandatory=$false)][ValidateSet("GENERIC",
  785.                                                   "DOMAIN_PASSWORD",
  786.                                                   "DOMAIN_CERTIFICATE",
  787.                                                   "DOMAIN_VISIBLE_PASSWORD",
  788.                                                   "GENERIC_CERTIFICATE",
  789.                                                   "DOMAIN_EXTENDED",
  790.                                                   "MAXIMUM",
  791.                                                   "MAXIMUM_EX")][String] $CredType = "GENERIC",
  792.         [Parameter(Mandatory=$false)][ValidateSet("SESSION",
  793.                                                   "LOCAL_MACHINE",
  794.                                                   "ENTERPRISE")][String] $CredPersist = "ENTERPRISE"
  795.     )
  796.  
  797.     if([String]::IsNullOrEmpty($Target))
  798.     {
  799.         $Target = $UserName
  800.     }
  801.     if("GENERIC" -ne $CredType -and 337 -lt $Target.Length) #CRED_MAX_DOMAIN_TARGET_NAME_LENGTH
  802.     {
  803.         [String] $Msg = "Target field is longer ($($Target.Length)) than allowed (max 337 characters)"
  804.         [Management.ManagementException] $MgmtException = New-Object Management.ManagementException($Msg)
  805.         [Management.Automation.ErrorRecord] $ErrRcd = New-Object Management.Automation.ErrorRecord($MgmtException, 666, 'LimitsExceeded', $null)
  806.         return $ErrRcd
  807.     }
  808.     if([String]::IsNullOrEmpty($Comment))
  809.     {
  810.         $Comment = [String]::Format("Last edited by {0}\{1} on {2}",
  811.                                     $Env:UserDomain,
  812.                                     $Env:UserName,
  813.                                     $Env:ComputerName)
  814.     }
  815.     [String] $DomainName = [Net.NetworkInformation.IPGlobalProperties]::GetIPGlobalProperties().DomainName
  816.     [PsUtils.CredMan+Credential] $Cred = New-Object PsUtils.CredMan+Credential
  817.     switch($Target -eq $UserName -and
  818.            ("CRED_TYPE_DOMAIN_PASSWORD" -eq $CredType -or
  819.             "CRED_TYPE_DOMAIN_CERTIFICATE" -eq $CredType))
  820.     {
  821.         $true  {$Cred.Flags = [PsUtils.CredMan+CRED_FLAGS]::USERNAME_TARGET}
  822.         $false  {$Cred.Flags = [PsUtils.CredMan+CRED_FLAGS]::NONE}
  823.     }
  824.     $Cred.Type = Get-CredType $CredType
  825.     $Cred.TargetName = $Target
  826.     $Cred.UserName = $UserName
  827.     $Cred.AttributeCount = 0
  828.     $Cred.Persist = Get-CredPersist $CredPersist
  829.     $Cred.CredentialBlobSize = [Text.Encoding]::Unicode.GetBytes($Password).Length
  830.     $Cred.CredentialBlob = $Password
  831.     $Cred.Comment = $Comment
  832.  
  833.     [Int] $Results = 0
  834.     try
  835.     {
  836.         $Results = [PsUtils.CredMan]::CredWrite($Cred)
  837.     }
  838.     catch
  839.     {
  840.         return $_
  841.     }
  842.  
  843.     if(0 -ne $Results)
  844.     {
  845.         [String] $Msg = "Failed to write to credentials store for target '$Target' using '$UserName', '$Password', '$Comment'"
  846.         [Management.ManagementException] $MgmtException = New-Object Management.ManagementException($Msg)
  847.         [Management.Automation.ErrorRecord] $ErrRcd = New-Object Management.Automation.ErrorRecord($MgmtException, $Results.ToString("X"), $ErrorCategory[$Results], $null)
  848.         return $ErrRcd
  849.     }
  850.     return $Results
  851. }
  852.  
  853. #endregion
  854.  
  855. #region Cmd-Line functionality
  856. function CredManMain
  857. {
  858. #region Adding credentials
  859.     if($AddCred)
  860.     {
  861.         if([String]::IsNullOrEmpty($User) -or
  862.            [String]::IsNullOrEmpty($Pass))
  863.         {
  864.             Write-Host "You must supply a user name and password (target URI is optional)."
  865.             return
  866.         }
  867.         # may be [Int32] or [Management.Automation.ErrorRecord]
  868.         [Object] $Results = Write-Creds $Target $User $Pass $Comment $CredType $CredPersist
  869.         if(0 -eq $Results)
  870.         {
  871.             [Object] $Cred = Read-Creds $Target $CredType
  872.             if($null -eq $Cred)
  873.             {
  874.                 Write-Host "Credentials for '$Target', '$User' was not found."
  875.                 return
  876.             }
  877.             if($Cred -is [Management.Automation.ErrorRecord])
  878.             {
  879.                 return $Cred
  880.             }
  881.             [String] $CredStr = @"
  882. Successfully wrote or updated credentials as:
  883.  UserName  : $($Cred.UserName)
  884.  Password  : $($Cred.CredentialBlob)
  885.  Target    : $($Cred.TargetName.Substring($Cred.TargetName.IndexOf("=")+1))
  886.  Updated   : $([String]::Format("{0:yyyy-MM-dd HH:mm:ss}", $Cred.LastWritten.ToUniversalTime())) UTC
  887.  Comment   : $($Cred.Comment)
  888. "@
  889.             Write-Host $CredStr
  890.             return
  891.         }
  892.         # will be a [Management.Automation.ErrorRecord]
  893.         return $Results
  894.     }
  895. #endregion 
  896.  
  897. #region Removing credentials
  898.     if($DelCred)
  899.     {
  900.         if(-not $Target)
  901.         {
  902.             Write-Host "You must supply a target URI."
  903.             return
  904.         }
  905.         # may be [Int32] or [Management.Automation.ErrorRecord]
  906.         [Object] $Results = Del-Creds $Target $CredType
  907.         if(0 -eq $Results)
  908.         {
  909.             Write-Host "Successfully deleted credentials for '$Target'"
  910.             return
  911.         }
  912.         # will be a [Management.Automation.ErrorRecord]
  913.         return $Results
  914.     }
  915. #endregion
  916.  
  917. #region Reading selected credential
  918.     if($GetCred)
  919.     {
  920.         if(-not $Target)
  921.         {
  922.             Write-Host "You must supply a target URI."
  923.             return
  924.         }
  925.         # may be [PsUtils.CredMan+Credential] or [Management.Automation.ErrorRecord]
  926.         [Object] $Cred = Read-Creds $Target $CredType
  927.         if($null -eq $Cred)
  928.         {
  929.             Write-Host "Credential for '$Target' as '$CredType' type was not found."
  930.             return
  931.         }
  932.         if($Cred -is [Management.Automation.ErrorRecord])
  933.         {
  934.             return $Cred
  935.         }
  936.         [String] $CredStr = @"
  937. Found credentials as:
  938.  UserName  : $($Cred.UserName)
  939.  Password  : $($Cred.CredentialBlob)
  940.  Target    : $($Cred.TargetName.Substring($Cred.TargetName.IndexOf("=")+1))
  941.  Updated   : $([String]::Format("{0:yyyy-MM-dd HH:mm:ss}", $Cred.LastWritten.ToUniversalTime())) UTC
  942.  Comment   : $($Cred.Comment)
  943. "@
  944.         Write-Host $CredStr
  945.     }
  946. #endregion
  947.  
  948. #region Reading all credentials
  949.     if($ShoCred)
  950.     {
  951.         # may be [PsUtils.CredMan+Credential[]] or [Management.Automation.ErrorRecord]
  952.         [Object] $Creds = Enum-Creds
  953.         if($Creds -split [Array] -and 0 -eq $Creds.Length)
  954.         {
  955.             Write-Host "No Credentials found for $($Env:UserName)"
  956.             return
  957.         }
  958.         if($Creds -is [Management.Automation.ErrorRecord])
  959.         {
  960.             return $Creds
  961.         }
  962.         foreach($Cred in $Creds)
  963.         {
  964.             [String] $CredStr = @"
  965.            
  966. UserName  : $($Cred.UserName)
  967. Password  : $($Cred.CredentialBlob)
  968. Target    : $($Cred.TargetName.Substring($Cred.TargetName.IndexOf("=")+1))
  969. Updated   : $([String]::Format("{0:yyyy-MM-dd HH:mm:ss}", $Cred.LastWritten.ToUniversalTime())) UTC
  970. Comment   : $($Cred.Comment)
  971. "@
  972.             if($All)
  973.             {
  974.                 $CredStr = @"
  975. $CredStr
  976. Alias     : $($Cred.TargetAlias)
  977. AttribCnt : $($Cred.AttributeCount)
  978. Attribs   : $($Cred.Attributes)
  979. Flags     : $($Cred.Flags)
  980. Pwd Size  : $($Cred.CredentialBlobSize)
  981. Storage   : $($Cred.Persist)
  982. Type      : $($Cred.Type)
  983. "@
  984.             }
  985.             Write-Host $CredStr
  986.         }
  987.         return
  988.     }
  989. #endregion
  990.  
  991. #region Run basic diagnostics
  992.     if($RunTests)
  993.     {
  994.         [PsUtils.CredMan]::Main()
  995.     }
  996. #endregion
  997. }
  998. #endregion
  999.  
  1000. CredManMain
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement