Certificates issue - windows

The background
We have been using certificates to access a third party service from a windows 2003 box. The certificate recently expired so we went about getting a new one from the third party(Experian). We were provided with two certs to be installed in the "Trusted Root Certication Authorities" and two to be installed in the "Intermediate Certification Authorities" and then the main one that gets installed to the Personal\Certificates.
I know the certs are working when I can access a URL. If I install the certs allowing the cert decide where to install themselves (local Computer or Current User) they install to the current user store. I can then access the URL ... all is well.
The Issue
However I need the certificates to work on a computer level rather than a user level. So I move the certs to the relative Local Computer store locations however this does not work. I now cannot access the URL as any user. I tried deleting them all out and importing them directly into the required local computer cert location... still no joy. I tried installing them as the local admin .... still no joy. Tried granting access to the certs via winhttpcertcfg to everyone/specific users etc, still no joy.
Is it possible that the cert is designed to work for only one user? Is there something I am missing to make this work? Any suggestions would be greatly appreciated.

As admin you should:
run mmc
add snapin for certificates (for local computer)
add root CAs to "Trusted Root Certication Authorities"
add intermediate CAs to "Intermediate Certification Authorities"
add end entity certificate with private key (it should be a .p12 or .pfx file) to Personal\Certificates
grant rights to user that can access the private key using winhttpcertcfg utility
and it should work (at least it did for me every time).
If you don't have private key corresponding to end entity certificate (because you deleted them all) then you need to get a new one from third party(Experian).

Related

Two valid certificates equal one invalid certificate

I'm fairly new to the whole certificate shebang and not a versed Linux admin.
In our company, we run a Windows domain, but we also have some CentOS servers for different services.
On one of said servers we have our ticket system, which is browser based. I want to certify it with a certificate, signed by our Windows root CA, but no matter what I do, the certificate is shown as invalid in the browser.
Funny enough, both certificates in the chain (CA -> server) are shown as valid.
I already did the following:
start certificate process from scratch
tried different certificate formats (.cer, .pem)
verified server cert with root cert
checked validity with openssl (OK)
checked SSL connection with openssl, no issues
added root cert to Linux server trusted CA store
recreated cert chain (of 2)
restarted Apache over and over
reset browser cache
tried different browser
checked DNS entries
checked, if root CA is trusted in Windows (it is)
manually installed server cert in my browser
Both the server cert and the root cert show up as valid in the browser, with the correct relation.
I'm completely lost here. Is there some key step I forgot and not one of the ~30 guides I read forgot to mention?
Any help is greatly appreciated
Your question is missing some information:
Did you check the SSL connection from outside the server?
Did you verify the RootCA cert is inside the cert-store of the server (sometimes it is rejected without error messages)?
I would check the reason for rejecting the certificate in the browser (FireFox is usually more informative than Chrome), and look for the error-code.
Reasons can be (some of which you have already verified):
Wrong certificate properties (missing the required values in the "usage" attribute)
Wrong domain name
Expired certificate
Certificate could not be verified on the client-side
See this image as an example of an error code:
https://user-images.githubusercontent.com/165314/71407838-14f55a00-2634-11ea-8a30-c119d2eb1eb1.png

Running CodeSigned powershell scripts on target machines

Goal: I would like to run my custom powershell scripts that are signed with a valid certificate against target machines with their powershell execution policy set to “AllSigned” without having to install another certificate on the target machine.
Problem: The powershell scripts will not run until I install the public key of the certificate I used to sign the scripts as a trusted publisher (lets call it MyCert.cer) on the target machine.
Possible Misunderstanding: I could be misunderstanding the way code siging works with my “problem” above. However I was under the impression that since windows comes with DigiCert certificates installed by default as “Trusted Root Certification Authorities” (See image below) that all I would need for my signed scripts to work is signing them from a digicert authority.
My Certificate details:
I purchased a code signing certificate from DigiCert. The certificate is valid and has an “EKU” of “Code Signing (1.3.6.1.5.5.7.3.3)”.
Certificate chain:
Final Thoughts: I signed the powershell scripts using the cmdlet “Set-AuthenticodeSignature” and my issued code signing certificate. The scripts will run if I install the MyCert.cer public key as a “Trusted Publisher” on the target machine. However, I would like to not have to touch the target machine and be able to run my code signed scripts against said machine. Is this possible? Have I purchased the wrong certificate for my goal? Or is an entry to the Trusted Publishers certificate store required for running code signed scripts?
Thank you for your time.
Update: Here is the command I used to sign the powershell scripts.
Set-AuthenticodeSignature -Certificate $cert -FilePath $FileToSign -IncludeChain all
I wanted to let everyone know that I did include "All" for the includeChain. I have also tried using digiCerts timestamp server for the -TimestampServer parameter. However adding the timestamp does not make a difference for running the script. The -TimestampServer parameter as to my understanding is for when a certificate expires and need to be re-validated. However the certificate I am using is still current and not expired.
You are finding the intended behavior of the AllSigned Execution Policy. From Get-Help about_Execution_Policies you will see:
AllSigned
- Scripts can run.
- Requires that all scripts and configuration files
be signed by a trusted publisher, including scripts
that you write on the local computer.
The short answer is that you'll need to trust your cert on all your computers (the easy way to do this is with Group Policy). The Group Policy Object that you'll write will modify Computer Configuration\Windows Settings\Security Settings\Public Key Policies\Trusted Publishers and then you'll need to follow the instructions in the Certificate Import Wizard. The key thing here is that the certificate can be traced back to the Trusted Root Certification Authorities in your organization, so it's a very good thing that you bought a Digicert certificate and that your organization trusts Digicert certs.
So why does Digicert show up under Trusted Root Certification Authorities? The answer here is pretty simple. It means that your organization recognizes Digicert certificates and allows them to be trusted. This doesn't mean that every single Digicert certificate automatically gets a pass, it just means that they are allowed to be installed to your domain. I am gonna pick on Comodo, since they're close alphabetically and they don't show up in your screenshot. Because Comodo also gives out digital certificates, if I were to sign my scripts with my Comodo cert and try and install that certificate across your domain, it wouldn't stick since Comodo is not a Trusted Root Certification Authority in your domain.
I hope that helps explain what's going on!

X509 Certificate Access to private Key Denied

I am importing X509 from PKCS #12 file (using PFXImportCertStore Cryptographic API) in Computer's Personal Store.
Problem:
Any process running under "Local Service" account or any non-admin account can not access privates key (restricted to Admin user by Windows).
How to give access to private keys of a certificate to non-admin users and local service?
Note:
Since multiple process use certificates, I preferred using Computers store instead user's store.
This is a tricky one with some pitfalls. I had the same problem and was close to despair, when I finally found the remark which saved me in this post
I succeeded to do this for a local service running under the Network Service account.
First, there is the option to grant other users access to the private key of a certificate in the MS certificate store. Already this I'd classify as druid knowledge: this option is available in the context menu (right click the certificate), but only if the certificate resides in the localMachine\Personal store. There, in the entry All tasks, you will find the sub entry Manage Private Keys. This is not available in other stores, not even in the CurrentUser\Personal store.
This entry opens a dialog which allows you to add access rights to the certificate for other users. Here, the next hurdle waits for you: the default setting is to search for users in the domain, not on the local machine. The desired user may not be found, unless you change the search filter.
To this result I came very fast by googling, but it did not help. I could get the service to run, but only if I changed the service user to the logon account, which is not what I wanted (this leads, btw, to a workaround: create a local user account for services and import the certificate from within that user account. You can then place the certificate in almost any store and it will work fine)
This is where the post cited above comes in, the last hurdle for me: the procedure described above seems to work only if you import the certificate into the certificate store from within the MMC snapin. Select the store localMachine\Personal and use the context menu to import the certificate in question. (I chose to make the private key exportable, this may or may not be relevant here). If you import the certificate by double clicking on it in the file system, it will be imported into some store in the Current User location. I used to do this and then move it into the localMachine\Personal folder and changed the access right -- this did never work for me. Only after importing it from within localMachine\Personal in the MMC certificate snap-in it worked immediately...
(Also note that you have to place the certificate into a store which can be found by the service user. Your current user stores usually does not allow this, so localMachine is the better choice, anyway)
I don't know whether you can move the certificate around afterwards, but that's easy to check in the system..

How to add a certificate to the default Firefox profile on RHEL 6?

I want to add a certificate to the CAs that Firefox trusts, before any user profile exists, on RHEL 6 (or CentOS, or Scientific Linux... would expect it to be the same).
I know how to add a certificate to an existing user profile. I don't need to do that at all. I want to do this during a kickstart (unattended, don't want to start X), so I can't really start up Firefox for the user, create a profile, and add it the normal way. I need the certificate to be there the first time a user on the system opens Firefox.
I know that there is no system store of CAs that Firefox reads in addition to the user profile (though it evidently has an internal store somewhere as it trusts way more than what's in the user profile). That's OK, I just want the user profile to be created with the certificate already added.
I have seen some indication that this is possible, or was possible. E.g. https://support.mozilla.org/en-US/questions/967376 indicates where to put the cert8.db under Windows; https://askubuntu.com/questions/244582/add-certificate-authorities-system-wide-on-firefox/369858#369858 indicates that /etc/firefox-3.0/profile worked on Ubuntu (there is no such location under RHEL).
I can't determine where to do this under RHEL 6. I've tried adding a certificate database using certutil under the following directories, which were owned by the firefox RPM and seemed promising:
/usr/lib64/firefox/browser
/usr/lib64/firefox/browser/defaults
/usr/lib64/firefox/defaults
... but still, when a user profile is created, certutil indicates the same contents:
certutil -L -d .mozilla/firefox/*.default/
Certificate Nickname Trust Attributes
SSL,S/MIME,JAR/XPI
VeriSign Class 3 Secure Server CA - G3 ,,
DigiCert High Assurance EV CA-1 ,,
Google Internet Authority G2 ,,
I can't even tell where those certificates are coming from; it might be helpful to do even that much.
I do not think that you can do what you are trying to do without altering a user's defaults. The reason why I say this is because of how Mozilla bundles their default set of Root CA's. see How Mozilla Products Respond to User Changes of Root Certificates
the Mozilla Foundation and its wholly-owned subsidiary the Mozilla Corporation include with such software a default set of X.509v3 certificates for various Certification Authorities (CAs).
However with that said you could use Skeleton Files to define a set of defaults for all of your users, and follow the same process that Mozilla outlines, by simply providing your defaults as a thing each user already has when their profile is created.

PrivateKey trust permissions for local machine "Trusted roots" certificates

I have a certificate that has to be imported into Certificates/Trusted Root Certification Authorities and has a corresponding private key.
To actually access the key from code you need to set private key permissions to grant full access to particular IIS application pool. I totally understand that but the problem is that this can only be set on personal certificates and not trusted root ones.
I've tried adding the same certificate to Personal store and the following code doesn't break:
X509Store store = new X509Store(StoreName.Root, StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadOnly);
foreach (X509Certificate2 cert in store.Certificates)
{
if (cert.HasPrivateKey)
{
// access private key here
}
}
store.Close();
Setting permissions on certificate in personal store works if I change StoreName.Root to StoreName.My. I'm able to access it there. But I'm not able to access it in root. It just says:
Keyset does not exist
Any suggestions?
Additional information
If I set my application pools identity to Local System (which has total permissions over my machine) I can successfully access private key. So the main question is how do I set permissions on my application pool identity to have access to private keys for certificates in the Trusted Root store.
Why trusted root store and not personal?
I have a pre-built assembly that accesses this certificate in this particular store, so simply placing the certificate in Personal store won't do the trick for me. That's why setting trust permissions on private keys of trusted root certificates is imperative.
I haven't tried this with the Trusted Root Certification Authorities but what I have found is the simplest thing to do with other Certificate Stores is to drag and drop the certificate into the Personal Store and then set permissions and then drag and drop back to the original certificate store. In your case the Trusted Root Certification Authorities.
Steps using Certificates MMC:
Import certificate to the store you want it and mark keys as exportable. (You might be able to bypass this and import directly to the Personal Store, but I haven't tried.)
Drag and drop the imported cert to the Personal Store.
Right click the certificate in the Personal Store and in the context menu, click "All Tasks", then in the submenu click on "Manage Private Keys". Set the appropriate permissions according to your app pool as referenced in step 1.
After permissions have been set, drag and drop the certificate back to the original store (in your case the Trusted Root Certification Authorities).
Solution
It is possible to set trust permissions on certificates other than those in Personal certificate store, but you can't set permissions via MMC. At least not directly on the store that is. Accepted answer shows a simplified approach with moving certificates around to achieve the same result.
You have to do it this way...
Getting the tool
Get WF_WCF_Samples file from Microsoft. This is a self extracting archive, but you won't need to extract everything. So...
Open the file with any archiver tool and only extract FindPrivateKey solution/project
Open in Visual Studio and compile it.
Finding your private key
Open MMC and add Certificates snap-in. Make sure you select Computer and Local Machine when adding it.
Select the store that has your certificate with private key.
Open private key and copy its Thumbprint
Open command prompt and navigate to the folder where you compiled your FindPrivateKey tool
Enter this command
FindPrivateKey YourStoreName LocalMachine -t "ThumbprintWithSpaces" -a
ie.
FindPrivateKey Root LocalMachine -t "83 45 22 ..." -a
Copy file along with path (it will liekly span over two lines so copy to Notepad and concatenate)
Grant certificate trust
open command prompt and enter:
icacls "FullPathOfYourPrivateKey" /grant:r "UserFQDN":f
ie.
icacls "c:\ProgramData..." /grant:r "IIS AppPool\ASP.NET v4.0":f
Done.
This will grant certificate private key full trust to your user (in my case above it's application pool identity) so you can use the key to sign data or do whatever you need to do with it.
In case you don't want full permissions, you can easily change the last part after colon. It can have many different settings, so I urge you to check icacls command help.
If you are using Windows Server 2003, you'll notice that you don't get the Manage Private Keys task under your certificate.
If you install Microsoft WSE 2.0 on to your machine, you can use a tool called X509 Certificate Tool. Just search for your cert, its more than likely in (or should be) in Local Machine / Personal Store.
NOTE: if you have your cert in Current User / Personal Store (which often is the default), it will only be accessible to the user that is currently logged in, which means if you want your webserver to access it, it can't without changing permissions to your AppPool.
You should be able to change the permissions to the private key very easily, by default, your AppPool on your webserver will be using NETWORK SERVICE to run your web application. So just add NETWORK SERVICE to the security and by default it will set the Read and Read / Execute permissions which is sufficient for your BouncyCastle, etc, to read the private key so you can sign your document.
Hope this helps.

Resources