Connection to mainframe and Unix to get certificate information - powershell

I have a program that works good to get certificate information, but only for Windows boxes. I need it to work for UNIX and mainframe. I added the cert to the Windows trusted root cert auth and have the root cert there as well. I did not generate my own cert here as I didn't think it was needed.
It blows up on the last line where it does an auth, with the error
The remote certificate is invalid according to the validation procedure.
Any ideas what to check for?
$certpath = "C:\Certdir\Certificates\xxx.cer"
$cert = [System.Security.Cryptography.X509Certificates.X509Certificate2]::CreateFromCertFile($certPath)
[System.Security.Authentication.SslProtocols]$protocol = "TLS"
$certcol = New-Object System.Security.Cryptography.X509Certificates.X509CertificateCollection
$certcol.Add($cert)
$socket = New-Object Net.Sockets.TcpClient($computerName, $port)
$stream = $socket.GetStream()
$sslStream = New-Object System.Net.Security.SslStream $stream,$false
$sslStream.AuthenticateAsClient($computerName,$certcol,$protocol,$false)

Related

Powershell - Enroll SSL cert On Behalf Of

I created Enrollment Agent Certificate, and through GUI i can install certificate for another user.
Now, i want to automate this procedure using Powershell.
On my local cert store Enrollment agent certificate is installed (Template name:Enrollment Agent) along with certificate i want to issue to other user (Template name:GP)
$PKCS10 = New-Object -ComObject X509Enrollment.CX509CertificateRequestPkcs10
# cert template name i want to issue to user
$PKCS10.InitializeFromTemplateName(0x1,"GP")
$PKCS10.Encode()
$pkcs7 = New-Object -ComObject X509enrollment.CX509CertificateRequestPkcs7
$pkcs7.InitializeFromInnerRequest($pkcs10)
$pkcs7.RequesterName = "domain\some.user"
$signer = New-Object -ComObject X509Enrollment.CSignerCertificate
# bellow is thumbprint of certificate i want to issue (GP)
$signer.Initialize(0,0,0xc,"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
$pkcs7.SignerCertificate = $signer
$Request = New-Object -ComObject X509Enrollment.CX509Enrollment
$Request.InitializeFromRequest($pkcs7)
$Request.Enroll()
Last line fail with error
CertEnroll::CX509Enrollment::Enroll: Error Verifying Request Signature
or Signing Certificate The certificate is not valid for the requested usage.
0x800b0110 (-2146762480 CERT_E_WRONG_USAGE)
Solved, had to specify Enrollment agent thumbprint

Bypass Internet Explorer certificate warning

My Question is pretty straight forward.
Can I somehow bypass this warning in PowerShell?
Right now I'm loading the website with the InternetExplorer.Application ComObject, but I could switch to Invoke-Webrequest etc. if that's needed
EDIT: Additional information
This is just for a function I wrote to open ILO of our HP Servers via PowerShell. that's the function:
function Open-ILO {
param(
[Parameter(
Position = 0,
Mandatory = $true
)]
[string]$computer,
[switch]$show
)
$hash = #{
"Server1" = "http://10.0.0.49/"
"Server2" = "http://10.0.0.50/"
"Server3" = "http://10.0.0.56/"
}
$Wert = $hash.get_item($computer)
if (!$show.IsPresent)
{
$ie = new-object -com InternetExplorer.Application
$ie.Visible = $true
$ie.Navigate($Wert)
}
else { Write-Host $Wert }
}
The issue here isn't PowerShell it's Internet Explorer.
The ILO comes with a self-signed certificate which IE does not trust and so shows you the error. Self-signed certificates are not trusted as they are self-generated and require no verification from a certificate authority.
You can either generate a new cert for the ILO from an internal certificate authority to replace the self signed cert. If you are using Active Directory you will have a CA.
Or you can install the self-signed certificate so that IE trusts it.
Depending on your workplace security policy there might be security concerns with the second option, as your computer will trust content that is signed with that certificate. Most businesses will be ok with this but some with high security might not.

New-SelfSignedCertificate on Win2012 r2 has less parameters

I'm trying to create a self signed certificate with specific encryption parameter values.
On a Win Server 2012 r2 standard running PowerShell 5.0, when I attempt to use
New-SelfSignedCertificate
I receive an error:
New-SelfSignedCertificate : A parameter cannot be found that matches parameter name 'Subject'.
when I attempt to use the -Subject parameter, which in addition to other parameters allowed on my laptop, does not appear in the intellisense.
However on my laptop (Win 10 and PowerShell 5.0) I'm allowed to use these parameters, and I create a self-signed certificate by using the following code
#create a Certificate
# OID for document encryption
$Oid = New-Object System.Security.Cryptography.Oid "1.3.6.1.4.1.311.80.1"
$oidCollection = New-Object System.Security.Cryptography.OidCollection
$oidCollection.Add($oid) > $Null
# Create enhanced key usage extension that allows document encryption
$Ext = New-Object System.Security.Cryptography.X509Certificates.X509EnhancedKeyUsageExtension $oidCollection, $true
$myCert = New-SelfSignedCertificate -Subject 'CN=myservernameasubject' -CertStoreLocation "Cert:\LocalMachine\My" -KeySpec KeyExchange -KeyUsage KeyEncipherment, DataEncipherment -Extension $Ext
Use -DnsName instead without the CN=.
From the PowerShell help:
-DnsName <String>
Specifies one or more DNS names to put into the Subject Alternative Name extension of the certificate when a certificate to be
copied is not specified via the CloneCert parameter. The first DNS
name is also saved as Subject Name and Issuer Name.
The -KeySpec and other related options are, unfortunately, not supported by New-SelfSignedCertificate in Windows Server 2012 R2 and Windows 8.1. Otherwise, you're looking at one of three options to generate the desired certificate; Adapt the COM object based code in the answer to How to create a self-signed certificate using C#? to use in PowerShell, use an external executable like makecert.exe, or generate the certificate/key pair elsewhere and then import it to the certificate store on the other machine.
Update: After further research, it looks like adapting COM based code in PowerShell is a good option. I found a blog entry by Vishal Agarwal, Generating a certificate (self-signed) using powershell and CertEnroll interfaces, that gives the following PowerShell code:
$name = new-object -com "X509Enrollment.CX500DistinguishedName.1"
$name.Encode("CN=TestServer", 0)
$key = new-object -com "X509Enrollment.CX509PrivateKey.1"
$key.ProviderName = "Microsoft RSA SChannel Cryptographic Provider"
$key.KeySpec = 1
$key.Length = 1024
$key.SecurityDescriptor = "D:PAI(A;;0xd01f01ff;;;SY)(A;;0xd01f01ff;;;BA)(A;;0x80120089;;;NS)"
$key.MachineContext = 1
$key.Create()
$serverauthoid = new-object -com "X509Enrollment.CObjectId.1"
$serverauthoid.InitializeFromValue("1.3.6.1.5.5.7.3.1")
$ekuoids = new-object -com "X509Enrollment.CObjectIds.1"
$ekuoids.add($serverauthoid)
$ekuext = new-object -com "X509Enrollment.CX509ExtensionEnhancedKeyUsage.1"
$ekuext.InitializeEncode($ekuoids)
$cert = new-object -com "X509Enrollment.CX509CertificateRequestCertificate.1"
$cert.InitializeFromPrivateKey(2, $key, "")
$cert.Subject = $name
$cert.Issuer = $cert.Subject
$cert.NotBefore = get-date
$cert.NotAfter = $cert.NotBefore.AddDays(90)
$cert.X509Extensions.Add($ekuext)
$cert.Encode()
$enrollment = new-object -com "X509Enrollment.CX509Enrollment.1"
$enrollment.InitializeFromRequest($cert)
$certdata = $enrollment.CreateRequest(0)
$enrollment.InstallResponse(2, $certdata, 0, "")
The following worked just fine for the self-signed option...
New-SelfSignedCertificate -DnsName "*.costoso100.com" -CertStoreLocation "cert:\LocalMachine\My"
I was able to export and setup LDAPS in about 15 minutes.

Export root certificate using powershell

I am installing a client side certificate on a Windows 2012 server through Powershell.
Installing a client side certificate requires two steps:
Installing the certificate on the Personal Store ("my").
Installing the root certificate of that certificate in the Trusted
Root Certification Authority Store.
Step 1 is fairly easy.
However, step 2 is tricky. First, I do not know the length of the chain of the certificate. When doing it by-hand, you need to go to export each certificate in the chain until you reach the root (you can only export the first element of the chain). Then, you install the root certificate in the Trusted Store.
So, my question is: how do you get the root certificate of a certificate?
My idea would be to get the certificate chain and somehow process it until you get the root certificate. Any ideas on how this can be done?
GodEater's advice helped me, by looking at this page https://msdn.microsoft.com/en-us/library/system.security.cryptography.x509certificates(v=vs.110).aspx I figured out how to do it:-
If you import your pkcs12 certificate into System.Security.Cryptography.X509Certificates.X509Certificate2Collection
When you take a look at the object both certificates are there, so simply looping through the object and adding each certificate to the correct store works:-
$fileName = "cert.p12";
$password = "Password"
$certRootStore = "localmachine";
$certStore = "Root";
$certStore2 = "My";
$X509Flags = "PersistKeySet,MachineKeySet";
$pfx = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2Collection;
$pfx.Import($fileName, $Password, $X509Flags);
foreach ($cert in $pfx) {
if ($cert.Subject -match "CN=Your Cert Auth Name") {
$store = New-Object -TypeName System.Security.Cryptography.X509Certificates.X509Store -ArgumentList $certStore,$certRootStore;
$store.Open("MaxAllowed");$store.Add($cert);
$store.Close | Out-Null
}
else {
$store = New-Object -TypeName System.Security.Cryptography.X509Certificates.X509Store -ArgumentList $certStore2,$certRootStore;
$store.Open("MaxAllowed");
$store.Add($cert);
$store.Close | Out-Null
}
}

Can't Bind Certificate to SSL When Imported using .NET API

I've created a self-signed SSL certificate using openssl. When I import the certificate using the .NET APIs, I can't bind it to my website with netsh. I'm importing the certificate with PowerShell:
$Certificate = New-Object 'security.Cryptography.X509Certificates.X509Certificate2' $PathToCertificate
$keyFlags = [Security.Cryptography.X509Certificates.X509KeyStorageFlags]::MachineKeySet
$keyFlags = $keyFlags -bor [Security.Cryptography.X509Certificates.X509KeyStorageFlags]::PersistKeySet
$keyFlags = $keyFlags -bor [Security.Cryptography.X509Certificates.X509KeyStorageFlags]::Exportable
$store = New-Object 'Security.Cryptography.X509Certificates.X509Store' 'My','LocalComputer'
$store.Open( 'ReadWrite' )
$store.Remove( $Certificate )
$store.Add( $Certificate )
$store.Close()
I then use netsh to bind to the certificate:
netsh http add sslcert ipport=0.0.0.0:443 certhash=<thumbprint> appid=<app ID>
Which succeeds the first time run, but fails on subsequent attempt with this error:
SSL Certificate add failed, Error: 1312
A specified logon session does not exist. It may already have been terminated.
However, when I import the certificate manually through the Certificates MMC/snap-in, I never have any problems running the netsh command.
I'm seeing this error on some of our Windows 7 and Windows 2012 R2 computers. Strangely, more than half our computers don't have this problem. Am I adding the cert incorrectly? Could I have generated a bad certificate?
I lied. Looks like I thought I was setting the key storage flags in the code above. Turns out I was loading the certificate in a different part of our script, and it wasn't specifying the correct key storage flags. After correcting my script so it actually does what I claimed it did, everything works.