key in the given certificate database and places the signature in the named
output file.
- Copyright (C) 2009 Red Hat Inc.
+ Copyright (C) 2009-2011 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
return 1; // ok
}
-/* Function: char * password_callback()
- *
- * Purpose: This function is our custom password handler that is called by
- * NSS when retrieving private certs and keys from the database. Returns a
- * pointer to a string that with a password for the database. Password pointer
- * should point to dynamically allocated memory that will be freed later.
- */
-static char *
-password_callback (PK11SlotInfo *info, PRBool retry, void *arg)
-{
- char *passwd = NULL;
-
- if (! retry && arg)
- passwd = PORT_Strdup((char *)arg);
-
- return passwd;
-}
-
-/* Obtain the certificate and key database password from the given file. */
-static char *
-get_password (const string &fileName)
-{
- PRFileDesc *local_file_fd;
- PRFileInfo fileInfo;
- PRInt32 numBytesRead;
- PRStatus prStatus;
- PRInt32 i;
- char *password;
-
- prStatus = PR_GetFileInfo (fileName.c_str(), &fileInfo);
- if (prStatus != PR_SUCCESS || fileInfo.type != PR_FILE_FILE || fileInfo.size < 0)
- {
- cerr << _("Could not obtain information on password file ") << fileName << "." << endl;
- nssError ();
- return NULL;
- }
-
- local_file_fd = PR_Open (fileName.c_str(), PR_RDONLY, 0);
- if (local_file_fd == NULL)
- {
- cerr << _("Could not open password file ") << fileName << "." << endl;
- nssError ();
- return NULL;
- }
-
- password = (char*)PORT_Alloc (fileInfo.size + 1);
- if (! password)
- {
- cerr << "Unable to allocate " << (fileInfo.size + 1) << " bytes." << endl;
- nssError ();
- return NULL;
- }
-
- numBytesRead = PR_Read (local_file_fd, password, fileInfo.size);
- if (numBytesRead <= 0)
- {
- cerr << _("Error reading password file ") << fileName << "." << endl;
- nssError ();
- return 0;
- }
-
- PR_Close (local_file_fd);
-
- /* Keep only the first line of data. */
- for (i = 0; i < numBytesRead; ++i)
- {
- if (password[i] == '\n' || password[i] == '\r' || password[i] == '\0')
- break;
- }
- password[i] = '\0';
-
- return password;
-}
-
static void
sign_it (const string &inputName, const string &outputName, SECKEYPrivateKey *privKey)
{
const char *nickName = "stap-server";
string module_name;
string cert_db_path;
- char *password;
CERTCertificate *cert;
SECKEYPrivateKey *privKey;
SECStatus secStatus;
if (! check_cert_db_path (cert_db_path))
return 1;
- password = get_password (cert_db_path + "/pw");
- if (! password)
- {
- cerr << _("Unable to obtain certificate database password.") << endl;
- return 1;
- }
-
/* Call the NSPR initialization routines. */
PR_Init (PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
/* Set the cert database password callback. */
- PK11_SetPasswordFunc (password_callback);
+ PK11_SetPasswordFunc (nssPasswordCallback);
- /* Initialize NSS. */
+ /* Initialize NSS. */
secStatus = NSS_Init (cert_db_path.c_str());
if (secStatus != SECSuccess)
{
}
/* Get own certificate and private key. */
- cert = PK11_FindCertFromNickname (nickName, password);
+ cert = PK11_FindCertFromNickname (nickName, NULL);
if (cert == NULL)
{
cerr << _F("Unable to find certificate with nickname %s in %s.",
return 1;
}
- privKey = PK11_FindKeyByAnyCert (cert, password);
+ /* cert_db_path.c_str () gets passed to nssPasswordCallback */
+ privKey = PK11_FindKeyByAnyCert (cert, (void *)cert_db_path.c_str ());
if (privKey == NULL)
{
- cerr << _F("Unable to obtain private key from the certificate with nickname %s, in %s.",
+ cerr << _F("Unable to obtain private key from the certificate with nickname %s in %s.",
nickName, cert_db_path.c_str()) << endl;
nssError ();
return 1;
/*
Common functions used by the NSS-aware code in systemtap.
- Copyright (C) 2009, 2010 Red Hat Inc.
+ Copyright (C) 2009-2011 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 <stdio.h>
+#include <termios.h>
+#include <unistd.h>
#include <nss.h>
#include <nspr.h>
#include <secerr.h>
#include <sslerr.h>
+#include "nsscommon.h"
+
void
nssError (void)
{
PR_Cleanup ();
}
+/* Disable character echoing, if the fd is a tty. */
+static void
+echoOff(int fd)
+{
+ if (isatty(fd)) {
+ struct termios tio;
+ tcgetattr(fd, &tio);
+ tio.c_lflag &= ~ECHO;
+ tcsetattr(fd, TCSAFLUSH, &tio);
+ }
+}
+
+/* Enable character echoing, if the fd is a tty. */
+static void
+echoOn(int fd)
+{
+ if (isatty(fd)) {
+ struct termios tio;
+ tcgetattr(fd, &tio);
+ tio.c_lflag |= ECHO;
+ tcsetattr(fd, TCSAFLUSH, &tio);
+ }
+}
+
+/*
+ * This function is our custom password handler that is called by
+ * NSS when retrieving private certs and keys from the database. Returns a
+ * pointer to a string with a password for the database. Password pointer
+ * must be allocated by one of the PORT_* memory allocation fuinctions, or by PORT_Strdup,
+ * and will be freed by the caller.
+ */
+char *
+nssPasswordCallback (PK11SlotInfo *info __attribute ((unused)), PRBool retry, void *arg)
+{
+ static int retries = 0;
+ #define PW_MAX 200
+ char* password = NULL;
+ const char *dbname ;
+ int infd;
+ int isTTY;
+
+ if (! retry)
+ {
+ /* Not a retry. */
+ retries = 0;
+ }
+ else
+ {
+ /* Maximum of 2 retries for bad password. */
+ if (++retries > 2)
+ return NULL; /* No more retries */
+ }
+
+ /* Can only prompt for a password if stdin is a tty. */
+ infd = fileno (stdin);
+ isTTY = isatty (infd);
+ if (! isTTY)
+ return NULL;
+
+ /* Prompt for password */
+ password = PORT_Alloc (PW_MAX);
+ if (! password)
+ {
+ nssError ();
+ return NULL;
+ }
+
+ dbname = (const char *)arg;
+ fprintf (stderr, "Password for certificate database in %s: ", dbname);
+ fflush (stderr);
+ echoOff (infd);
+ fgets (password, PW_MAX, stdin);
+ fprintf( stderr, "\n");
+ echoOn(infd);
+
+ /* stomp on the newline */
+ password [strlen (password) - 1] = '\0';
+
+ return password;
+}
+
/* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */
+#include <nspr.h>
+#include <pk11func.h>
+
void nssError (void);
void nssCleanup (void);
+char *
+nssPasswordCallback (PK11SlotInfo *info __attribute ((unused)),
+ PRBool retry __attribute ((unused)),
+ void *arg __attribute ((unused)));
+
/* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */
# Generate a certificate for the systemtap server and add it to the
# database of trusted servers for the client.
#
-# Copyright (C) 2008-2010 Red Hat Inc.
+# Copyright (C) 2008-2011 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
# Initialize the environment
. ${PKGLIBEXECDIR}stap-env
-# Arguments
-serverdb="$1"
-shift
-
-# Domains for the certificate.
+serverdb=
domains="$HOSTNAME"
+use_db_password=0
+
+# Arguments
while test $# != 0
do
- test -n "$domains" && domains="$domains,"
- domains="${domains}$1"
- shift
+ case "$1" in
+ -P)
+ use_db_password=1
+ shift 1
+ ;;
+ --)
+ ;;
+ *)
+ if test -z "$serverdb"; then
+ # Server cert database
+ serverdb="$1"
+ else
+ # Domains for the certificate.
+ test -n "$domains" && domains="$domains,"
+ domains="${domains}$1"
+ fi
+ ;;
+ esac
+ shift
done
# Obtain the certificate database directory name.
exit 1
fi
-# Create the certificate database password file. Care must be taken
-# that this file is only readable by the owner.
-if ! (touch "$serverdb/pw" && chmod 600 "$serverdb/pw"); then
- echo "Unable to create the server certificate database password file: $serverdb/pw" >&2
+# If not using a database password, then create an empty certificate database password
+# file. This is a temporary file used only because certutil demands it.
+if test $use_db_password = 0; then
+ if ! (touch "$serverdb/pw" && chmod 600 "$serverdb/pw"); then
+ echo "Unable to create temporary certificate database password file: $serverdb/pw" >&2
exit 1
+ fi
+ # Generate the server certificate database. Filter the message about the passowrd file
+ # being empty.
+ certutil -N -d "$serverdb" -f "$serverdb/pw" 2>&1 >/dev/null | \
+ sed '/password file contains no data/ d'
+else
+ # Generate the server certificate database. certutil will ask for the password.
+ certutil -N -d "$serverdb" >/dev/null
fi
+rc=$?
+rm -fr "$serverdb/pw"
-# Generate a random password.
-mkpasswd -l 20 > "$serverdb/pw" 2>/dev/null || \
-apg -a 1 -n 1 -m 20 -x 20 > "$serverdb/pw" 2>/dev/null || \
-(read -n20 password </dev/urandom; echo "$password" > "$serverdb/pw")
-
-# Generate the server certificate database
-if ! certutil -N -d "$serverdb" -f "$serverdb/pw" > /dev/null; then
+if test $rc != 0; then
echo "Unable to initialize the server certificate database directory: $serverdb" >&2
exit 1
fi
dd bs=123 count=1 < /dev/urandom > "$serverdb/noise" 2> /dev/null
# Generate a request for the server's certificate.
-certutil -R -d "$serverdb" -f "$serverdb/pw" -s "CN=Systemtap Compile Server, OU=Systemtap" \
+certutil -R -d "$serverdb" -s "CN=Systemtap Compile Server, OU=Systemtap" \
-o "$serverdb/stap.req" -z "$serverdb/noise" 2> /dev/null
rm -fr "$serverdb/noise"
# Now generate the actual certificate. Make it valid for 1 year.
certutil -C -i "$serverdb/stap.req" -o "$serverdb/$stap_certfile" -x -d "$serverdb" \
- -f "$serverdb/pw" -v 12 -5 -8 "$domains" >/dev/null <<-EOF
+ -v 12 -5 -8 "$domains" >/dev/null <<-EOF
1
3
7
rm -fr "$serverdb/stap.req"
# Add the certificate to the server's certificate/key database as a trusted peer, ssl server and object signer
-certutil -A -n stap-server -t "PCu,,PCu" -i "$serverdb/$stap_certfile" -d "$serverdb" -f "$serverdb/pw"
+certutil -A -n stap-server -t "PCu,,PCu" -i "$serverdb/$stap_certfile" -d "$serverdb"
# Print some information about the certificate.
echo "Certificate $serverdb/$stap_certfile created and added to database $serverdb"
# Default option settings
# Optional global config file
OPT_CONFIG_FILE=
+OPT_USE_DB_PASSWORD=
echo_usage () {
echo $"Usage: $prog {start|stop|restart|condrestart|try-restart|force-reload|status} [options]"
test $? = 0 || rc=1
shift 1
;;
+ -P)
+ OPT_USE_DB_PASSWORD="-P"
+ shift 1
+ ;;
-r)
process_r "$2"
test $? = 0 || rc=1
fi
# Construct the server start command.
- local server_cmd="$STAP_START_SERVER -r \"`quote_for_cmd "$RELEASE"`\" -a \"`quote_for_cmd "$ARCH"`\""
+ local server_cmd="$STAP_START_SERVER -r \"`quote_for_cmd "$RELEASE"`\" -a \"`quote_for_cmd "$ARCH"`\" $OPT_USE_DB_PASSWORD"
for b in "${BUILD[@]}"; do
server_cmd="$server_cmd -B \"`quote_for_cmd "$b"`\""
done
exit 1
fi
-OPTS=`getopt -s bash -u -o 'a:B:c:iI:n:p:r:R:u:' -- "$@"`
+OPTS=`getopt -s bash -u -o 'a:B:c:iI:n:p:Pr:R:u:' -- "$@"`
if [ $? -ne 0 ]; then
echo "Error: Argument parse error: $@" >&2
echo_usage
the data into a temporary file, calls the systemtap translator and
then transmits the resulting file back to the client.
- Copyright (C) 2008-2010 Red Hat Inc.
+ Copyright (C) 2008-2011 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
/* Global variables */
-static char *password = NULL;
static CERTCertificate *cert = NULL;
static SECKEYPrivateKey *privKey = NULL;
static char *dbdir = NULL;
Usage(const char *progName)
{
fprintf(stderr,
- "Usage: %s -p port -d dbdir -n rsa_nickname -w passwordFile\n",
+ "Usage: %s -p port -d dbdir -n rsa_nickname\n",
progName);
exit(1);
}
exit(1);
}
-
-
-
/* Function: readDataFromSocket()
*
* Purpose: Read data from the socket into a temporary file.
{
PRFileDesc *sslSocket;
SSLKEAType certKEA;
-#if 0
- int certErr = 0;
-#endif
SECStatus secStatus;
/* Inport the socket into SSL. */
goto loser;
}
#endif
- secStatus = SSL_SetPKCS11PinArg(sslSocket, password);
- if (secStatus != SECSuccess)
- {
- errWarn("SSL_SetPKCS11PinArg");
- goto loser;
- }
certKEA = NSS_FindCertKEAType(cert);
PR_Close(listenSocket);
}
-/* Function: char * myPasswd()
- *
- * Purpose: This function is our custom password handler that is called by
- * SSL when retreiving private certs and keys from the database. Returns a
- * pointer to a string that with a password for the database. Password pointer
- * should point to dynamically allocated memory that will be freed later.
- */
-static char *
-myPasswd(PK11SlotInfo *info __attribute ((unused)), PRBool retry, void *arg)
-{
- char * passwd = NULL;
-
- if (! retry && arg)
- passwd = PORT_Strdup((char *)arg);
-
- return passwd;
-}
-
-/* Obtain the certificate and key database password from the given file. */
-static char *
-getPassword(char *fileName)
-{
- PRFileDesc *local_file_fd;
- PRFileInfo fileInfo;
- PRInt32 numBytesRead;
- PRStatus prStatus;
- char *password;
- PRInt32 i;
-
- prStatus = PR_GetFileInfo(fileName, &fileInfo);
- if (prStatus != PR_SUCCESS || fileInfo.type != PR_FILE_FILE || fileInfo.size < 0)
- {
- fprintf (stderr, "Password file %s not found\n", fileName);
- return NULL;
- }
-
- local_file_fd = PR_Open(fileName, PR_RDONLY, 0);
- if (local_file_fd == NULL)
- {
- fprintf (stderr, "Could not open password file %s\n", fileName);
- return NULL;
- }
-
- password = PORT_Alloc(fileInfo.size + 1);
- if (! password) {
- errWarn ("PORT_Alloc");
- return NULL;
- }
-
- numBytesRead = PR_Read(local_file_fd, password, fileInfo.size);
- if (numBytesRead <= 0)
- {
- fprintf (stderr, "Error reading password file\n");
- exitErr ("PR_Read");
- }
-
- PR_Close(local_file_fd);
-
- /* Keep only the first line of data. */
- for (i = 0; i < numBytesRead; ++i)
- {
- if (password[i] == '\n' || password[i] == '\r' ||
- password[i] == '\0')
- break;
- }
- password[i] = '\0';
-
- return password;
-}
-
/* Function: int main()
*
* Purpose: Parses command arguments and configures SSL server.
{
const char * progName = NULL;
const char * nickName = NULL;
- char * passwordFile = NULL;
unsigned short port = 0;
SECStatus secStatus;
PLOptState * optstate;
progName = PL_strdup(argv[0]);
- optstate = PL_CreateOptState(argc, argv, "d:p:n:w:s:");
+ optstate = PL_CreateOptState(argc, argv, "d:p:n:s:");
while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK)
{
switch(optstate->option)
case 'd': dbdir = PL_strdup(optstate->value); break;
case 'n': nickName = PL_strdup(optstate->value); break;
case 'p': port = PORT_Atoi(optstate->value); break;
- case 'w': passwordFile = PL_strdup(optstate->value); break;
case 's': stapOptions = PL_strdup(optstate->value); break;
default:
case '?': Usage(progName);
}
}
- if (nickName == NULL || port == 0 || dbdir == NULL || passwordFile == NULL)
+ if (nickName == NULL || port == 0 || dbdir == NULL)
Usage(progName);
- password = getPassword (passwordFile);
-
/* Call the NSPR initialization routines. */
PR_Init( PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
/* Set the cert database password callback. */
- PK11_SetPasswordFunc(myPasswd);
+ PK11_SetPasswordFunc (nssPasswordCallback);
/* Initialize NSS. */
secStatus = NSS_Init(dbdir);
exitErr("NSS_SetDomesticPolicy");
/* Get own certificate and private key. */
- cert = PK11_FindCertFromNickname(nickName, password);
+ cert = PK11_FindCertFromNickname(nickName, NULL);
if (cert == NULL)
exitErr("PK11_FindCertFromNickname");
- privKey = PK11_FindKeyByAnyCert(cert, password);
+ privKey = PK11_FindKeyByAnyCert(cert, dbdir); /* dbdir gets passed to nssPasswordCallback */
if (privKey == NULL)
exitErr("PK11_FindKeyByAnyCert");
# Compile server manager for systemtap
#
-# Copyright (C) 2008-2010 Red Hat Inc.
+# Copyright (C) 2008-2011 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
B_options=
I_options=
R_option=
+ use_db_password=
# Parse the arguments
parse_options "$@"
ssl_db="$stap_user_ssl_db/server"
fi
- nss_pw="$ssl_db/pw"
nss_cert=stap-server
# Ensure that our certificate is valid. Generate a new one if
get_arg "$first_token" "$2"
warning "Option '-$first_char $stap_arg' ignored"
;;
+ P)
+ use_db_password="-$first_char"
+ ;;
r)
get_arg "$first_token" "$2"
process_r $stap_arg
# If the certificate does not exist or the certificate
# is not valid, then generate a new one.
if test ! -d "$ssl_db" -o ! -f "$ssl_db/$stap_certfile" -o ! -f "$ssl_db/cert8.db" || \
- ! certutil -V -n $nss_cert -u V -d "$ssl_db" -e -f "$nss_pw" \
+ ! certutil -V -n $nss_cert -u V -d "$ssl_db" -e \
-b `date +%g%m%d%H%M%S`+0005 >> "$logfile" 2>&1; then
# Our certificate does not exist or is not valid.
# Generate a new certificate database.
- ${stap_pkglibexecdir}stap-gen-cert "$ssl_db" >> "$logfile" 2>&1 || exit 1
+ ${stap_pkglibexecdir}stap-gen-cert $use_db_password "$ssl_db" >> "$logfile" 2>&1 || exit 1
# Now add the new certificate to the client's database,
# making it a trusted peer for this user.
# too much / long computation
(test $set_ulimits = 1 && ulimit -f 50000 -s 1000 -t 60 -u 20 -v 500000;
exec ${stap_pkglibexecdir}stap-server-connect \
- -p $port -n $nss_cert -d "$ssl_db" -w "$nss_pw" \
- -s "$stap_options") &
+ -p $port -n $nss_cert -d "$ssl_db" -s "$stap_options") &
stap_server_connect_pid=$!
echo "$service_name ready"
wait $stap_server_connect_pid