summaryrefslogtreecommitdiffstats
path: root/nss_engine_init.c
diff options
context:
space:
mode:
Diffstat (limited to 'nss_engine_init.c')
-rw-r--r--nss_engine_init.c122
1 files changed, 95 insertions, 27 deletions
diff --git a/nss_engine_init.c b/nss_engine_init.c
index 81b2434..2a6ce58 100644
--- a/nss_engine_init.c
+++ b/nss_engine_init.c
@@ -27,6 +27,8 @@
#include "ocsp.h"
#include "keyhi.h"
#include "cert.h"
+#include <sys/types.h>
+#include <pwd.h>
static SECStatus ownBadCertHandler(void *arg, PRFileDesc * socket);
static SECStatus ownHandshakeCallback(PRFileDesc * socket, void *arg);
@@ -49,6 +51,32 @@ static char *version_components[] = {
NULL
};
+/* See if a uid or gid can read a file at a given path. Ignore world
+ * read permissions.
+ *
+ * Return 0 on failure or file doesn't exist
+ * Return 1 on success
+ */
+static int check_path(uid_t uid, gid_t gid, char *filepath, apr_pool_t *p)
+{
+ apr_finfo_t finfo;
+ int rv;
+
+ if ((rv = apr_stat(&finfo, filepath, APR_FINFO_PROT | APR_FINFO_OWNER,
+ p)) == APR_SUCCESS) {
+ if (((uid == finfo.user) &&
+ ((finfo.protection & APR_FPROT_UREAD))) ||
+ ((gid == finfo.group) &&
+ ((finfo.protection & APR_FPROT_GREAD)))
+ )
+ {
+ return 1;
+ }
+ return 0;
+ }
+ return 0;
+}
+
static char *nss_add_version_component(apr_pool_t *p,
server_rec *s,
char *name)
@@ -130,6 +158,68 @@ static void nss_init_SSLLibrary(server_rec *base_server, apr_pool_t *p)
}
}
+ /* Assuming everything is ok so far, check the cert database permissions
+ * for the server user before Apache starts forking. We die now or
+ * get stuck in an endless loop not able to read the NSS database.
+ */
+ if (mc->nInitCount == 1) {
+ if (mc->skip_permission_check == PR_FALSE) {
+ char filepath[1024];
+ struct passwd *pw = NULL;
+
+ pw = getpwnam(mc->user);
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, base_server,
+ "Checking permissions for user %s: uid %d gid %d",
+ mc->user, pw->pw_uid, pw->pw_gid);
+
+ if (strncasecmp(mc->pCertificateDatabase, "sql:", 4) == 0) {
+ apr_snprintf(filepath, 1024, "%s/key4.db",
+ mc->pCertificateDatabase+4);
+ if (!(check_path(pw->pw_uid, pw->pw_gid, filepath, p))) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, base_server,
+ "Server user %s lacks read access to NSS key "
+ "database %s.", mc->user, filepath);
+ nss_die();
+ }
+ apr_snprintf(filepath, 1024, "%s/cert9.db",
+ mc->pCertificateDatabase+4);
+ if (!(check_path(pw->pw_uid, pw->pw_gid, filepath, p))) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, base_server,
+ "Server user %s lacks read access to NSS cert "
+ "database %s.", mc->user, filepath);
+ nss_die();
+ }
+ } else {
+ apr_snprintf(filepath, 1024, "%s/key3.db",
+ mc->pCertificateDatabase);
+ if (!(check_path(pw->pw_uid, pw->pw_gid, filepath, p))) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, base_server,
+ "Server user %s lacks read access to NSS key "
+ "database %s.", mc->user, filepath);
+ nss_die();
+ }
+ apr_snprintf(filepath, 1024, "%s/cert8.db",
+ mc->pCertificateDatabase);
+ if (!(check_path(pw->pw_uid, pw->pw_gid, filepath, p))) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, base_server,
+ "Server user %s lacks read access to NSS cert "
+ "database %s.", mc->user, filepath);
+ nss_die();
+ }
+ apr_snprintf(filepath, 1024, "%s/secmod.db",
+ mc->pCertificateDatabase);
+ if (!(check_path(pw->pw_uid, pw->pw_gid, filepath, p))) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, base_server,
+ "Server user %s lacks read access to NSS secmod "
+ "database %s.", mc->user, filepath);
+ nss_die();
+ }
+ }
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, base_server,
+ "Permissions check out ok");
+ }
+ }
+
/* We need to be in the same directory as libnssckbi.so to load the
* root certificates properly.
*/
@@ -155,6 +245,7 @@ static void nss_init_SSLLibrary(server_rec *base_server, apr_pool_t *p)
else
return;
}
+
/* Initialize NSS and open the certificate database read-only. */
rv = NSS_Initialize(mc->pCertificateDatabase, mc->pDBPrefix, mc->pDBPrefix, "secmod.db", NSS_INIT_READONLY);
if (chdir(cwd) != 0) {
@@ -168,39 +259,16 @@ static void nss_init_SSLLibrary(server_rec *base_server, apr_pool_t *p)
return;
}
- /* Assuming everything is ok so far, check the cert database password(s). */
if (rv != SECSuccess) {
- apr_finfo_t finfo;
- char keypath[1024];
- int rv;
- uid_t user_id;
- gid_t gid;
-
- user_id = ap_uname2id(mc->user);
- gid = getegid();
-
NSS_Shutdown();
+
ap_log_error(APLOG_MARK, APLOG_ERR, 0, base_server,
"NSS_Initialize failed. Certificate database: %s.", mc->pCertificateDatabase != NULL ? mc->pCertificateDatabase : "not set in configuration");
nss_log_nss_error(APLOG_MARK, APLOG_ERR, base_server);
- apr_snprintf(keypath, 1024, "%s/key3.db", mc->pCertificateDatabase);
- if ((rv = apr_stat(&finfo, keypath, APR_FINFO_PROT | APR_FINFO_OWNER,
- p)) == APR_SUCCESS) {
- if (((user_id == finfo.user) &&
- (!(finfo.protection & APR_FPROT_UREAD))) ||
- ((gid == finfo.group) &&
- (!(finfo.protection & APR_FPROT_GREAD))) ||
- (!(finfo.protection & APR_FPROT_WREAD))
- )
- {
- ap_log_error(APLOG_MARK, APLOG_ERR, 0, base_server,
- "Server user lacks read access to NSS database.");
- }
- } else {
- ap_log_error(APLOG_MARK, APLOG_ERR, 0, base_server,
- "Does the NSS database exist?");
- }
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, base_server,
+ "Does the NSS database exist?");
+
nss_die();
}