Skip to content

Instantly share code, notes, and snippets.

@dshcherb
Created February 8, 2018 17:48
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dshcherb/c03d080f9f721d16050a65210f3a05e2 to your computer and use it in GitHub Desktop.
Save dshcherb/c03d080f9f721d16050a65210f3a05e2 to your computer and use it in GitHub Desktop.
An investigation into where CA certificates are stored in Ubuntu
For verification, applications that use openssl would create an openssl context with either default or specific directories used for verification. Note that some packages (e.g. openldap) use gnutls instead of openssl and gnutls has a compatibility layer (includes/gnutls/openssl.h) which includes common functions like setting verification paths so you may rely on using a single code base for configuration to some extent.
https://www.openssl.org/docs/man1.0.2/ssl/SSL_CTX_load_verify_locations.html
SSL_CTX_load_verify_locations - set default locations for trusted CA certificates
int SSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *CAfile,
const char *CApath)
{ return (X509_STORE_load_locations(ctx->cert_store, CAfile, CApath));
int X509_STORE_load_locations(X509_STORE *ctx, const char *file,
const char *path)
... lookup = X509_STORE_add_lookup(ctx, X509_LOOKUP_file());
... if (X509_LOOKUP_load_file(lookup, file, X509_FILETYPE_PEM) != 1)
... lookup = X509_STORE_add_lookup(ctx, X509_LOOKUP_hash_dir());
... if (X509_LOOKUP_add_dir(lookup, path, X509_FILETYPE_PEM) != 1)
# define X509_LOOKUP_load_file(x,name,type) \
X509_LOOKUP_ctrl((x),X509_L_FILE_LOAD,(name),(long)(type),NULL)
# define X509_LOOKUP_add_dir(x,name,type) \
X509_LOOKUP_ctrl((x),X509_L_ADD_DIR,(name),(long)(type),NULL)
int X509_LOOKUP_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc, long argl,
char **ret)
... return ctx->method->ctrl(ctx, cmd, argc, argl, ret);
X509_LOOKUP *X509_STORE_add_lookup(X509_STORE *v, X509_LOOKUP_METHOD *m)
... lu = X509_LOOKUP_new(m);
X509_LOOKUP *X509_LOOKUP_new(X509_LOOKUP_METHOD *method)
ret->method = method;
crypto/store/str_meth.c|194| sm->ctrl = ctrl_f;
crypto/engine/eng_lib.c|281| e->ctrl = ctrl_f;
crypto/engine/eng_list.c|318| dest->ctrl = src->ctrl;
Typical lookup controllers are here (they are using X509_CERT_DIR implicitly:
crypto/x509/by_dir.c:
x509_lookup_method *x509_lookup_hash_dir(void)
{ return (&x509_dir_lookup); }
static int dir_ctrl(x509_lookup *ctx, int cmd, const char *argp, long argl,
char **retp)
...
if (argl == X509_FILETYPE_DEFAULT) {
dir = (char *)getenv(X509_get_default_cert_dir_env()); // <--- by environment variable
if (dir)
ret = add_cert_dir(ld, dir, X509_FILETYPE_PEM);
else
ret = add_cert_dir(ld, X509_get_default_cert_dir(), <--- or by compile-time define variable
X509_FILETYPE_PEM);
dir = (char *)getenv(X509_get_default_cert_dir_env());
...
const char *X509_get_default_cert_dir_env(void)
{ return (X509_CERT_DIR_EVP); } // <--- the same exists for CA files
This can be used by users of openssl library (unless they call this explicitly, nothing will ever be set`:
int SSL_CTX_set_default_verify_paths(SSL_CTX *ctx)
... return (X509_STORE_set_default_paths(ctx->cert_store));
ubuntu-specific directories:
- /etc/ssl
- Access: (0755/drwxr-xr-x) Uid: ( 0/ root) Gid: ( 0/ root)
- /etc/ssl/certs
- Access: (0755/drwxr-xr-x) Uid: ( 0/ root) Gid: ( 0/ root)
- ca certificates
- server/client certificates
- /etc/ssl/private
- private keys associated with server/client certificates (only root can use by default
- Access: (0700/drwx------) Uid: ( 0/ root) Gid: ( 0/ root)
- uid: root
- gid: root
ubuntu-specific:
OPENSSLDIR: "/usr/lib/ssl"
In openssl itself there are compile-time defaults:
# define X509_CERT_AREA OPENSSLDIR
# define X509_CERT_DIR OPENSSLDIR "/certs"
# define X509_CERT_FILE OPENSSLDIR "/cert.pem"
# define X509_PRIVATE_DIR OPENSSLDIR "/private"
Also, there are environment variables that can be implicitly used by any process using openssl (note that if there's forking you are generally OK, if there's one of exec* family of functions a parent must pass the environment explicitly:
# define X509_CERT_DIR_EVP "SSL_CERT_DIR"
# define X509_CERT_FILE_EVP "SSL_CERT_FILE"
const char *X509_get_default_cert_area(void);
const char *X509_get_default_cert_dir(void);
const char *X509_get_default_cert_file(void);
const char *X509_get_default_cert_dir_env(void);
const char *X509_get_default_cert_file_env(void);
const char *X509_get_default_private_dir(void);
http://manpages.ubuntu.com/manpages/xenial/man1/c_rehash.1ssl.html
"c_rehash - Create symbolic links to files named by the hash values"
"c_rehash scans directories and calculates a hash value of each ".pem", ".crt", ".cer", or ".crl" file in the specified directory list and
creates symbolic links for each file, where the name of the link is the hash value. (If the platform does not support symbolic links, a copy is made.) This utility is useful as many programs that use OpenSSL require directories to be set up like this in order to find
certificates. If any directories are named on the command line, then those are processed in turn. If not, then the SSL_CERT_DIR environment variable is consulted; this shold be a colon-separated list of directories, like the Unix PATH variable. If that is not set then the default directory (installation-specific but often /usr/local/ssl/certs) is processed."
Hashed files have the following names:
d06393bb.0@
openssl version -d
OPENSSLDIR: "/usr/lib/ssl"
stat /usr/lib/ssl/certs
File: /usr/lib/ssl/certs -> /etc/ssl/certs
➜ openssl git:(ubuntu/xenial-updates) cat debian/openssl.dirs
usr/bin
usr/lib
etc/ssl/certs
etc/ssl/private
➜ openssl git:(ubuntu/xenial-updates) cat debian/openssl.files
usr/share/man/man1
usr/share/man/man5
usr/share/man/man7
usr/bin
usr/lib/ssl/misc
usr/lib/ssl/certs
usr/lib/ssl/openssl.cnf
usr/lib/ssl/private
etc/ssl
debian/openssl.postinst: echo Linking /usr/lib/ssl to /etc/ssl
debian/rules:CONFARGS = --prefix=/usr --openssldir=/usr/lib/ssl --libdir=lib/$(DEB_HOST_MULTIARCH) no-idea no-mdc2 no-rc5 no-zlib enable-tlsext no-ssl2 no-ssl3 enable-unit-test $(ARCH_CONFARGS)
https://wiki.openssl.org/index.php/Compilation_and_Installation#PREFIX_and_OPENSSLDIR
"PREFIX and OPENSSLDIR
--prefix and --openssldir control the configuration of installed components. The behavior and interactions of --prefix and --openssldir are slightly different between OpenSSL 1.0.2 and below, and OpenSSL 1.1.0 and above.
The rule of thumb to use when you want something that "just works" for all recent versions of OpenSSL, including OpenSSL 1.0.2 and 1.1.0, is:
specify both --prefix and --openssldir
set --prefix and --openssldir to the same location"
https://stackoverflow.com/a/24959823
==============
https://help.ubuntu.com/16.04/serverguide/certificates-and-security.html
1) Put your ca certificate into:
/usr/local/share/ca-certificates
2) Run
sudo update-ca-certificates
man update-ca-certificates:
It reads the file /etc/ca-certificates.conf. Each line gives a pathname of a CA certificate under /usr/share/ca-certificates that should be trusted. Lines that begin with "#" are comment lines and thus ignored. Lines that begin with "!" are deselected, causing the deactivation of the CA certificate in question. Certificates must have a .crt extension in order to be included by update-ca-certificates.
/etc/ca-certificates.conf - A configuration file.
/etc/ssl/certs/ca-certificates.crt - A single-file version of CA certificates. This holds all CA certificates that you activated in /etc/ca-certificates.conf.
/usr/share/ca-certificates - Directory of CA certificates.
/usr/local/share/ca-certificates - Directory of local CA certificates (with .crt extension).
See:
https://git.launchpad.net/~usd-import-team/ubuntu/+source/ca-certificates/tree/sbin/update-ca-certificates?h=ubuntu/xenial#n157
# Now process certificate authorities installed by the local system
# administrator.
if [ -d "$LOCALCERTSDIR" ]
then
find -L "$LOCALCERTSDIR" -type f -name '*.crt' | sort | while read crt
do
add "$crt"
done
fi
http://manpages.ubuntu.com/manpages/xenial/man8/update-ca-certificates.8.html
Remove symlinks in /etc/ssl/certs
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment