the data into a temporary file, calls the systemtap translator and
then transmits the resulting file back to the client.
- Copyright (C) 2011-2014 Red Hat Inc.
+ Copyright (C) 2011-2018 Red Hat Inc.
This file is part of systemtap, and is free software. You can
redistribute it and/or modify it under the terms of the GNU General Public
#include <climits>
#include <iostream>
#include <map>
+#include <thread>
extern "C" {
#include <unistd.h>
const char* fd0, const char* fd1, const char* fd2,
const char *pwd, const vector<string>& envVec = vector<string> ());
-#define MOK_PUBLIC_CERT_NAME "signing_key.x509"
-#define MOK_PUBLIC_CERT_FILE "/" MOK_PUBLIC_CERT_NAME
#define MOK_PRIVATE_CERT_NAME "signing_key.priv"
#define MOK_PRIVATE_CERT_FILE "/" MOK_PRIVATE_CERT_NAME
#define MOK_CONFIG_FILE "/x509.genkey"
static size_t max_compressed_req_size;
static string cert_db_path;
static string stap_options;
-static string uname_r;
-static string kernel_build_tree;
+static map<string,string> kernel_build_tree; // Kernel version -> build tree
static string arch;
static string cert_serial_number;
static string B_options;
process_r (const string &arg)
{
if (arg[0] == '/') // fully specified path
- {
- kernel_build_tree = arg;
- uname_r = kernel_release_from_build_tree (arg);
- }
+ kernel_build_tree.insert({kernel_release_from_build_tree(arg), arg});
else
- {
- kernel_build_tree = "/lib/modules/" + arg + "/build";
- uname_r = arg;
- }
- stap_options += " -r " + arg; // Pass the argument to stap directly.
+ kernel_build_tree.insert({arg, "/lib/modules/" + arg + "/build" });
}
static void
if (*num_endptr != '\0')
fatal (_F("%s: cannot parse number '--max-request-size=%s'", argv[0], optarg));
else if (maxsize_tmp < 1)
- fatal (_F("%s: invalid entry: max (uncompressed) request size must not be greater than 0 '--max-request-size=%s'",
+ fatal (_F("%s: invalid entry: max (uncompressed) request size must be greater than 0 '--max-request-size=%s'",
argv[0], optarg));
max_uncompressed_req_size = (size_t) maxsize_tmp; // convert the long to an unsigned
break;
if (*num_endptr != '\0')
fatal (_F("%s: cannot parse number '--max-compressed-request=%s'", argv[0], optarg));
else if (maxsize_tmp < 1)
- fatal (_F("%s: invalid entry: max compressed request size must not be greater than 0 '--max-compressed-request=%s'",
+ fatal (_F("%s: invalid entry: max compressed request size must be greater than 0 '--max-compressed-request=%s'",
argv[0], optarg));
max_compressed_req_size = (size_t) maxsize_tmp; // convert the long to an unsigned
break;
if (! avahi_group)
{
if (! (avahi_group = avahi_entry_group_new (c, entry_group_callback, NULL)))
- {
- server_error (_F("avahi_entry_group_new () failed: %s",
- avahi_strerror (avahi_client_errno (c))));
- return;
- }
+ {
+ server_error (_F("avahi_entry_group_new () failed: %s",
+ avahi_strerror (avahi_client_errno (c))));
+ return;
+ }
}
else
avahi_entry_group_reset(avahi_group);
// Contruct the information needed for our service.
log (_F("Adding Avahi service '%s'", avahi_service_name));
- // Create the txt tags that will be registered with our service.
- string sysinfo = "sysinfo=" + uname_r + " " + arch;
- string certinfo = "certinfo=" + cert_serial_number;
- string version = string ("version=") + CURRENT_CS_PROTOCOL_VERSION;;
- string optinfo = "optinfo=";
- string separator;
- // These option strings already have a leading space.
- if (! R_option.empty ())
- {
- optinfo += R_option.substr(1);
- separator = " ";
- }
- if (! B_options.empty ())
- {
- optinfo += separator + B_options.substr(1);
- separator = " ";
- }
- if (! D_options.empty ())
- {
- optinfo += separator + D_options.substr(1);
- separator = " ";
- }
- if (! I_options.empty ())
- optinfo += separator + I_options.substr(1);
-
- // Create an avahi string list with the info we have so far.
- vector<string> mok_fingerprints;
- AvahiStringList *strlst = avahi_string_list_new(sysinfo.c_str (),
- optinfo.c_str (),
- version.c_str (),
- certinfo.c_str (), NULL);
- if (strlst == NULL)
- {
- server_error (_("Failed to allocate string list"));
- goto fail;
- }
+ AvahiStringList *strlst = NULL;
+ int ret;
+ for (auto it = kernel_build_tree.cbegin(); it != kernel_build_tree.cend(); ++it)
+ {
+ // Create the txt tags that will be registered with our service.
+ string sysinfo = "sysinfo=" + it->first + " "+ arch;
+ string certinfo = "certinfo=" + cert_serial_number;
+ string version = string ("version=") + CURRENT_CS_PROTOCOL_VERSION;;
+ string optinfo = "optinfo=";
+ string separator;
+ // These option strings already have a leading space.
+ if (! R_option.empty ())
+ {
+ optinfo += R_option.substr(1);
+ separator = " ";
+ }
+ if (! B_options.empty ())
+ {
+ optinfo += separator + B_options.substr(1);
+ separator = " ";
+ }
+ if (! D_options.empty ())
+ {
+ optinfo += separator + D_options.substr(1);
+ separator = " ";
+ }
+ if (! I_options.empty ())
+ optinfo += separator + I_options.substr(1);
+
+ // Create an avahi string list with the info we have so far.
+ vector<string> mok_fingerprints;
+ strlst = avahi_string_list_new(sysinfo.c_str (),
+ optinfo.c_str (),
+ version.c_str (),
+ certinfo.c_str (), NULL);
+ if (strlst == NULL)
+ {
+ server_error (_("Failed to allocate string list"));
+ goto fail;
+ }
- // Add server MOK info, if available.
- get_server_mok_fingerprints (mok_fingerprints, true, false);
- if (! mok_fingerprints.empty())
- {
- vector<string>::const_iterator it;
- for (it = mok_fingerprints.begin(); it != mok_fingerprints.end(); it++)
+ // Add server MOK info, if available.
+ get_server_mok_fingerprints (mok_fingerprints, true, false);
+ if (! mok_fingerprints.empty())
{
- string tmp = "mok_info=" + *it;
- strlst = avahi_string_list_add(strlst, tmp.c_str ());
- if (strlst == NULL)
- {
- server_error (_("Failed to add a string to the list"));
- goto fail;
- }
- }
- }
+ for (auto it = mok_fingerprints.cbegin(); it != mok_fingerprints.cend(); it++)
+ {
+ string tmp = "mok_info=" + *it;
+ strlst = avahi_string_list_add(strlst, tmp.c_str ());
+ if (strlst == NULL)
+ {
+ server_error (_("Failed to add a string to the list"));
+ goto fail;
+ }
+ }
+ }
- // We will now add our service to the entry group.
- // Loop until no collisions.
- int ret;
- for (;;) {
- ret = avahi_entry_group_add_service_strlst (avahi_group,
- AVAHI_IF_UNSPEC,
- AVAHI_PROTO_UNSPEC,
- (AvahiPublishFlags)0,
- avahi_service_name,
- avahi_service_tag,
- NULL, NULL, port, strlst);
- if (ret == AVAHI_OK)
- break; // success!
-
- if (ret == AVAHI_ERR_COLLISION)
- {
- // A service name collision with a local service happened.
- // Pick a new name.
- if (rename_service () < 0) {
- // Too many collisions. Message already issued.
- goto fail;
- }
- continue; // try again.
+ // We will now add our service to the entry group.
+ // Loop until no collisions.
+ for (;;) {
+ ret = avahi_entry_group_add_service_strlst (avahi_group,
+ AVAHI_IF_UNSPEC,
+ AVAHI_PROTO_UNSPEC,
+ (AvahiPublishFlags)0,
+ avahi_service_name,
+ avahi_service_tag,
+ NULL, NULL, port, strlst);
+ if (ret == AVAHI_OK)
+ break; // success!
+
+ if (ret == AVAHI_ERR_COLLISION)
+ {
+ // A service name collision with a local service happened.
+ // Pick a new name.
+ if (rename_service () < 0) {
+ // Too many collisions. Message already issued.
+ goto fail;
+ }
+ continue; // try again.
+ }
+
+ server_error (_F("Failed to add %s service: %s",
+ avahi_service_tag, avahi_strerror (ret)));
+ goto fail;
}
- server_error (_F("Failed to add %s service: %s",
- avahi_service_tag, avahi_strerror (ret)));
- goto fail;
- }
+ avahi_string_list_free(strlst);
+ strlst = NULL;
+ }
// Tell the server to register the service.
if ((ret = avahi_entry_group_commit (avahi_group)) < 0)
server_error (_F("Failed to commit avahi entry group: %s", avahi_strerror (ret)));
goto fail;
}
-
- avahi_string_list_free(strlst);
return;
fail:
// Initial values.
use_db_password = false;
port = 0;
- max_threads = sysconf( _SC_NPROCESSORS_ONLN ); // Default to number of processors
- max_uncompressed_req_size = 50000; // 50 KB <- default max uncompressed request size
- max_compressed_req_size = 5000; // 5 KB <- default max compressed request size
+ max_threads = thread::hardware_concurrency(); // Default to number of processors
+ max_uncompressed_req_size = 50000; // 50 KB: default max uncompressed request size
+ max_compressed_req_size = 5000; // 5 KB: default max compressed request size
keep_temp = false;
struct utsname utsname;
uname (& utsname);
- uname_r = utsname.release;
- kernel_build_tree = "/lib/modules/" + uname_r + "/build";
+ kernel_build_tree.insert({utsname.release, "/lib/modules/" + string(utsname.release) + "/build"});
arch = normalize_machine (utsname.machine);
// Parse the arguments. This also starts the server log, if any, and should be done before
/* Function: setupSSLSocket()
*
* Purpose: Configure a socket for SSL.
- *
+ * In case of failure, clean up the incoming tcpSocket and/or any partially setup sslSocket.
*
*/
static PRFileDesc *
if (sslSocket == NULL)
{
server_error (_("Could not import socket into SSL"));
- nssError ();
- return NULL;
+ goto error;
}
/* Set the appropriate flags. */
if (secStatus != SECSuccess)
{
server_error (_("Error setting SSL security for socket"));
- nssError ();
- return NULL;
+ goto error;
}
secStatus = SSL_OptionSet(sslSocket, SSL_HANDSHAKE_AS_SERVER, PR_TRUE);
if (secStatus != SECSuccess)
{
server_error (_("Error setting handshake as server for socket"));
- nssError ();
- return NULL;
+ goto error;
}
secStatus = SSL_OptionSet(sslSocket, SSL_REQUEST_CERTIFICATE, PR_FALSE);
if (secStatus != SECSuccess)
{
server_error (_("Error setting SSL client authentication mode for socket"));
- nssError ();
- return NULL;
+ goto error;
}
secStatus = SSL_OptionSet(sslSocket, SSL_REQUIRE_CERTIFICATE, PR_FALSE);
if (secStatus != SECSuccess)
{
server_error (_("Error setting SSL client authentication mode for socket"));
- nssError ();
- return NULL;
+ goto error;
}
/* Set the appropriate callback routines. */
secStatus = SSL_AuthCertificateHook (sslSocket, myAuthCertificate, CERT_GetDefaultCertDB());
if (secStatus != SECSuccess)
{
- nssError ();
server_error (_("Error in SSL_AuthCertificateHook"));
- return NULL;
+ goto error;
}
#endif
#if 0 /* Use the default */
secStatus = SSL_BadCertHook(sslSocket, (SSLBadCertHandler)myBadCertHandler, &certErr);
if (secStatus != SECSuccess)
{
- nssError ();
server_error (_("Error in SSL_BadCertHook"));
- return NULL;
+ goto error;
}
#endif
#if 0 /* no handshake callback */
if (secStatus != SECSuccess)
{
server_error (_("Error in SSL_HandshakeCallback"));
- nssError ();
- return NULL;
+ goto error;
}
#endif
if (secStatus != SECSuccess)
{
server_error (_("Error configuring SSL server"));
- nssError ();
- return NULL;
+ goto error;
}
return sslSocket;
+
+ error:
+ nssError();
+
+ if (sslSocket) {
+ if (PR_Close (sslSocket) != PR_SUCCESS) {
+ server_error (_("Error closing ssl socket"));
+ nssError ();
+ }
+ } else {
+ if (PR_Close (tcpSocket) != PR_SUCCESS) {
+ server_error (_("Error closing tcp/ssl socket"));
+ nssError ();
+ }
+ }
+
+ return NULL;
}
#if 0 /* No client authentication (for now) and not authenticating after each transaction. */
const std::string &name,
std::string stapstderr)
{
- vector<string> cmd;
int rc;
string mok_directory = mok_path + "/" + mok_fingerprint;
- cmd.clear();
- cmd.push_back (kernel_build_tree + "/scripts/sign-file");
- cmd.push_back ("sha512");
- cmd.push_back (mok_directory + MOK_PRIVATE_CERT_FILE);
- cmd.push_back (mok_directory + MOK_PUBLIC_CERT_FILE);
- cmd.push_back (name);
+ vector<string> cmd
+ {
+ kernel_build_tree + "/scripts/sign-file",
+ "sha512",
+ mok_directory + MOK_PRIVATE_CERT_FILE,
+ mok_directory + MOK_PUBLIC_CERT_FILE,
+ name
+ };
rc = stap_system (0, cmd);
if (rc != 0)
static void
filter_response_file (const string &file_name, const string &responseDirName)
{
- vector<string> cmd;
+ // Filter the server's home directory name (unless it is "/")
+ string dir = get_home_directory();
+ if (dir != "/")
+ {
+ string swap = string ("s,") + get_home_directory () + ",<server>,g";
+ vector<string> cmd { "sed", "-i", swap, file_name };
+ (void) stap_system (0, cmd);
+ }
- // Filter the server's home directory name
- cmd.clear();
- cmd.push_back ("sed");
- cmd.push_back ("-i");
- cmd.push_back (string ("s,") + get_home_directory () + ",<server>,g");
- cmd.push_back (file_name);
- (void) stap_system (0, cmd);
-
- // Filter the server's response directory name
- cmd.clear();
- cmd.push_back ("sed");
- cmd.push_back ("-i");
- cmd.push_back (string ("s,") + responseDirName + ",<server>,g");
- cmd.push_back (file_name);
- (void) stap_system (0, cmd);
+ // Filter the server's response directory name (unless it is "/")
+ if (responseDirName != "/")
+ {
+ string swap = string ("s,") + responseDirName + ",<server>,g";
+ vector<string> cmd = { "sed", "-i", swap, file_name };
+ (void) stap_system (0, cmd);
+ }
}
static privilege_t
char tmpdir[PATH_MAX] = { '\0' };
string public_cert_path, private_cert_path, destdir;
mode_t old_umask;
+ int retlen;
mok_fingerprint.clear ();
}
// Make a temporary directory to store results in.
- snprintf (tmpdir, PATH_MAX, "%s/stap-server.XXXXXX", mok_path.c_str ());
+ retlen = snprintf (tmpdir, PATH_MAX, "%s/stap-server.XXXXXX", mok_path.c_str ());
+ if (retlen < 0 || retlen >= PATH_MAX)
+ {
+ server_error (_F("Could not create %s name", "temporary directory"));
+ tmpdir[0] = '\0';
+ goto cleanup;
+ }
+
if (mkdtemp (tmpdir) == NULL)
{
server_error (_F("Could not create temporary directory %s: %s", tmpdir,
// Actually generate key using openssl.
public_cert_path = tmpdir + string (MOK_PUBLIC_CERT_FILE);
private_cert_path = tmpdir + string (MOK_PRIVATE_CERT_FILE);
- cmd.push_back ("openssl");
- cmd.push_back ("req");
- cmd.push_back ("-new");
- cmd.push_back ("-nodes");
- cmd.push_back ("-utf8");
- cmd.push_back ("-sha256");
- cmd.push_back ("-days");
- cmd.push_back ("36500");
- cmd.push_back ("-batch");
- cmd.push_back ("-x509");
- cmd.push_back ("-config");
- cmd.push_back (config_path);
- cmd.push_back ("-outform");
- cmd.push_back ("DER");
- cmd.push_back ("-out");
- cmd.push_back (public_cert_path);
- cmd.push_back ("-keyout");
- cmd.push_back (private_cert_path);
+
+ cmd =
+ {
+ "openssl", "req", "-new", "-nodes", "-utf8",
+ "-sha256", "-days", "36500", "-batch", "-x509",
+ "-config", config_path,
+ "-outform", "DER",
+ "-out", public_cert_path,
+ "-keyout", private_cert_path
+ };
rc = stap_system (0, cmd);
if (rc != 0)
{
cleanup:
// Remove the temporary directory.
- cmd.clear ();
- cmd.push_back ("rm");
- cmd.push_back ("-rf");
- cmd.push_back (tmpdir);
+ cmd = { "rm", "-rf", tmpdir };
rc = stap_system (0, cmd);
if (rc != 0)
server_error (_("Error in tmpdir cleanup"));
unsigned u;
unsigned i;
FILE* f;
+ int retlen;
// Save the server version. Do this early, so the client knows what version of the server
// it is dealing with, even if the request is not fully completed.
// The name of the translator executable.
stapargv.push_back ((char *)(getenv ("SYSTEMTAP_STAP") ?: STAP_PREFIX "/bin/stap"));
+ // Fetch the target kernel version from request and pass flag to stap
+ string kernel_version;
+ filename = requestDirName + "/sysinfo";
+ ifstream versionfile(filename.c_str());
+ if (versionfile >> kernel_version >> kernel_version) // Skip sysinfo: label
+ {
+ if (kernel_build_tree.find(kernel_version) != kernel_build_tree.end())
+ {
+ stapargv.push_back("-r" + kernel_version);
+ }
+ else
+ {
+ log(_F("Target kernel version %s is not supported by this server",
+ kernel_version.c_str()));
+ return;
+ }
+ }
+ else
+ {
+ server_error(_("Unable to read sysinfo"));
+ return;
+ }
+
/* Transcribe stap_options. We use plain wordexp(3), since these
options are coming from the local trusted user, so malicious
content is not a concern. */
struct stat st;
char *arg;
- snprintf (stapargfile, PATH_MAX, "%s/argv%d", requestDirName.c_str (), i);
+ retlen = snprintf (stapargfile, PATH_MAX, "%s/argv%d", requestDirName.c_str (), i);
+ if (retlen < 0 || retlen >= PATH_MAX)
+ {
+ server_error (_F("Error creating %s name", "path"));
+ return;
+ }
rc = stat(stapargfile, & st);
if (rc) break;
{
glob_t globber;
char pattern[PATH_MAX];
- snprintf (pattern, PATH_MAX, "%s/*.ko", new_staptmpdir.c_str());
+ int retlen;
+
+ retlen = snprintf (pattern, PATH_MAX, "%s/*.ko", new_staptmpdir.c_str());
+ if (retlen < 0 || retlen >= PATH_MAX)
+ {
+ server_error (_F("Error creating %s name", "pattern"));
+ return;
+ }
+
rc = glob (pattern, GLOB_ERR, NULL, &globber);
if (rc)
server_error (_F("Unable to find a module in %s", new_staptmpdir.c_str()));
else if (globber.gl_pathc != 1)
- server_error (_F("Too many modules (%zu) in %s", globber.gl_pathc, new_staptmpdir.c_str()));
+ {
+ server_error (_F("Too many modules (%zu) in %s", globber.gl_pathc, new_staptmpdir.c_str()));
+ globfree(&globber);
+ }
else
{
if (pr_contains (privilege, pr_stapusr)
// If we signing the module failed, change the staprc to
// 1, so that the client won't try to run the resulting
// module, which wouldn't work.
- if (! mok_sign_file (mok_fingerprint, kernel_build_tree,
+ if (! mok_sign_file (mok_fingerprint, kernel_build_tree[kernel_version],
globber.gl_pathv[0], stapstderr))
staprc = 1;
}
// resulting module, which wouldn't work.
staprc = 1;
}
+ globfree(&globber);
}
}
// requires signed modules. The error will have been generated
// above on the systemtap module itself.
if (! mok_fingerprint.empty ())
- mok_sign_file (mok_fingerprint, kernel_build_tree, uprobes_response,
+ mok_sign_file (mok_fingerprint, kernel_build_tree[kernel_version], uprobes_response,
stapstderr);
}
}
/* Given the path to the compressed request file, return 0 if the size of the
- * uncompressed request is within the determined limits. */
+ * uncompressed request is within the determined limit. */
int
check_uncompressed_request_size (const char * zip_file)
{
- vector<string> args;
ostringstream result;
- // Check the uncompressed file size.
- args.push_back("unzip");
- args.push_back("-Zt");
- args.push_back(zip_file);
-
+ // Generate the command to heck the uncompressed size
+ vector<string> args { "unzip", "-Zt", zip_file };
int rc = stap_system_read (0, args, result);
if (rc != 0)
{
server_error (_F("Unable to check the zipefile size. Error code: %d .", rc));
return rc;
}
- log (_F("Result of the unzip -Zt call is:\n%s", result.str().c_str()));
// Parse the result from the unzip call, looking for the third token
vector<string> toks;
copy for each connection.*/
vector<string> argv;
PRInt32 bytesRead;
+ int retlen;
/* Detatch to avoid a memory leak */
if(max_threads > 0)
#endif
secStatus = SECFailure;
- snprintf(tmpdir, PATH_MAX, "%s/stap-server.XXXXXX", getenv("TMPDIR") ?: "/tmp");
+ retlen = snprintf(tmpdir, PATH_MAX, "%s/stap-server.XXXXXX", getenv("TMPDIR") ?: "/tmp");
+ if (retlen < 0 || retlen >= PATH_MAX)
+ {
+ server_error (_F("Error creating %s name", "temporary directory"));
+ tmpdir[0]=0; /* prevent /bin/rm */
+ goto cleanup;
+ }
rc1 = mkdtemp(tmpdir);
if (! rc1)
{
}
/* Create a temporary files names and directories. */
- snprintf (requestFileName, PATH_MAX, "%s/request.zip", tmpdir);
+ retlen = snprintf (requestFileName, PATH_MAX, "%s/request.zip", tmpdir);
+ if (retlen < 0 || retlen >= PATH_MAX)
+ {
+ server_error (_F("Error creating %s name", "request.zip path"));
+ goto cleanup;
+ }
+
+ retlen = snprintf (requestDirName, PATH_MAX, "%s/request", tmpdir);
+ if (retlen < 0 || retlen >= PATH_MAX)
+ {
+ server_error (_F("Error creating %s name", "request directory path"));
+ goto cleanup;
+ }
- snprintf (requestDirName, PATH_MAX, "%s/request", tmpdir);
rc = mkdir(requestDirName, 0700);
if (rc)
{
goto cleanup;
}
- snprintf (responseDirName, PATH_MAX, "%s/response", tmpdir);
+ retlen = snprintf (responseDirName, PATH_MAX, "%s/response", tmpdir);
+ if (retlen < 0 || retlen >= PATH_MAX)
+ {
+ server_error (_F("Error creating %s name", "response directory path"));
+ goto cleanup;
+ }
+
rc = mkdir(responseDirName, 0700);
if (rc)
{
// Set this early, since it gets used for errors to be returned to the client.
stapstderr = string(responseDirName) + "/stderr";
- snprintf (responseFileName, PATH_MAX, "%s/response.zip", tmpdir);
+ retlen = snprintf (responseFileName, PATH_MAX, "%s/response.zip", tmpdir);
+ if (retlen < 0 || retlen >= PATH_MAX)
+ {
+ server_error (_F("Error creating %s name", "response.zip path"));
+ goto cleanup;
+ }
/* Read data from the socket.
* If the user is requesting/requiring authentication, authenticate
/* Unzip the request. */
secStatus = SECFailure;
- argv.push_back ("unzip");
- argv.push_back ("-q");
- argv.push_back ("-d");
- argv.push_back (requestDirName);
- argv.push_back (requestFileName);
+ argv = { "unzip", "-q", "-d", requestDirName, requestFileName };
rc = stap_system (0, argv);
if (rc != 0)
{
/* Zip the response. */
int ziprc;
- argv.clear ();
- argv.push_back ("zip");
- argv.push_back ("-q");
- argv.push_back ("-r");
- argv.push_back (responseFileName);
- argv.push_back (".");
+ argv = { "zip", "-q", "-r", responseFileName, "." };
rc = spawn_and_wait (argv, &ziprc, NULL, NULL, NULL, responseDirName);
if (rc != PR_SUCCESS || ziprc != 0)
{
log (_F("Keeping temporary directory %s", tmpdir));
else
{
- argv.clear ();
- argv.push_back ("rm");
- argv.push_back ("-r");
- argv.push_back (tmpdir);
+ argv = { "rm", "-r", tmpdir };
rc = stap_system (0, argv);
if (rc != 0)
server_error (_("Error in tmpdir cleanup"));
log (_F("Request from [%s]:%d complete", buf, addr.ipv6.port));
}
+ if (privKey)
+ SECKEY_DestroyPrivateKey (privKey); /* Destroy our copy of the private key. */
+
/* Increment semephore to indicate this thread is finished. */
free(t_arg);
if (max_threads > 0)
fatal(_("No memory available for new thread arg!"));
t_arg->tcpSocket = tcpSocket;
t_arg->cert = cert;
- t_arg->privKey = privKey;
+ t_arg->privKey = SECKEY_CopyPrivateKey(privKey); /* pass by value */
t_arg->addr = addr;
/* Handle the conncection */
+ int thread_rc = -1;
if (max_threads > 0)
/* Create the worker thread and handle the connection. */
- pthread_create(&tid, NULL, handle_connection, t_arg);
- else
+ thread_rc = pthread_create(&tid, NULL, handle_connection, t_arg);
+
+ if (thread_rc != 0)
/* Since max_threads == 0, don't spawn a new thread,
* just handle in the current thread. */
handle_connection(t_arg);
certUsageSSLServer, NULL/*wincx*/);
if (secStatus != SECSuccess)
{
- // Not an error. Exit the loop so a new cert can be generated.
+ // Not a serious error. Exit the loop so a new cert can be generated.
+ nssError ();
break;
}
}
- SECKEY_DestroyPrivateKey (privKey);
+ SECKEY_DestroyPrivateKey (privKey); /* Safe to destroy, even if thread still running. */
return SECSuccess;
}
if (check_cert (cert_db_path, server_cert_nickname (), use_db_password) != 0)
{
// Message already issued
- goto done;
+ server_error (_("Cannot check/create certificate, giving up."));
+ goto done;
}
// Ensure that our certificate is trusted by our local client.
// Construct the client database path relative to the server database path.
SECStatus secStatus = add_client_cert (server_cert_file (),
- local_client_cert_db_path ());
+ local_client_cert_db_path (), true);
if (secStatus != SECSuccess)
{
// Not fatal. Other clients may trust the server and trust can be added