diff --git a/src/main-misc.c b/src/main-misc.c index f8bc5cec..e7851c8a 100644 --- a/src/main-misc.c +++ b/src/main-misc.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include "ipc.h" #include "setproctitle.h" @@ -379,59 +380,24 @@ struct banned_st *btmp; void run_sec_mod(main_server_st * s) { -struct sockaddr_un sa; -int sd, e, ret; +int e; pid_t pid; - - sa.sun_family = AF_UNIX; /* make socket name */ snprintf(s->socket_file, sizeof(s->socket_file), "%s.%u", s->config->socket_file_prefix, (unsigned)getpid()); - snprintf(sa.sun_path, sizeof(sa.sun_path), "%s", s->socket_file); - remove(s->socket_file); - - sd = socket(AF_UNIX, SOCK_STREAM, 0); - if (sd == -1) { - e = errno; - mslog(s, NULL, LOG_ERR, "could not create socket '%s': %s", s->socket_file, strerror(e)); - exit(1); - } - - ret = bind(sd, (struct sockaddr *)&sa, sizeof(sa)); - if (ret == -1) { - e = errno; - mslog(s, NULL, LOG_ERR, "could not bind socket '%s': %s", s->socket_file, strerror(e)); - exit(1); - } - - ret = chown(sa.sun_path, s->config->uid, s->config->gid); - if (ret == -1) { - e = errno; - mslog(s, NULL, LOG_ERR, "could not chown socket '%s': %s", s->socket_file, strerror(e)); - } - - ret = listen(sd, 1024); - if (ret == -1) { - e = errno; - mslog(s, NULL, LOG_ERR, "could not listen to socket '%s': %s", s->socket_file, strerror(e)); - exit(1); - } - set_cloexec_flag (sd, 1); - pid = fork(); if (pid == 0) { /* child */ + prctl(PR_SET_PDEATHSIG, SIGTERM); setproctitle(PACKAGE_NAME"-secmod"); - sec_mod_server(s->config, sd); + sec_mod_server(s->config, s->socket_file); exit(0); } else if (pid > 0) { /* parent */ - close(sd); s->sec_mod_pid = pid; } else { e = errno; mslog(s, NULL, LOG_ERR, "error in fork(): %s", strerror(e)); exit(1); } - } diff --git a/src/main.c b/src/main.c index c65d6e78..59c2ec41 100644 --- a/src/main.c +++ b/src/main.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -304,6 +305,7 @@ static void remove_proc(main_server_st* s, struct proc_st *proc, unsigned k) proc->lease->in_use = 0; list_del(&proc->list); free(proc); + s->active_clients--; } static void cleanup_children(main_server_st *s) @@ -367,25 +369,6 @@ static void drop_privileges(main_server_st* s) } } - rl.rlim_cur = 0; - rl.rlim_max = 0; - ret = setrlimit(RLIMIT_NPROC, &rl); - if (ret < 0) { - e = errno; - mslog(s, NULL, LOG_ERR, "cannot enforce NPROC limit: %s\n", - strerror(e)); - } - -#define MAX_WORKER_MEM (128*1024) - rl.rlim_cur = MAX_WORKER_MEM; - rl.rlim_max = MAX_WORKER_MEM; - ret = setrlimit(RLIMIT_AS, &rl); - if (ret < 0) { - e = errno; - mslog(s, NULL, LOG_ERR, "cannot enforce AS limit: %s\n", - strerror(e)); - } - if (s->config->gid != -1 && (getgid() == 0 || getegid() == 0)) { ret = setgid(s->config->gid); if (ret < 0) { @@ -407,6 +390,25 @@ static void drop_privileges(main_server_st* s) } } + + rl.rlim_cur = 0; + rl.rlim_max = 0; + ret = setrlimit(RLIMIT_NPROC, &rl); + if (ret < 0) { + e = errno; + mslog(s, NULL, LOG_ERR, "cannot enforce NPROC limit: %s\n", + strerror(e)); + } + +#define MAX_WORKER_MEM (4*1024*1024) + rl.rlim_cur = MAX_WORKER_MEM; + rl.rlim_max = MAX_WORKER_MEM; + ret = setrlimit(RLIMIT_AS, &rl); + if (ret < 0) { + e = errno; + mslog(s, NULL, LOG_ERR, "cannot enforce AS limit: %s\n", + strerror(e)); + } } /* clears the server llist and clist. To be used after fork(). @@ -797,6 +799,7 @@ int main(int argc, char** argv) erase_cookies(&s); setproctitle(PACKAGE_NAME"-worker"); + prctl(PR_SET_PDEATHSIG, SIGTERM); ws.config = &config; ws.cmd_fd = cmd_fd[1]; diff --git a/src/sec-mod.c b/src/sec-mod.c index 75d5f231..506fb401 100644 --- a/src/sec-mod.c +++ b/src/sec-mod.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -147,7 +148,7 @@ int fd, ret; } void -sec_mod_server(struct cfg_st* config, int sd) +sec_mod_server(struct cfg_st* config, const char* socket_file) { struct sockaddr_un sa; socklen_t sa_len; @@ -160,6 +161,8 @@ struct pin_st pins; gnutls_datum_t data, out; uint16_t length; struct iovec iov[2]; +int sd; +int mask; signal(SIGHUP, SIG_IGN); signal(SIGINT, SIG_DFL); @@ -178,7 +181,41 @@ struct iovec iov[2]; syslog(LOG_ERR, "error in memory allocation"); exit(1); } + + memset(&sa, 0, sizeof(sa)); + sa.sun_family = AF_UNIX; + snprintf(sa.sun_path, sizeof(sa.sun_path), "%s", socket_file); + remove(socket_file); + + sd = socket(AF_UNIX, SOCK_STREAM, 0); + if (sd == -1) { + e = errno; + syslog(LOG_ERR, "could not create socket '%s': %s", socket_file, strerror(e)); + exit(1); + } + mask = umask(066); + ret = bind(sd, (struct sockaddr *)&sa, SUN_LEN(&sa)); + if (ret == -1) { + e = errno; + syslog(LOG_ERR, "could not bind socket '%s': %s", socket_file, strerror(e)); + exit(1); + } + umask(mask); + + ret = chown(socket_file, config->uid, config->gid); + if (ret == -1) { + e = errno; + syslog(LOG_ERR, "could not chown socket '%s': %s", socket_file, strerror(e)); + } + + ret = listen(sd, 1024); + if (ret == -1) { + e = errno; + syslog(LOG_ERR, "could not listen to socket '%s': %s", socket_file, strerror(e)); + exit(1); + } + ret = load_pins(config, &pins); if (ret < 0) { syslog(LOG_ERR, "error loading PIN files"); @@ -215,6 +252,7 @@ struct iovec iov[2]; } } + syslog(LOG_INFO, "sec-mod initialized (socket: %s)", socket_file); for (;;) { sa_len = sizeof(sa); cfd = accept(sd, (struct sockaddr *)&sa, &sa_len); @@ -226,7 +264,9 @@ struct iovec iov[2]; /* read request */ ret = recv(cfd, buffer, buffer_size, 0); - if (ret <= 2) { + if (ret == 0) + goto cont; + else if (ret <= 2) { e = errno; syslog(LOG_ERR, "error receiving sec-mod data: %s", strerror(e)); goto cont; diff --git a/src/sec-mod.h b/src/sec-mod.h index b1fb7e3b..5d255802 100644 --- a/src/sec-mod.h +++ b/src/sec-mod.h @@ -1,5 +1,5 @@ #ifndef SEC_MOD_H -void sec_mod_server(struct cfg_st* config, int sd); +void sec_mod_server(struct cfg_st* config, const char* file); #endif diff --git a/src/tlslib.c b/src/tlslib.c index b3ddefdc..06faa56e 100644 --- a/src/tlslib.c +++ b/src/tlslib.c @@ -192,7 +192,7 @@ static int verify_certificate_cb(gnutls_session_t session) ws = gnutls_session_get_ptr(session); if (ws == NULL) { - syslog(LOG_ERR, "%s:%d: could not obtain worker state.", __func__, __LINE__); + syslog(LOG_ERR, "%s:%d: could not obtain worker state", __func__, __LINE__); return -1; } @@ -225,7 +225,7 @@ static int verify_certificate_cb(gnutls_session_t session) gnutls_free(out.data); #else - oclog(ws, LOG_INFO, "client certificate verification failed."); + oclog(ws, LOG_INFO, "client certificate verification failed"); #endif goto fail; @@ -328,6 +328,7 @@ int ret; struct key_cb_data { unsigned idx; /* the index of the key */ struct sockaddr_un sa; + unsigned sa_len; }; static @@ -346,22 +347,22 @@ int key_cb_common_func (gnutls_privkey_t key, void* userdata, const gnutls_datum if (sd == -1) { e = errno; syslog(LOG_ERR, "error opening socket: %s", strerror(e)); - return -1; + return GNUTLS_E_INTERNAL_ERROR; } - ret = connect(sd, (struct sockaddr *)&cdata->sa, sizeof(cdata->sa)); + ret = connect(sd, (struct sockaddr *)&cdata->sa, cdata->sa_len); if (ret == -1) { e = errno; syslog(LOG_ERR, "error connecting to sec-mod socket '%s': %s", cdata->sa.sun_path, strerror(e)); - return -1; + return GNUTLS_E_INTERNAL_ERROR; } header[0] = cdata->idx; header[1] = type; iov[0].iov_base = header; - iov[0].iov_len = sizeof(header); + iov[0].iov_len = 2; iov[1].iov_base = raw_data->data; iov[1].iov_len = raw_data->size; @@ -401,7 +402,7 @@ int key_cb_common_func (gnutls_privkey_t key, void* userdata, const gnutls_datum error: close(sd); gnutls_free(output->data); - return -1; + return GNUTLS_E_INTERNAL_ERROR; } @@ -445,8 +446,8 @@ struct key_cb_data * cdata; } else { ret = gnutls_load_file(s->config->cert[i], &data); if (ret < 0) { - mslog(s, NULL, LOG_ERR, "error loading file '%s'", s->config->key[i]); - GNUTLS_FATAL_ERR(ret); + mslog(s, NULL, LOG_ERR, "error loading file '%s'", s->config->cert[i]); + return -1; } pcert_list_size = 8; @@ -473,8 +474,11 @@ struct key_cb_data * cdata; } cdata->idx = i; + + memset(&cdata->sa, 0, sizeof(cdata->sa)); cdata->sa.sun_family = AF_UNIX; snprintf(cdata->sa.sun_path, sizeof(cdata->sa.sun_path), "%s", s->socket_file); + cdata->sa_len = SUN_LEN(&cdata->sa); /* load the private key */ ret = gnutls_privkey_import_ext2(key, gnutls_pubkey_get_pk_algorithm(pcert_list[0].pubkey, NULL), @@ -510,7 +514,7 @@ const char* perr; set_dh_params(s, s->creds.xcred); if (s->config->key_size == 0 || s->config->cert_size == 0) { - mslog(s, NULL, LOG_ERR, "no certificate or key files were specified.\n"); + mslog(s, NULL, LOG_ERR, "no certificate or key files were specified"); exit(1); } @@ -518,7 +522,7 @@ const char* perr; ret = load_key_files(s); if (ret < 0) { - mslog(s, NULL, LOG_ERR, "error loading the certificate or key file\n"); + mslog(s, NULL, LOG_ERR, "error loading the certificate or key file"); exit(1); } @@ -529,12 +533,12 @@ const char* perr; s->config->ca, GNUTLS_X509_FMT_PEM); if (ret < 0) { - mslog(s, NULL, LOG_ERR, "error setting the CA (%s) file.\n", + mslog(s, NULL, LOG_ERR, "error setting the CA (%s) file", s->config->ca); exit(1); } - mslog(s, NULL, LOG_INFO, "processed %d CA certificate(s).\n", ret); + mslog(s, NULL, LOG_INFO, "processed %d CA certificate(s)", ret); } if (s->config->crl != NULL) { @@ -543,7 +547,7 @@ const char* perr; s->config->crl, GNUTLS_X509_FMT_PEM); if (ret < 0) { - mslog(s, NULL, LOG_ERR, "error setting the CRL (%s) file.\n", + mslog(s, NULL, LOG_ERR, "error setting the CRL (%s) file", s->config->crl); exit(1); } @@ -555,7 +559,7 @@ const char* perr; ret = gnutls_priority_init(&s->creds.cprio, s->config->priorities, &perr); if (ret == GNUTLS_E_PARSING_ERROR) - mslog(s, NULL, LOG_ERR, "error in TLS priority string: %s\n", perr); + mslog(s, NULL, LOG_ERR, "error in TLS priority string: %s", perr); GNUTLS_FATAL_ERR(ret); ret = gnutls_session_ticket_key_generate(&s->creds.ticket_key); @@ -619,14 +623,14 @@ gnutls_x509_crt_t crt; gnutls_free(data.data); if (ret < 0) { - fprintf(stderr, "Error calculating hash of '%s': %s\n", file, gnutls_strerror(ret)); + fprintf(stderr, "error calculating hash of '%s': %s", file, gnutls_strerror(ret)); exit(1); } size_t ret_size = sizeof(digest)*2+1; retval = malloc(ret_size); if (retval == NULL) { - fprintf(stderr, "Memory error\n"); + fprintf(stderr, "memory error"); exit(1); } @@ -634,7 +638,7 @@ gnutls_x509_crt_t crt; data.size = sizeof(digest); ret = gnutls_hex_encode(&data, retval, &ret_size); if (ret < 0) { - fprintf(stderr, "Error in hex encode: %s\n", gnutls_strerror(ret)); + fprintf(stderr, "error in hex encode: %s", gnutls_strerror(ret)); exit(1); } retval[ret_size] = 0;