Add Mozilla root certs to Windows without admin - windows

I want to add Mozilla's root certs to Windows 7 without admin privileges.
Is there a straight forward way to add the root certificates into the current user's certificate store? I'd prefer to use Windows' native tools, without relying on something I'd have to download.
Some resources that looked promising.
Pre-converted PEM files by CURL - The Mozilla root certs converted to PEM and hosted by cURL. Here's a direct link to the PEM Encoded root certs
Verified HTTPs in Ruby - A general overview of how to obtain the root certificates.
How to get root certs for cURL - explains how to generate the PEM file from the Mozilla certificates yourself.
How to Import Certificates using Powershell - a ranting overview of how to install certificates that seems more complex than it ought to be.

I ended making a powershell script to do it.
VERIFY THIS CODE BEFORE RUNNING IT. It's adding all of the certificate authorities from http://curl.haxx.se/ca/cacert.pem to the current user's TRUSTED ROOT certificate store.
To run it in a single command, paste the following into a command prompt:
#powershell -NoProfile -ExecutionPolicy unrestricted -Command "iex ((new-object net.webclient).DownloadString('https://raw.github.com/jschaf/install-mozilla-certs/master/install-mozilla-cert.ps1'))"
Here's the Github link: https://github.com/jschaf/install-mozilla-certs
And the source:
# Variables
$url = "http://curl.haxx.se/ca/cacert.pem"
# Download the certificates
Write-Host "Downloading Mozilla certificates from $url."
$downloader = New-Object System.Net.WebClient
$rawcerts = $downloader.DownloadString("http://curl.haxx.se/ca/cacert.pem")
# Remove headers and begin/end delimiters and convert into a byte
# stream
$header = "-----BEGIN CERTIFICATE-----`n"
$footer = "`n-----END CERTIFICATE-----"
$match_string = "(?s)$header(.*?)$footer"
$certs_matches = Select-String $match_string -input $rawcerts -AllMatches
$certs_base64 = $certs_matches.matches | %{ $_.Groups[1].Value }
$certs_bytes = $certs_base64 | %{ ,[System.Text.Encoding]::UTF8.GetBytes($_) }
# Install the certificates
$user_root_cert_store = Get-Item Cert:\CurrentUser\Root
$user_root_cert_store.Open("ReadWrite")
foreach ($c in $certs_bytes) {
$cert = new-object System.Security.Cryptography.X509Certificates.X509Certificate2(,$c)
$user_root_cert_store.Add($cert)
}
$user_root_cert_store.Close()
Write-Host "Finished installing all certificates."
One annoying thing is that Windows will prompt for yes/no for every certificate. Since it's installing 158 certificates this gets old quick. If anyone knows how to prevent confirmation let me know or drop a pull request.

Related

Add Windows Credentials using PowerShell & cmdkey

I am trying to use credentials from some UI prompted to add Windows credentials using cmdkey:
$sessionCredential = $host.ui.PromptForCredential("Need credentials", "Please enter your user name and password.", "", "Server Crdentials")
$ps = ConvertFrom-SecureString -SecureString $sessionCredential.password
cmdkey.exe /add:server1 /user:$($sessionCredential.UserName) /pass:$($ps)
The credentials are added correctly, but the password is not.
What can I do?
Use the CredentialManager PowerShell module. It saves the password in the same place as cmdkey, but it can take PSCredential objects directly without needing to convert to text.
Import-Module CredentialManager
# Get the credential from the user with a windows credentials prompt:
$SessionCredential = Get-Credential -Message 'Please enter your server credentials'
# Save the credential object directly without unwrapping it:
New-StoredCredential -Credentials $SessionCredential -Target ServerCredentials -Persist Enterprise `
-Comment "Server Credentials for $($SessionCredential.UserName)" > $null
# Open the credential later
$SavedCred = Get-StoredCredential -Target ServerCredentials
# Delete if needed
Remove-StoredCredential -Target ServerCredentials
cmdkey /pass:$($ps) is prone to errors due to PowerShell garbling password characters.
Apparently, the problem is ConvertFrom-SecureString is returning an encrypted standard string, ConvertFrom-SecureString.
And the option to get plain text is not available on PowerShell 5.1.
I found the correct convert here.
I understand it is not secured. It is used inside secured clients.
See fixed code below:
$sessionCredential = $host.ui.PromptForCredential("Need credentials", "Please enter your user name and password.", "", "Server Crdentials")
$mpass = [System.Net.NetworkCredential]::new("",$sessionCredential.password).Password
cmdkey.exe /add:server1 /user:$($sessionCredential.UserName) /pass:$($mpass)
Cpt.Whale's answer worked like a charm. The only caveat was the need to copy/distribute the CredentialManager module before using it.

How to request a exportable certificate using PowerShell?

Refer to Get-Certificate
I tried to request a certificate using PowerShell, it worked but the certificate is not exportable, here is my command:
Get-Certificate -Template "MyComputer" -SubjectName "CN=corey.com" -CertStoreLocation cert:\LocalMachine\My
When I try to export the certificate, it failed.
Export-PfxCertificate -Cert cert:\LocalMachine\My\$Thumbprint -FilePath C:\corey.com.pfx -Password $mypwd
The error message:
Export-PfxCertificate: Cannot export non-exportable private key.
I can't find any parameter like Exportable or property for me to use with Get-Certificate command. Is there any way to request/make a certificate exportable by using PowerShell?
Cause there is no parameter to make it exportable when using Get-Certificate, so I use certreq as a replacement to achieve my goal and post here hoping that could help someone else.
Firstly, prepare an information file, and set Exportable as TRUE.
$file = #'
[NewRequest]
Subject = "CN=corey.com"
KeyLength = 2048
Exportable = TRUE
[RequestAttributes]
CertificateTemplate = "MyTemplate"
'#
Set-Content temp.inf $file
Secondly, type the following commands.
# create a new request from an .inf file
certreq -new temp.inf temp.req
# submit a request to the certificate authority
certreq -submit -config CAHostName\CAName temp.req temp.cer
# accept and install a response to a certificate request
certreq -accept temp.cer
Finally, export the certificate and assign a password for it.
$mypwd = ConvertTo-SecureString -String $password -Force -AsPlainText
Export-PfxCertificate -Cert cert:\LocalMachine\My\$Thumbprint -FilePath C:\corey.com.pfx -Password $mypwd
For more details, please see certreq - Microsoft Docs

Powershell: The access to the certificate store returns an empty EnhancedKeyUsageList

When I run the following script line on my Windows 7 32bit (PS version 3.0) I get an empty EnhancedKeyUsageList (I see only empty curly brackets {}).
On a Windows 10 machine with PS 5.x I get the right result.
What am I doing wrong?
Get-ChildItem -Path Cert:\LocalMachine\My | Format-List -Property *
A certificate with EnhancedKeyUsage set to ALL will have this as empty if queried . Open the certificate store via MMC and check the same for the certificate you are getting EKU as null.

FTP: copy, check integrity and delete

I am looking for a way to connect to a remote server with ftp or lftp and make sure the following steps:
Copy files from FTP server to my local machine.
Check if the downloaded files are fine (i.e. md5checksum).
If the download was fine then delete the downloaded files from the FTP server.
This routine will be executed each day from my local machine. What would be the best option to do this? Is there a tool that makes abstraction of all the 3 steps ?
I am running Linux on both client and server machines.
Update: Additionally, I have also a text file that contains the association between the files on the FTPserver and their MD5sum. They were computed at the FTP server side.
First, make sure your remote server supports the checksum calculation at all. Many do not. I believe there's even no standard FTP command to calculate a checksum of a remote file. There were many proposals and there are many proprietary solutions.
The latest proposal is:
https://datatracker.ietf.org/doc/html/draft-bryan-ftpext-hash-02
So even if your server supports checksum calculation, you have to find a client that supports the same command.
Some of the commands that can be used to calculate checksum are: XSHA1, XSHA256, XSHA512, XMD5, MD5, XCRC and HASH.
You can test that with WinSCP. The WinSCP supports all the previously mentioned commands. Test its checksum calculation function or the checksum scripting command. If they work, enable logging and check, what command and what syntax WinSCP uses against your server.
Neither the ftp (neither Windows nor *nix version) nor the lftp support checksum calculation, let alone automatic verification of downloaded file.
I'm not even aware of any other client that can automatically verify downloaded file.
You can definitely script it with a help of some feature-rich client.
I've wrote this answer before OP specified that he/she is on Linux. I'm keeping the Windows solution in case it helps someone else.
On Windows, you could script it with PowerShell using WinSCP .NET assembly.
param (
$sessionUrl = "ftp://username:password#example.com/",
[Parameter(Mandatory)]
$localPath,
[Parameter(Mandatory)]
$remotePath,
[Switch]
$pause = $False
)
try
{
# Load WinSCP .NET assembly
Add-Type -Path (Join-Path $PSScriptRoot "WinSCPnet.dll")
# Setup session options
$sessionOptions = New-Object WinSCP.SessionOptions
$sessionOptions.ParseUrl($sessionUrl);
$session = New-Object WinSCP.Session
try
{
# Connect
$session.Open($sessionOptions)
Write-Host "Downloading $remotePath to $localPath..."
$session.GetFiles($remotePath, $localPath).Check();
# Calculate remote file checksum
$buf = $session.CalculateFileChecksum("sha-1", $remotePath)
$remoteChecksum = [BitConverter]::ToString($buf)
Write-Host "Remote file checksum: $remoteChecksum"
# Calculate local file checksum
$sha1 = [System.Security.Cryptography.SHA1]::Create()
$localStream = [System.IO.File]::OpenRead($localPath)
$localChecksum = [BitConverter]::ToString($sha1.ComputeHash($localStream))
Write-Host "Downloaded file checksum: $localChecksum"
# Compare cheksums
if ($localChecksum -eq $remoteChecksum)
{
Write-Host "Match, deleting remote file"
$session.RemoveFiles($remotePath).Check();
$result = 0
}
else
{
Write-Host "Does NOT match"
$result = 1
}
}
finally
{
# Disconnect, clean up
$session.Dispose()
}
}
catch [Exception]
{
Write-Host "Error: $($_.Exception.Message)"
$result = 1
}
# Pause if -pause switch was used
if ($pause)
{
Write-Host "Press any key to exit..."
[System.Console]::ReadKey() | Out-Null
}
exit $result
You can run it like:
powershell -file checksum.ps1 -remotePath ./file.dat -localPath C:\path\file.dat
This is partially based on WinSCP example for Verifying checksum of a remote file against a local file over SFTP/FTP protocol.
(I'm the author on WinSCP)
The question was later edited to say that OP has a text file with a checksum. That makes it a completely different question. Just download the file, calculate local checksum and compare it to the checksum you have in the text file. If they match, delete the remote file.
That's a long shot, but if the server supports php, you can exploit that.
Save the following as a php file (say, check.php), in the same folder as your name_of_file.txt file:
<? php
echo md5_file('name_of_file.txt');
php>
Then, visit the page check.php, and you should get the md5 hash of your file.
Related questions:
Calculate file checksum in FTP server using Apache FtpClient
How to perform checksums during a SFTP file transfer for data integrity?
https://serverfault.com/q/98597/401691

Windows / Perl / Net::SSLeay / OpenSSL: What locations are CA certificates loaded from?

Here's a program that does an HTTPS request, with some code at the start that I'm going to explain below:
use 5.012;
use LWP::UserAgent;
use HTTP::Request::Common;
use Net::SSLeay;
BEGIN {
return unless $^O eq 'MSWin32'; # only needed on Windows
print STDERR "attempting to set HTTPS_CA_FILE to PEM file path\n";
require Mozilla::CA; # load module to determine PEM file path
my $pemfile = do {
my $path = $INC{ 'Mozilla/CA.pm' };
$path =~ s#\.pm$#/cacert.pem#;
$path;
};
if ( -f $pemfile ) {
$ENV{HTTPS_CA_FILE} = $pemfile;
print STDERR "HTTPS_CA_FILE set to $pemfile\n";
}
else {
warn "PEM file $pemfile missing";
}
} # ==========================================================================
$Net::SSLeay::trace = 2;
my $ua = LWP::UserAgent->new;
my $req = GET 'https://client.billsafe.de/';
my $rsp = $ua->request( $req );
say $rsp->is_success ? 'success' : 'failure';
say $rsp->status_line;
say '=================';
say substr $rsp->decoded_content, 0, 200;
say '=================';
# possibly relevant module versions
for ( qw/Net::SSLeay Crypt::SSLeay LWP::Protocol::https Mozilla::CA/ ) {
no strict 'refs';
say $_, "\t", ${"${_}::VERSION"}
}
The code at the beginning sets the environment variable HTTPS_CA_FILE to the value of the PEM file cacert.pem from Mozilla::CA that gets loaded by default (I checked using procmon.exe, the file is fully read by default).
The reason for doing this apparently nonsensical setting is that we have some Windows machines (Windows Server 2008) where the SSL setup fails with certificate verify failed when the environment variable is not set. It is a mystery to us why this is so. And it works fine on other Windows machines with identical versions for Net::SSLeay, LWP::Protocol::https and Mozilla::CA.
Our module versions are:
Net::SSLeay 1.36
Crypt::SSLeay -/-
LWP::Protocol::https 6.02
Mozilla::CA 20110409
Now the question: Are there other places, apart from cacert.pem, that root certificates are loaded from in this constellation (Windows, Perl, Net::SSLeay)? If so, what are they? Where can I read up on it?
Update
The OpenSSL docs do not mention any certificate store other than a plain file and a plain directory:
SSL_CTX_set_cert_store(3)
SSL_CTX_load_verify_locations(3)
The Windows C API functions used to open the system certificate store are the following:
CertOpenStore
CertOpenSystemStore
I checked out the OpenSSL HEAD from CVS. The CertOpenStore function is indeed used in engines/e_capi.c. I haven't investigated further to find out what is used to access a store in the OpenSSL versions on the servers in question.
If you do a web search you'll see that a couple of people have wondered whether OpenSSL can access the Windows certificate store directly, or have proposed to patch OpenSSL accordingly. There's also this recent issue on the TortoiseSVN list (Windows Certificate Store / OpenSSL CAPI). Some more research needed to find out what's the matter here.
Since LWP 6.00 you can pass an ssl_opts hashref to new specifying the certificate files amongst other options:
my $ua = LWP::UserAgent->new(
ssl_opts => {
verify_hostname => 1,
SSL_cert_file => $ssl_cert_file,
SSL_key_file => $ssl_key_file,
},
);

Resources