summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog17
-rwxr-xr-xstap-client166
-rw-r--r--stap-client-connect.c19
3 files changed, 154 insertions, 48 deletions
diff --git a/ChangeLog b/ChangeLog
index fd6c7e06..941bf91f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,20 @@
+2009-01-28 Dave Brolley <brolley@redhat.com>
+
+ * stap-client (parse_options): Handle the --server option.
+ (process_server): New function.
+ (find_and_connect_to_server): Create the server's .jar file
+ here. Process $specified_servers if present. Issue server
+ connection error here ...
+ (choose_server): ... not here.
+ (send_receive): Don't create the server's .jar file here.
+ Always check the local certificate databases. Echo the
+ name of the database used to successfully authenticate the
+ server.
+ * stap-client-connect.c (sslerr.h): #include it.
+ (errWarn): Handle SEC_ERROR_BAD_DATABASE and SSL_ERROR_BAD_CERT_DOMAIN.
+ (do_connect): Don't call PR_GetHostByName or PR_EnumerateHostEnt.
+ (client_main): No longer takes 'hostName' argument. Update all callers.
+
2009-01-26 Mark Wielaard <mjw@redhat.com>
* dtrace: Handle (absense of) -o argument correctly.
diff --git a/stap-client b/stap-client
index 09ee60bf..1a23361c 100755
--- a/stap-client
+++ b/stap-client
@@ -111,6 +111,9 @@ function parse_options {
ssl)
process_ssl $first_token
;;
+ server)
+ process_server $first_token
+ ;;
*)
# An unknown or unimportant option.
# Ignore it, but pass it on to the server.
@@ -282,6 +285,18 @@ function process_ssl {
additional_local_ssl_dbs="$additional_local_ssl_dbs $db"
}
+# function: process_server ARGUMENT
+#
+# Process the --server option.
+function process_server {
+ local spec=`expr "$1" : '--server=\(.*\)'`
+
+ test "X$spec" != "X" || \
+ fatal "Missing argument to --server"
+
+ specified_servers="$specified_servers $spec"
+}
+
# function: process_c ARGUMENT
#
# Process the -c flag.
@@ -493,31 +508,106 @@ function unpack_response {
#
# Find and establish connection with a compatible stap server.
function find_and_connect_to_server {
- # Use a temp file here instead of a pipeline so that the side effects
- # of choose_server are seen by the rest of this script.
- cd $tmpdir_client
- ${exec_prefix}stap-find-servers > servers
- choose_server < servers
- rm -fr servers
+ local num_servers=0
+
+ # Make a place to receive the response file.
+ jar_server=`mktemp -t $tmpdir_prefix_client.server.jar.XXXXXX` || \
+ fatal "ERROR: cannot create temporary file " $jar_server
+
+ # If servers were specified on the command line, then try them
+ # in sequence. Don't try any other servers.
+ if test "X$specified_servers" != "X"; then
+ for server in $specified_servers; do
+ num_servers=$(($num_servers + 1))
+
+ # If the server is completely specified, (i.e. server:port),
+ # then try it directly.
+ port=`expr "$server" : '.\+:\([0-9]\+\)'`
+ if test "X$port" != "X"; then
+ name=`expr "$server" : '\(.\+\):[0-9]\+'`
+
+ # If we have been given an ip address, then try to resolve it to a name.
+ # If we have been given a name, try to resolve the full name.
+ # The full name is needed in order to validate the server's certificate.
+ address=`expr "$name" : '\([0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+\)'`
+ if test "X$address" = "X"; then
+ # We've been given a host name
+ full_name=`nslookup $name | awk '/^Name\:/ {print $2}'`
+ if test "X$full_name" != "X"; then
+ name=$full_name
+ fi
+ else
+ # We've been given an ip address.
+ name=`nslookup $address | awk '/^$address.+name = .+\.$/ {print $4}'`
+ if test "X$name" = "X"; then
+ echo "Cannot resolve ip address $address" >> $tmpdir_client/connect
+ continue
+ fi
+ fi
+
+ # Now try to contact the given server.
+ ssl_db=`send_receive $name $port`
+ test "X$ssl_db" != "X" && return
+ continue
+ fi
+
+ # Otherwise select the matching server from the available servers
+ # and use the port it is advertizing.
+ #
+ # Have we been given an ip address? If so, just use it.
+ address=`expr "$server" : '\([0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+\)'`
+ if test "X$address" = "X"; then
+ # We have not been given an ip address. Try to resolve it as a host name.
+ address=`nslookup $server | awk '/^Address\:[ \t][0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$/ {print $2}'`
+ if test "X$address" = "X"; then
+ echo "Cannot resolve server $server" >> $tmpdir_client/connect
+ continue
+ fi
+ fi
+
+ if test `${exec_prefix}stap-find-servers | grep $address | wc -l` = "0"; then
+ echo "No server is available on $server" >> $tmpdir_client/connect
+ continue
+ fi
+
+ ssl_db=`${exec_prefix}stap-find-servers | grep $address | choose_server`
+ test "X$ssl_db" != "X" && return
+ done
+ else
+ # No servers specified. Find available servers and choose one of them.
+ # Remember which ssl certificate database was used to authenticate the chosen
+ # server.
+ ssl_db=`${exec_prefix}stap-find-servers | choose_server`
+ test "X$ssl_db" != "X" && return
+
+ num_servers=`${exec_prefix}stap-find-servers | wc -l`
+ fi
+
+ if test $num_servers = 0; then
+ fatal "ERROR: unable to find a server"
+ fi
+
+ cat $tmpdir_client/connect >&2
+ fatal "ERROR: unable to connect to a server"
}
# function: choose_server
#
# Examine each line from stdin and attempt to connect to each server
# specified until successful.
+# echo the name of the ssl certificate database used to successfully authenticate
+# the server.
function choose_server {
- local num_servers=0
local name
+ local our_host_name=`expr "$HOSTNAME" : "\\\([a-zA-Z0-9-]*\\\).*"`
+ local our_domain_name=`expr "$HOSTNAME" : "$our_host_name\\\(.*\\\)"`
+
while read name server port remain
do
- num_servers=$(($num_servers + 1))
-
# The server must match the dns name on the certificate
# and must be 'localhost' if the server is on the local host.
local server_host_name=`expr "$name" : "\\\([a-zA-Z0-9-]*\\\).*"`
local server_domain_name=`expr "$name" : "$server_host_name\\\(.*\\\)"`
- local our_host_name=`expr "$HOSTNAME" : "\\\([a-zA-Z0-9-]*\\\).*"`
- local our_domain_name=`expr "$HOSTNAME" : "$our_host_name\\\(.*\\\)"`
if test "X$server_domain_name" = "X.local"; then
server_domain_name=$our_domain_name
@@ -529,61 +619,51 @@ function choose_server {
fi
if test "X$server" = "X"; then
- fatal "ERROR: server ip address not provided"
+ fatal "ERROR: server ip address not provided by avahi"
fi
if test "X$port" = "X"; then
- fatal "ERROR: server port not provided"
+ fatal "ERROR: server port not provided by avahi"
fi
- if send_receive; then
- return 0
- fi
+ ssl_db=`send_receive $server $port`
+ test "X$ssl_db" != "X" && echo $ssl_db && return
done
-
- if test $num_servers = 0; then
- fatal "ERROR: unable to find a server"
- fi
-
- cat $tmpdir_client/connect >&2
- fatal "ERROR: unable to connect to a server"
}
-# function: send_receive
+# function: send_receive SERVER PORT
#
# Connect to the server, send the request and receive the response
+# echo the name of the ssl certificate database used to successfully authenticate
+# the server.
function send_receive {
- # Make a place to receive the response file.
- jar_server=`mktemp -t $tmpdir_prefix_client.server.jar.XXXXXX` || \
- fatal "ERROR: cannot create temporary file " $jar_server
+ local server=$1
+ local port=$2
- # If the server is local, try to connect using each of the given local
- # certificate databases in turn for verification.
- if test "X$server" = "Xlocalhost"; then
- for db in $local_ssl_dbs
- do
- # Send the request and receive the response using stap-client-connect
- echo "Attempting connection with $server using certificate database in '$db'" >> $tmpdir_client/connect
- ${exec_prefix}stap-client-connect -i $zip_client -o $jar_server -d $db -p $port -h $server >> $tmpdir_client/connect 2>&1 &
- wait '%${exec_prefix}stap-client-connect'
- test $? = 0 && ssl_db=$db && return 0
- sleep 1
- done
- fi
+ # Try to connect using each of the given local certificate databases in turn
+ # for verification.
+ for db in $local_ssl_dbs
+ do
+ # Send the request and receive the response using stap-client-connect
+ echo "Attempting connection with $server using certificate database in '$db'" >> $tmpdir_client/connect
+ ${exec_prefix}stap-client-connect -i $zip_client -o $jar_server -d $db -p $port -h $server >> $tmpdir_client/connect 2>&1 &
+ wait '%${exec_prefix}stap-client-connect'
+ test $? = 0 && echo $db && return
+ sleep 1
+ done
- # We can try the public certificate databases for all servers.
+ # Next, try the public certificate databases.
for db in $public_ssl_dbs
do
# Send the request and receive the response using stap-client-connect
echo "Attempting connection with $server using certificate database in '$db'" >> $tmpdir_client/connect
${exec_prefix}stap-client-connect -i $zip_client -o $jar_server -d $db -p $port -h $server >> $tmpdir_client/connect 2>&1 &
wait '%${exec_prefix}stap-client-connect'
- test $? = 0 && ssl_db=$db && return 0
+ test $? = 0 && echo $db && return
sleep 1
done
# Could not connect using any of the certificate databases
- return 1
}
# function: process_response
diff --git a/stap-client-connect.c b/stap-client-connect.c
index 9466b566..fd64f6c7 100644
--- a/stap-client-connect.c
+++ b/stap-client-connect.c
@@ -27,6 +27,7 @@
#include <nss.h>
#include <prerror.h>
#include <secerr.h>
+#include <sslerr.h>
#define READ_BUFFER_SIZE (60 * 1024)
static char *hostName = NULL;
@@ -74,6 +75,12 @@ errWarn(char *function)
case SEC_ERROR_CA_CERT_INVALID:
fputs ("The issuer's certificate is invalid\n", stderr);
break;
+ case SEC_ERROR_BAD_DATABASE:
+ fputs ("The specified certificate database does not exist or is not valid\n", stderr);
+ break;
+ case SSL_ERROR_BAD_CERT_DOMAIN:
+ fputs ("The requested domain name does not match the server's certificate\n", stderr);
+ break;
case PR_CONNECT_RESET_ERROR:
fputs ("Connection reset by peer\n", stderr);
break;
@@ -307,10 +314,12 @@ static SECStatus
do_connect(PRNetAddr *addr)
{
PRFileDesc *sslSocket;
+ PRStatus prStatus;
+#if 0
PRHostEnt hostEntry;
char buffer[PR_NETDB_BUF_SIZE];
- PRStatus prStatus;
PRIntn hostenum;
+#endif
SECStatus secStatus;
secStatus = SECSuccess;
@@ -338,7 +347,7 @@ do_connect(PRNetAddr *addr)
errWarn("SSL_SetURL");
goto done;
}
-
+#if 0 /* Already done? */
/* Prepare and setup network connection. */
prStatus = PR_GetHostByName(hostName, buffer, sizeof(buffer), &hostEntry);
if (prStatus != PR_SUCCESS)
@@ -355,7 +364,7 @@ do_connect(PRNetAddr *addr)
secStatus = SECFailure;
goto done;
}
-
+#endif
prStatus = PR_Connect(sslSocket, addr, PR_INTERVAL_NO_TIMEOUT);
if (prStatus != PR_SUCCESS)
{
@@ -397,7 +406,7 @@ do_connect(PRNetAddr *addr)
}
static void
-client_main(unsigned short port, const char *hostName)
+client_main(unsigned short port)
{
SECStatus secStatus;
PRStatus prStatus;
@@ -479,7 +488,7 @@ main(int argc, char **argv)
/* All cipher suites except RSA_NULL_MD5 are enabled by Domestic Policy. */
NSS_SetDomesticPolicy();
- client_main(port, hostName);
+ client_main(port);
NSS_Shutdown();
PR_Cleanup();