diff options
-rw-r--r-- | mod_nss.c | 2 | ||||
-rw-r--r-- | mod_nss.h | 7 | ||||
-rw-r--r-- | nss_engine_config.c | 9 | ||||
-rw-r--r-- | nss_engine_init.c | 45 | ||||
-rw-r--r-- | nss_engine_pphrase.c | 17 | ||||
-rw-r--r-- | nss_pcache.c | 25 |
6 files changed, 98 insertions, 7 deletions
@@ -152,6 +152,8 @@ static const command_rec nss_config_cmds[] = { AP_INIT_RAW_ARGS("NSSLogLevel", ap_set_deprecated, NULL, OR_ALL, "SSLLogLevel directive is no longer supported - use LogLevel."), #endif + AP_INIT_TAKE1("User", set_user, NULL, RSRC_CONF, + "Apache user. Comes from httpd.conf."), AP_END_CMD }; @@ -41,6 +41,9 @@ #include "apr_shm.h" #include "apr_global_mutex.h" #include "apr_optional.h" +#include <sys/types.h> +#include <sys/ipc.h> +#include <sys/sem.h> #define MOD_NSS_VERSION AP_SERVER_BASEREVISION @@ -244,6 +247,9 @@ typedef struct { struct { void *pV1, *pV2, *pV3, *pV4, *pV5, *pV6, *pV7, *pV8, *pV9, *pV10; } rCtx; + + int semid; + const char *user; } SSLModConfigRec; typedef struct SSLSrvConfigRec SSLSrvConfigRec; @@ -412,6 +418,7 @@ const char *nss_cmd_NSSProxyProtocol(cmd_parms *, void *, const char *); const char *nss_cmd_NSSProxyCipherSuite(cmd_parms *, void *, const char *); const char *nss_cmd_NSSProxyNickname(cmd_parms *cmd, void *dcfg, const char *arg); const char *nss_cmd_NSSProxyCheckPeerCN(cmd_parms *cmd, void *dcfg, int flag); +const char *set_user(cmd_parms *cmd, void *dummy, const char *arg); /* module initialization */ int nss_init_Module(apr_pool_t *, apr_pool_t *, apr_pool_t *, server_rec *); diff --git a/nss_engine_config.c b/nss_engine_config.c index 64ec447..2f1fb5c 100644 --- a/nss_engine_config.c +++ b/nss_engine_config.c @@ -830,3 +830,12 @@ const char *nss_cmd_NSSOptions(cmd_parms *cmd, return NULL; } + +const char *set_user(cmd_parms *cmd, void *dummy, const char *arg) +{ + SSLModConfigRec *mc = myModConfig(cmd->server); + + mc->user = arg; + + return NULL; +} diff --git a/nss_engine_init.c b/nss_engine_init.c index 0392205..6b0770c 100644 --- a/nss_engine_init.c +++ b/nss_engine_init.c @@ -312,6 +312,7 @@ int nss_init_Module(apr_pool_t *p, apr_pool_t *plog, int sslenabled = FALSE; int fipsenabled = FALSE; int threaded = 0; + struct semid_ds status; mc->nInitCount++; @@ -412,10 +413,26 @@ int nss_init_Module(apr_pool_t *p, apr_pool_t *plog, ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, "Init: %snitializing NSS library", mc->nInitCount == 1 ? "I" : "Re-i"); + /* The first pass through this function will create the semaphore that + * will be used to lock the pipe. The user is still root at that point + * so for any later calls the semaphore ops will fail with permission + * errors. So switch the user to the Apache user. + */ + if (mc->semid) { + uid_t user_id; + + user_id = ap_uname2id(mc->user); + semctl(mc->semid, 0, IPC_STAT, &status); + status.sem_perm.uid = user_id; + semctl(mc->semid,0,IPC_SET,&status); + } + /* Do we need to fire up our password helper? */ if (mc->nInitCount == 1) { const char * child_argv[5]; apr_status_t rv; + struct sembuf sb; + char sembuf[32]; if (mc->pphrase_dialog_helper == NULL) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, @@ -423,11 +440,31 @@ int nss_init_Module(apr_pool_t *p, apr_pool_t *plog, nss_die(); } + mc->semid = semget(IPC_PRIVATE, 1, IPC_CREAT | IPC_EXCL | 0600); + if (mc->semid == -1) { + ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, + "Unable to obtain semaphore."); + nss_die(); + } + + /* Initialize the semaphore */ + sb.sem_num = 0; + sb.sem_op = 1; + sb.sem_flg = 0; + if ((semop(mc->semid, &sb, 1)) == -1) { + ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, + "Unable to initialize semaphore."); + nss_die(); + } + + PR_snprintf(sembuf, 32, "%d", mc->semid); + child_argv[0] = mc->pphrase_dialog_helper; - child_argv[1] = fipsenabled ? "on" : "off"; - child_argv[2] = mc->pCertificateDatabase; - child_argv[3] = mc->pDBPrefix; - child_argv[4] = NULL; + child_argv[1] = sembuf; + child_argv[2] = fipsenabled ? "on" : "off"; + child_argv[3] = mc->pCertificateDatabase; + child_argv[4] = mc->pDBPrefix; + child_argv[5] = NULL; rv = apr_procattr_create(&mc->procattr, mc->pPool); diff --git a/nss_engine_pphrase.c b/nss_engine_pphrase.c index eb66029..a27de6f 100644 --- a/nss_engine_pphrase.c +++ b/nss_engine_pphrase.c @@ -279,6 +279,16 @@ static char *nss_get_password(FILE *input, FILE *output, char buf[1024]; apr_status_t rv; apr_size_t nBytes = 1024; + struct sembuf sb; + + /* lock the pipe */ + sb.sem_num = 0; + sb.sem_op = -1; + sb.sem_flg = SEM_UNDO; + if (semop(parg->mc->semid, &sb, 1) == -1) { + ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, + "Unable to reserve semaphore resource"); + } snprintf(buf, 1024, "RETR\t%s", token_name); rv = apr_file_write_full(parg->mc->proc.in, buf, strlen(buf), NULL); @@ -293,6 +303,13 @@ static char *nss_get_password(FILE *input, FILE *output, */ memset(buf, 0, sizeof(buf)); rv = apr_file_read(parg->mc->proc.out, buf, &nBytes); + sb.sem_op = 1; + if (semop(parg->mc->semid, &sb, 1) == -1) { + ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, + "Unable to free semaphore resource"); + /* perror("semop free resource id"); */ + } + if (rv != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "Unable to read from pin store for slot: %s APR err: %d", PK11_GetTokenName(slot), rv); diff --git a/nss_pcache.c b/nss_pcache.c index 3ba252e..800c0b6 100644 --- a/nss_pcache.c +++ b/nss_pcache.c @@ -21,6 +21,9 @@ #include <pk11func.h> #include <secmod.h> #include <signal.h> +#include <sys/types.h> +#include <sys/ipc.h> +#include <sys/sem.h> #include "nss_pcache.h" static char * getstr(const char * cmd, int el); @@ -70,6 +73,13 @@ struct Pk11PinStore unsigned char *crypt; }; +union semun { + int val; + struct semid_ds *buf; + unsigned short *array; + struct seminfo *__buf; +}; + /* * Node - for maintaining link list of tokens with cached PINs */ @@ -304,15 +314,19 @@ int main(int argc, char ** argv) char * tokenName; char * tokenpw; int fipsmode = 0; + int semid = 0; + union semun semarg; - if (argc < 3 || argc > 4) { + if (argc < 4 || argc > 5) { fprintf(stderr, "Usage: nss_pcache <fips on/off> <directory> <prefix>\n"); exit(1); } signal(SIGHUP, SIG_IGN); - if (!strcasecmp(argv[1], "on")) + semid = strtol(argv[1], NULL, 10); + + if (!strcasecmp(argv[2], "on")) fipsmode = 1; /* Initialize NSPR */ @@ -322,7 +336,7 @@ int main(int argc, char ** argv) PK11_ConfigurePKCS11(NULL,NULL,NULL, INTERNAL_TOKEN_NAME, NULL, NULL,NULL,NULL,8,1); /* Initialize NSS and open the certificate database read-only. */ - rv = NSS_Initialize(argv[2], argc == 4 ? argv[3] : NULL, argc == 4 ? argv[3] : NULL, "secmod.db", NSS_INIT_READONLY); + rv = NSS_Initialize(argv[3], argc == 4 ? argv[4] : NULL, argc == 5 ? argv[4] : NULL, "secmod.db", NSS_INIT_READONLY); if (rv != SECSuccess) { fprintf(stderr, "Unable to initialize NSS database: %d\n", rv); @@ -437,6 +451,11 @@ int main(int argc, char ** argv) } freeList(pinList); PR_Close(in); + /* Remove the semaphore used for locking here. This is because this + * program only goes away when Apache shuts down so we don't have to + * worry about reloads. + */ + semctl(semid, 0, IPC_RMID, semarg); return 0; } |