8000 Port CmsMessage cmdlets and Get-PfxCertificate to powershell core by daxian-dbw · Pull Request #3224 · PowerShell/PowerShell · GitHub
[go: up one dir, main page]

Skip to content

Port CmsMessage cmdlets and Get-PfxCertificate to powershell core #3224

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Mar 1, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 0 additions & 6 deletions src/Microsoft.PowerShell.Security/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,19 +47,13 @@
"define": [ "CORECLR" ],
"compile": {
"exclude": [
"security/CertificateCommands.cs",
"security/CmsCommands.cs",
"singleshell/installer/MshSecurityMshSnapin.cs",

"gen/CertificateCommands.cs",
"gen/CmsCommands.cs",
"gen/SecurityMshSnapinResources.cs"
]
},
"embed": {
"exclude": [
"resources/CertificateCommands.resx",
"resources/CmsCommands.resx",
"resources/SecurityMshSnapinResources.resx"
]
}
Expand Down
14 changes: 4 additions & 10 deletions src/Microsoft.PowerShell.Security/security/CertificateCommands.cs
Original file line number Diff line number Diff line change
Expand Up @@ -212,26 +212,20 @@ protected override void ProcessRecord()

private static X509Certificate2 GetCertFromPfxFile(string path)
{
X509Certificate2 cert = new X509Certificate2();

cert.Import(path);

X509Certificate2 cert = new X509Certificate2(path);
return cert;
}

private static X509Certificate2 GetCertFromPfxFile(string path, SecureString password)
{
X509Certificate2 cert = new X509Certificate2();

//
// NTRAID#DevDiv Bugs-33007-2004/7/08-kumarp
// the following will not be required once X509Certificate2.Import()
// accepts a SecureString
//
string clearTextPassword = SecurityUtils.GetStringFromSecureString(password);

cert.Import(path, clearTextPassword, X509KeyStorageFlags.DefaultKeySet);

string clearTextPassword = Utils.GetStringFromSecureString(password);

var cert = new X509Certificate2(path, clearTextPassword, X509KeyStorageFlags.DefaultKeySet);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see SecureString in corefx but not in alfa.16 😕

PS C:\Program Files\PowerShell\6.0.0.16> [X509Certificate2]::New

OverloadDefinitions
-------------------
System.Security.Cryptography.X509Certificates.X509Certificate2 new()
System.Security.Cryptography.X509Certificates.X509Certificate2 new(byte[] rawData)
System.Security.Cryptography.X509Certificates.X509Certificate2 new(byte[] rawData, string password)
System.Security.Cryptography.X509Certificates.X509Certificate2 new(byte[] rawData, string password,
System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags)
System.Security.Cryptography.X509Certificates.X509Certificate2 new(System.IntPtr handle)
System.Security.Cryptography.X509Certificates.X509Certificate2 new(string fileName)
System.Security.Cryptography.X509Certificates.X509Certificate2 new(string fileName, string password)
System.Security.Cryptography.X509Certificates.X509Certificate2 new(string fileName, string password,
System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for noticing this. We need to update our code to use the new APIs once we move to a newer version of .NET Core packages. I opened this issue #3228 to track this effort as well as the list of similar code instances. Please feel free to update the list when you spot one.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Closed.

return cert;
}
}
Expand Down
9 changes: 2 additions & 7 deletions src/Microsoft.PowerShell.Security/security/CmsCommands.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,14 @@
--********************************************************************/

using System;
using System.IO;
using System.Management.Automation;
using System.Text;
using System.Security;
using System.Security.Cryptography;
using System.Globalization;
using System.Security.Cryptography.Pkcs;
using System.Security.Cryptography.X509Certificates;
using System.Diagnostics.CodeAnalysis;
using System.Collections.ObjectModel;
using System.Collections.Generic;
using System.Management.Automation.Security;
using System.Diagnostics.Eventing.Reader;

namespace Microsoft.PowerShell.Commands
{
Expand Down Expand Up @@ -279,7 +274,7 @@ protected override void ProcessRecord()
{
if (_contentBuffer.Length > 0)
{
_contentBuffer.Append(Environment.NewLine);
_contentBuffer.Append(System.Environment.NewLine);
}

_contentBuffer.Append(Content);
Expand Down Expand Up @@ -456,7 +451,7 @@ protected override void ProcessRecord()
{
if (_contentBuffer.Length > 0)
{
_contentBuffer.Append(Environment.NewLine);
_contentBuffer.Append(System.Environment.NewLine);
}

_contentBuffer.Append(Content);
Expand Down
118 changes: 0 additions & 118 deletions src/Microsoft.PowerShell.Security/security/Utils.cs
17A6
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,9 @@
using System;
using System.IO;
using System.Management.Automation;
using Microsoft.PowerShell.Commands;
using System.Management.Automation.Host;
using System.Management.Automation.Internal;
using System.Security;
using System.Security.Principal;
using System.Security.AccessControl;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;

using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Runtime.InteropServices;
using DWORD = System.UInt32;
using BOOL = System.UInt32;
using FILETIME = System.Runtime.InteropServices.ComTypes.FILETIME;

namespace Microsoft.PowerShell
{
Expand Down Expand Up @@ -47,44 +35,6 @@ internal static long GetFileSize(string filePath)
return size;
}

#if false
/// <summary>
/// throw if file is smaller than 4 bytes in length
/// </summary>
///
/// <param name="filePath"> path to file </param>
///
/// <returns> Does not return a value </returns>
///
/// <remarks> </remarks>
///
internal static void CheckIfFileSmallerThan4Bytes(string filePath)
{
if (GetFileSize(filePath) < 4)
{
string message =
StringUtil.Format(
UtilsStrings.FileSmallerThan4Bytes,
new object[] { filePath }
);

throw PSTraceSource.NewArgumentException(message, "path");
/*
// 2004/10/22-JonN The above form of the constructor
// no longer exists. This should probably be as below,
// however I have not tested this. This method is not
// used so I have removed it.
throw PSTraceSource.NewArgumentException(
"path",
"Utils",
"FileSmallerThan4Bytes",
filePath
);
*/
}
}
#endif

/// <summary>
/// present a prompt for a SecureString data
/// </summary>
Expand All @@ -109,74 +59,6 @@ internal static SecureString PromptForSecureString(PSHostUserInterface hostUI,
return ss;
}

#if !CORECLR
/// <summary>
/// get plain text string from a SecureString
///
/// This function will not be required once all of the methods
/// that we call accept a SecureString. The list below has
/// classes/methods that will be changed to accept a SecureString
/// after Whidbey beta1
///
/// -- X509Certificate2.Import (String, String, X509KeyStorageFlags)
/// (DCR #33007 in the DevDiv Schedule db)
///
/// -- NetworkCredential(string, string);
///
/// </summary>
///
/// <param name="ss"> input data </param>
///
/// <returns> a string representing clear-text equivalent of ss </returns>
///
/// <remarks> </remarks>
///
[ArchitectureSensitive]
internal static string GetStringFromSecureString(SecureString ss)
{
IntPtr p = Marshal.SecureStringToGlobalAllocUnicode(ss);
string s = Marshal.PtrToStringUni(p);

Marshal.ZeroFreeGlobalAllocUnicode(p);

return s;
}
#endif

/*
/// <summary>
/// display sec-desc of a file
/// </summary>
///
/// <param name="sd"> file security descriptor </param>
///
/// <returns> Does not return a value </returns>
///
/// <remarks> </remarks>
///
internal static void ShowFileSd(FileSecurity sd)
{
string userName = null;
FileSystemRights rights = 0;
AccessControlType aceType = 0;

rules = sd.GetAccessRules(true, false, typeof(NTAccount));

foreach (FileSystemAccessRule r in rules)
{
userName = r.IdentityReference.ToString();
aceType = r.AccessControlType;
rights = r.FileSystemRights;

Console.WriteLine("{0} : {1} : {2}",
userName,
aceType.ToString(),
rights.ToString());
}
}
}
*/

/// <summary>
///
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ ModuleVersion="3.0.0.0"
PowerShellVersion="3.0"
AliasesToExport = @()
FunctionsToExport = @()
CmdletsToExport="Get-Credential", "Get-ExecutionPolicy", "Set-ExecutionPolicy", "ConvertFrom-SecureString", "ConvertTo-SecureString"
CmdletsToExport="Get-Credential", "Get-ExecutionPolicy", "Set-ExecutionPolicy", "ConvertFrom-SecureString", "ConvertTo-SecureString", "Get-PfxCertificate"
NestedModules="Microsoft.PowerShell.Security.dll"
HelpInfoURI = 'https://go.microsoft.com/fwlink/?linkid=390786'
}

This file was deleted.

25 changes: 0 additions & 25 deletions src/System.Management.Automation/CoreCLR/CorePsStub.cs
Original file line number Diff line number Diff line change
Expand Up @@ -793,31 +793,6 @@ public enum RollbackSeverity

#endregion PSTransaction

#region CMS

internal static class CmsUtils
{
internal static string BEGIN_CERTIFICATE_SIGIL = "-----BEGIN CERTIFICATE-----";
internal static string END_CERTIFICATE_SIGIL = "-----END CERTIFICATE-----";

internal static string Encrypt(byte[] contentBytes, CmsMessageRecipient[] recipients, SessionState sessionState, out ErrorRecord error)
{
throw new NotImplementedException("CmsUtils.Encrypt(...) is not implemented in CoreCLR powershell.");
}

internal static string GetAsciiArmor(byte[] bytes)
{
throw new NotImplementedException("CmsUtils.GetAsciiArmor(...) is not implemented in CoreCLR powershell.");
}

internal static byte[] RemoveAsciiArmor(string actualContent, string beginMarker, string endMarker, out int startIndex, out int endIndex)
{
throw new NotImplementedException("CmsUtils.RemoveAsciiArmor(...) is not implemented in CoreCLR powershell.");
}
}

#endregion CMS

#region ApartmentState

internal enum ApartmentState
Expand Down
1 change: 1 addition & 0 deletions src/System.Management.Automation/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@
"System.Reflection.Emit.Lightweight": "4.3.0",
"System.Security.AccessControl": "4.3.0",
"System.Security.Cryptography.Algorithms": "4.3.0",
"System.Security.Cryptography.Pkcs": "4.3.0",
"System.Security.Cryptography.X509Certificates": "4.3.0",
"System.Threading.Thread": "4.3.0",
"System.Threading.Tasks.Parallel": "4.3.0",
Expand Down
13 changes: 2 additions & 11 deletions src/System.Management.Automation/security/SecuritySupport.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1012,17 +1012,11 @@ internal enum CertificatePurpose

namespace System.Management.Automation
{
#if !CORECLR

using System.Security.Cryptography.Pkcs;

/// <summary>
/// Utility class for CMS (Cryptographic Message Syntax) related operations
/// </summary>
/// <remarks>
/// The namespace 'System.Security.Cryptography.Pkcs' is not available in CoreCLR,
/// so the Cryptographic Message Syntax (CMS) will not be supported on OneCore PS.
/// </remarks>
internal static class CmsUtils
{
internal static string Encrypt(byte[] contentBytes, CmsMessageRecipient[] recipients, SessionState sessionState, out ErrorRecord error)
Expand Down Expand Up @@ -1086,8 +1080,7 @@ internal static string GetAsciiArmor(byte[] bytes)
StringBuilder output = new StringBuilder();
output.AppendLine(BEGIN_CMS_SIGIL);

string encodedString = Convert.ToBase64String(
bytes, Base64FormattingOptions.InsertLineBreaks);
string encodedString = ClrFacade.ToBase64StringWithLineBreaks(bytes);
output.AppendLine(encodedString);
output.Append(END_CMS_SIGIL);

Expand Down Expand Up @@ -1131,8 +1124,6 @@ internal static byte[] RemoveAsciiArmor(string actualContent, string beginMarker
}
}

#endif

/// <summary>
/// Represents a message recipient for the Cms cmdlets.
/// </summary>
Expand Down Expand Up @@ -1271,7 +1262,7 @@ private void ResolveFromBase64Encoding(ResolutionPurpose purpose, out ErrorRecor
return;
}

List<X509Certificate2> certificatesToProcess = new List<X509Certificate2>(); ;
List<X509Certificate2> certificatesToProcess = new List<X509Certificate2>();
try
{
X509Certificate2 newCertificate = new X509Certificate2(messageBytes);
Expand Down
30 changes: 30 additions & 0 deletions src/System.Management.Automation/utils/ClrFacade.cs
Original file line number Diff line number Diff line change
Expand Up @@ -661,6 +661,36 @@ internal static void SetCurrentThreadUiCulture(CultureInfo uiCultureInfo)

#region Misc

/// <summary>
/// Facade for Convert.ToBase64String(bytes, Base64FormattingOptions.InsertLineBreaks)
/// Inserts line breaks after every 76 characters in the string representation.
/// </summary>
internal static string ToBase64StringWithLineBreaks(byte[] bytes)
Copy link
Collaborator
@iSazonov iSazonov Feb 28, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Haven't we still Base64FormattingOptions in CoreCLR? 😕

Workarround:

PS C:\Program Files\PowerShell\6.0.0.16> $test="0123456789" *10
PS C:\Program Files\PowerShell\6.0.0.16> $test
0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
PS C:\Program Files\PowerShell\6.0.0.16> [convert]::ToBase64String($test.ToCharArray(), 0, 100,1)
MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2
Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OQ==
PS C:\Program Files\PowerShell\6.0.0.16> [convert]::ToBase64String($test.ToCharArray(), 0, 100,0)
MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OQ==

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So they expose the 'Base64FormattingOptions' overload in runtime assembly but not in contract assembly, interesting. Since this overload is not in contract, we cannot use it in C# code.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I add workarround later. Cannot we use it too?

Copy link
Member Author
@daxian-dbw daxian-dbw Feb 28, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't [convert]::ToBase64String($test.ToCharArray(), 0, 100,1) your workaround in powershell? You can do this in powershell because the API ToBase64String(byte[] inArray, int offset, int length, System.Base64FormattingOptions) is exposed in runtime assembly and thus powershell is able to call it using reflection. However, the contract assembly doesn't contain this API. C# code are compiled against the contract assembly, and thus this won't work in C#.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for clarify!
Closed.

{
#if CORECLR
// Inserts line breaks after every 76 characters in the string representation.
string encodedRawString = Convert.ToBase64String(bytes);
if (encodedRawString.Length <= 76)
return encodedRawString;

StringBuilder builder = new StringBuilder(encodedRawString.Length);
int index = 0, remainingLen = encodedRawString.Length;
while (remainingLen > 76)
Copy link
Member
@mirichmo mirichmo Mar 1, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was this copied from somewhere in CoreCLR or is it new implementation? I'm curious if it needs additional testing or if it is sufficiently exercised by your tests.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is new implementation based on the base64LineBreakPosition from the source code of [System.Convert]::ToBase64String(byte[] inArray, Base64FormattingOptions options).
This method is used in Protect-CmsMessage through CmsUtils.Encrypt. I believe it's well exercised by the tests.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@daxian-dbw Perhaps it makes sense to open new Issue to migrate to .Net Core method when it become available?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Opened #3235 to track this category of issues.

{
builder.Append(encodedRawString, index, 76);
builder.Append(System.Environment.NewLine);

index += 76;
remainingLen -= 76;
}

builder.Append(encodedRawString, index, remainingLen);
return builder.ToString();
#else
return Convert.ToBase64String(bytes, Base64FormattingOptions.InsertLineBreaks);
#endif
}

/// <summary>
/// Facade for RemotingServices.IsTransparentProxy(object)
/// </summary>
Expand Down
Loading
0