51

I want to add some root CAs that doesn't come with the default firefox on Ubuntu, but I don't know how.

I tried adding them to the local certificates with certutil, but it didn't work. It messed up my certificates database.

$ certutil -A -d .mozilla/firefox/kek3dogy.default/ -i /usr/local/share/ca-certificates/FNMT_ACRAIZ.crt -n "Certificado Raiz FNMT" -t "TCu,Cuw,Tuw"

and then

$ certutil -L -d .mozilla/firefox/kek3dogy.default/

Certificate Nickname                                         Trust Attributes
                                                             SSL,S/MIME,JAR/XPI

Go Daddy Secure Certification Authority                      ,,   
VeriSign Class 3 Secure Server CA - G3                       ,,   
VeriSign Class 3 Extended Validation SSL CA                  ,,   
DigiCert High Assurance CA-3                                 ,,   
GlobalSign Domain Validation CA - G2                         ,,   
GeoTrust SSL CA                                              ,,   
StartCom Class 2 Primary Intermediate Server CA              ,,   
Google Internet Authority                                    ,,   
Certificado Raiz FNMT                                        CT,C,c
USERTrust Legacy Secure Server CA                            ,,   
HP Jetdirect 2B0EAD20                                        ,,   
Akamai Subordinate CA 3                                      ,,   
VeriSign, Inc.                                               ,,   
Thawte SGC CA                                                ,,   
VeriSign Class 3 Secure Server CA - G2                       ,,

The certificate won't show up on Firefox. I tried this several times, even deleting the profile, and it showed up once on the Firefox interface, but completely empty.

Anyways, that's only for a user, and I want to add them system-wide. Is there a system-wide database I can modify? How?

If there is no system-wide database I can modify, I can rely on a X start script (as /etc/X11/Xsession.d/ ones, or a script called by the xdg autostart system on /etc/xdg/autostart/) to modify the user profile at session start, but I need a solution that works. I can't even load certificates on the user profiles from the command line now!

11 Answers11

33

The problem here is that Firefox does not have a 'central' location where it looks for certificates. It just looks into the current profile. That's why modifying /usr/share/ca-certificates or other similar directories won't work with Firefox. This is something that has been requested for years; see issues 620373, 449498 and 454036 (and probably there are many others).

So you are left with just two kind of solutions: either modify each profile, or modify the behaviour of Firefox. I know this is not what you are looking for, but there are no ways because Firefox only looks at users' profiles.

Having said that, the solution I would choose is using hard or symbolic links, specifically I'd go with hardlinks. This solution is surely the easiest and probably the better, though I don't have enough information to judge.

What you have to do is basically removing each cert8.db and key3.db files for each profile and replace them with links to the "most complete" cert8.db and key3.db. If you go with hardlinks, the original cert8.db and key3.db will be indistinguishable from the new ones.

Remember to adjust permissions to fit your needs. Most likely, you will need to chmod a+rw so that everybody will be able to add/remove a certificate. If you want only certain users to be able to add/remove certificates, you can create a group, assign the two databases to that group and give +w permission just to the group.

18

The easiest way is to import the certificate into a sample firefox-profile and then copy the cert8.db to the users you want equip with the certificate.

First import the certificate by hand into the firefox profile of the sample-user. Then copy

/home/${USER}/.mozilla/firefox/${randomalphanum}.default/cert8.db

into the users firefox-profiles. That's it. If you want to make sure, that new users get the certificate automatically, copy cert8.db to:

/etc/firefox-3.0/profile

Here is an alternative way that doesn't override the existing certificates: [bash fragment for linux systems]

certificateFile="MyCa.cert.pem"
certificateName="MyCA Name" 
for certDB in $(find  ~/.mozilla* ~/.thunderbird -name "cert8.db")
do
  certDir=$(dirname ${certDB});
  #log "mozilla certificate" "install '${certificateName}' in ${certDir}"
 certutil -A -n "${certificateName}" -t "TCu,Cuw,Tuw" -i ${certificateFile} -d ${certDir}
done

You may find certutil in the libnss3-tools package (debian/ubuntu).

See also: Programmatic import of CA Certificate

Source: Programmatically Install Certificate into Mozilla

davelupt
  • 177
TomKat
  • 3,878
15

Found this solution to add certificates to firefox on ubuntu :

https://github.com/mozilla/policy-templates/#proxy

Simply need to add this file to :

/usr/lib/firefox/distribution/

touch policies.json

In policies.json add:

{
"policies": {
"Certificates": {
    "ImportEnterpriseRoots": true,
    "Install": [
               "somecert1.crt",
               "usr/local/share/ca-certificates/somecert1.crt"
               ]
         }
    }
}

The install part is first the name of the cert and then the path. And restart firefox. If something doesn't work try resetting firefox as if you have set something before it can stuck it.

This method works good without certutil.

14

Contrary to popular belief, you can get Firefox to look at the system certificates instead its own hard-coded set.

To do this, you will want to use a package called p11-kit. p11-kit provides a drop-in replacement for libnssckbi.so, the shared library that contains the hardcoded set of certificates. The p11-kit version instead reads the certificates from the system certificate store.

Since Firefox ships with its own version of libnssckbi.so, you'll need to track it down and replace it instead of the version provided in libnss3:

sudo mv /usr/lib/firefox/libnssckbi.so /usr/lib/firefox/libnssckbi.so.bak
sudo ln -s /usr/lib/x86_64-linux-gnu/pkcs11/p11-kit-trust.so /usr/lib/firefox/libnssckbi.so

Next, delete the ~/.pki directory to get Firefox to refresh its certificate database (causing it to pull in the system certs) upon restarting Firefox. Note: this will delete any existing certificates in the store, so if have custom ones that you added manually, you might want to back up that folder and then re-import them.

wheeler
  • 752
  • 1
  • 11
  • 18
4

Beginning with Firefox 64, Mozilla says, that an own "enterprise CA" can be imported from those system paths in Linux:

  • /usr/lib/mozilla/certificates
  • /usr/lib64/mozilla/certificates

Those paths do not exist by default in Ubuntu, but can be added manually.

Additionally, you have to name each certificate in the file /etc/firefox/policies/policies.json, so that it gets imported automatically:

{
    "policies": {
        "Certificates": {
            "ImportEnterpriseRoots": true,
            "Install": [
                "example.crt",
                "/specific/folder/another-example.crt"
            ]
       }
    }
}

In this case, a certificate file named "example.crt" in either of the named default directories will be added when firefox restarts.

As Batchen Regev showed in his answer, you can also point to a file with an absolute path. (This way the .NET core development server on linux is also adding the localhost certificate).

References:

sudormrfbin
  • 125
  • 1
  • 9
minni
  • 171
  • 3
2

I found out that most of the time and by default if not configured otherwise Firefox uses legacy security databases (cert8.db, key3.db, and secmod.db) that means you will need to use a different command line to inject the certificate into the correct database that Firefox use. (see more from the man of certutil)

so if your system uses the default data base the command should go like this: (dbm)

certutil -A -n "Description Name" -t "CT,C,C" -d dbm:/home/<username>/.mozilla/firefox/<default folder>/ -i certificate.crt

otherwise it should be like this: (sql)

certutil -A -n "Description Name" -t "CT,C,C" -d sql:/home/<username>/.mozilla/firefox/<default folder>/ -i certificate.crt

from man certutil:

-d [prefix]directory
Specify the database directory containing the certificate and key
database files.

certutil supports two types of databases: the legacy security databases
(cert8.db, key3.db, and secmod.db) and new SQLite databases (cert9.db,
key4.db, and pkcs11.txt).

NSS recognizes the following prefixes:

·   sql: requests the newer database

·   dbm: requests the legacy database

If no prefix is specified the default type is retrieved from
NSS_DEFAUL
1

TL;DR: Create a policy file (/etc/firefox/policies/policy.json) with the following contents:

{
  "policies": {
    "Certificates": {
      "Install": ["/path/to/cert.pem", "/path/to/cert2.der"]
    }
  }
}

Firefox 120+ on Windows and MacOS loads certificates from the system trust store, but unfortunately such a mechanism does not exist on Linux.

On Firefox 64+, we can use a policy to circumvent this issue, but it does not automatically import certificates from the system store; they have to be specified manually. It involves creating a policy.json file:

On Linux, the file goes into firefox/distribution, where firefox is the installation directory for Firefox, which varies by distribution or you can specify system-wide policy by placing the file in /etc/firefox/policies/.

Note that if you're using Firefox ESR, the path may be /etc/firefox-esr/policies.

We can now use the Certificates | Install policy to specify certificates to be added to Firefox. The template is:

{
  "policies": {
    "Certificates": {
      "Install": ["cert1.der", "/home/username/cert2.pem"]
    }
  }
}

If only the filename is provided, Firefox will search the following directories for it:

  • /usr/lib/mozilla/certificates/
  • /usr/lib64/mozilla/certificates/
  • ~/.mozilla/certificates/

An absolute path can also be used from Firefox 65+.


Reference: https://mozilla.github.io/policy-templates/#certificates--install

sudormrfbin
  • 125
  • 1
  • 9
1

The answers here are mostly stale, and adding the Certificates->Install entry to policies.json did not work for me. However, the following did work for me with Firefox 129.0.2 on Ubuntu 24.04.1. It is also part of their most recent official documentation on the matter, which conspicuously omits the Certificates section of the json file.

  1. Confirm you have p11-kit installed with which p11-kit. Install it if missing with sudo apt install p11-kit (should be unnecessary as it comes with Ubuntu 24.04.1).
  2. Run p11-kit list-modules to find the path to the library module p11-kit-trust. On my machine, it's /usr/lib/x86_64-linux-gnu/pkcs11/p11-kit-trust.so.
  3. Create the file (and path, if missing) /etc/firefox/policies/policies.json.
  4. Add the following to it:
    {
      "policies": {
        "SecurityDevices": {
          "p11-kit-trust": "/usr/lib/x86_64-linux-gnu/pkcs11/p11-kit-trust.so"
        }
      }
    }
    
    Save and close.
  5. Restart Firefox.

It should now see any certificates you added to the main store. For a quick refresher on how to do that, see here.

Here is a BASH script to do it all the above steps (except installing the certs) in one fell swoop:

#!/bin/bash

Check if the script is run as root

if [ "$EUID" -ne 0 ]; then echo "Please run as root (e.g., using sudo)." exit 1 fi

Step 1: Confirm p11-kit is installed

echo "Checking if p11-kit is installed..." if ! command -v p11-kit &>/dev/null; then echo "p11-kit is not installed. Installing now..." apt update && apt install -y p11-kit else echo "p11-kit is already installed." fi

Step 2: Locate the p11-kit-trust module

echo "Locating p11-kit-trust module..." P11_TRUST_MODULE=$(p11-kit list-modules | grep -Eo '/.*/p11-kit-trust.so' | head -n 1)

if [ -z "$P11_TRUST_MODULE" ]; then echo "p11-kit-trust module not found. Please verify your p11-kit installation." exit 1 else echo "Found p11-kit-trust module at: $P11_TRUST_MODULE" fi

Step 3: Create the Firefox policies.json file

POLICIES_DIR="/etc/firefox/policies" POLICIES_FILE="$POLICIES_DIR/policies.json"

echo "Creating Firefox policies configuration..." mkdir -p "$POLICIES_DIR"

cat >"$POLICIES_FILE" <<EOL { "policies": { "SecurityDevices": { "p11-kit-trust": "$P11_TRUST_MODULE" } } } EOL

echo "Firefox policies.json file has been created at $POLICIES_FILE."

Step 4: Restart Firefox message

echo echo "Configuration complete! Please restart Firefox for the changes to take effect."

exit 0

And a one-liner of the above to paste into terminal, if that's your preferred route:

sudo bash -c 'apt install -y p11-kit && P11_TRUST_MODULE=$(p11-kit \
list-modules | grep -Eo "/.*/p11-kit-trust\.so" | head -n 1) && mkdir -p \
/etc/firefox/policies && echo -e \
"{\n\t\"policies\": {\n\t\t\"SecurityDevices\": {\n\t\t\t\"p11-kit-trust\": \"$P11_TRUST_MODULE\"\n\t\t}\n\t}\n}" \
> /etc/firefox/policies/policies.json && echo \
"Configuration complete! Restart Firefox to apply changes."'
1

One of the features of the CCK Wizard Firefox add-on is importing CA certs. I use this add-on to create a custom add-on that includes a company CA Cert. I then package the custom xpi in a .deb on the internal repository that all the workstations get updates from.

CCK Wizard

EDIT: In order to package the xpi for Ubuntu, you need to create a package that includes the directory /usr/lib/firefox-addons/extensions/[addon-name@servername] and unzip the entire contents of the xpi into this directory. For instance if you name your addon foobarbaz and the server you have it set to update from (if you were to enable that function) is intranet.example.com, then the directory would be foobarbaz@intranet.example.com. I never enable the auto update, but instead update the deb in the repo.

1

Firefox works after a clean installation. If certificate database in cert8.db is deleted, it is regenerated on next Firefox start. This strongly suggests that there is a system-wide default storage of CA certs.

Firefox's source code shows that built-in CA certs are in fact hard-coded into firefox executable. They reside in security/nss/lib/ckfw/builtins/certdata.txt

So there is no way to install a certificate system-wide. Beware that patching source code may bring up issues with intellectual property rights.

yanychar
  • 652
1

I am using a "User Environment Virtualization" (UEV) application that does this for my users, but you can do this with logon scripts in Windows clients just the same. I won't post all of the code to dynamically find the %APPDATA%\Mozilla\Firefox\%PROFILE% path, but when you do find it, you can import the scripts using some basic commands. I am basically reading the Firefox profiles.ini file to determine the path to the Firefox profile/cert8.db.

You may want to look at using the certutil.exe application. https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/tools/NSS_Tools_certutil

You can run logon scripts for users that automatically imports the trusted certs from a central location into the Firefox of all users on the system.

Here is the "core" of my certificate import vb script:

If Instr(strLine,"Path=Profiles/") Then
  arrLine = Split(strLine, "/")
  strProfile = strAppData & "\Mozilla\Firefox\Profiles\" & arrLine(1)
  strCertDB = strProfile & "\cert8.db"

  'Verify the DB exists, if not move to the next entry
  If objFSO.FileExists(strCertDB) Then
    'Run certutil command on this database
    strCertCommand1 = "\\SERVERNAME\SHARENAME$\certs\certutil\certutil.exe -A " &_
    "-n MYCA -t ""CT,C,C"" -d " & strProfile & " -i \\SERVERNAME\SHARENAME$\certs\MYCA_Root.cer"

    strCertCommand2 = "\\SERVERNAME\SHARENAME$\certs\certutil\certutil.exe -A " &_
    "-n MYSECONDCA -t ""CT,C,C"" -d " & strProfile & " -i \\SERVERNAME\SHARENAME$\certs\SecondCA_Root.cer"

    strCertCommand3 = "\\SERVERNAME\SHARENAME$\certs\certutil\certutil.exe -A " &_
    "-n MYTHIRDCA -t ""CT,C,C"" -d " & strProfile & " -i \\SERVERNAME\SHARENAME$\certs\ThirdCA_Root.cer"

    'Run the import commands for this Firefox profile
    objShell.Run("%comspec% /c " & strCertCommand1),0,TRUE
    objShell.Run("%comspec% /c " & strCertCommand2),0,TRUE
    objShell.Run("%comspec% /c " & strCertCommand3),0,TRUE