]> sourceware.org Git - systemtap.git/blobdiff - stap-serverd
YAAU (Yet Another AUTHORS Update)
[systemtap.git] / stap-serverd
index 2c0743c0809eff297fd0258e9aead728a328f242..4eee8c381714eb322a4ca4f4b82f53f1cf93a731 100755 (executable)
@@ -2,7 +2,7 @@
 
 # Compile server manager for systemtap
 #
-# Copyright (C) 2008 Red Hat Inc.
+# Copyright (C) 2008, 2009 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
 # incoming connections. When a connection is detected, the stap-server script
 # is run to handle the request.
 
-# Catch ctrl-c
-trap 'handle_sigint' SIGINT
+# Catch ctrl-c and other termination signals
+trap 'terminate' SIGTERM SIGINT
+
+# Initialize the environment
+. `dirname $0`/stap-env
 
 #-----------------------------------------------------------------------------
 # Helper functions.
 #-----------------------------------------------------------------------------
 # function: initialization PORT
 function initialization {
-    # Default settings.
-    tmpdir_prefix_serverd=stap.serverd
-    avahi_type=_stap._tcp
+    # What port will we listen on?
     port=$1
     test "X$port" = "X" && port=65000
+    while netstat -atn | awk '{print $4}' | cut -f2 -d: | egrep -q "^$port\$";
+    do
+        # Whoops, the port is busy; try another one.
+       echo "$0: Port $port is busy"
+        port=$((1024+($port + $RANDOM)%64000))
+    done
+
+    # Where is the ssl certificate/key database?
+    ssl_db=$2
+    if test "X$ssl_db" = "X"; then
+       ssl_db=$stap_ssl_db/server
+       # Update the certificate file if it is old.
+       if test -f $ssl_db/$stap_old_certfile; then
+           if ! test -e $ssl_db/$stap_certfile; then
+               mv $ssl_db/$stap_old_certfile $ssl_db/$stap_certfile
+           else
+               rm -fr $ssl_db/$stap_old_certfile
+           fi
+       fi
+       # If no certificate/key database has been specified, then find/create
+       # a local one.
+       if ! test -f $ssl_db/$stap_certfile; then
+           ${stap_exec_prefix}stap-gen-cert $ssl_db || exit 1
+            # Now add the server's certificate to the client's database,
+           # making it a trusted peer. Do this only if the client has been installed.
+           if test -f `which ${stap_exec_prefix}stap-client` -a \
+                   -x `which ${stap_exec_prefix}stap-client`; then
+               ${stap_exec_prefix}stap-authorize-server-cert $ssl_db/$stap_certfile
+           fi
+       elif ! test -f $stap_ssl_db/client/cert8.db; then
+           # If the client's database does not exist, then initialize it with our certificate.
+           # Do this only if the client has been installed.
+           if test -f `which ${stap_exec_prefix}stap-client` -a \
+                    -x `which ${stap_exec_prefix}stap-client`; then
+               ${stap_exec_prefix}stap-authorize-server-cert $ssl_db/$stap_certfile
+           fi
+       fi
+    fi
+
+    # Check the security of the database.
+    check_db $ssl_db
+
+    nss_pw=$ssl_db/pw
+    nss_cert=stap-server
 }
 
 # function: advertise_presence
@@ -34,13 +79,12 @@ function initialization {
 function advertise_presence {
     # Build up a string representing our server's properties.
     # TODO: this needs fleshing out.
-
-    local sysinfo=`uname -r`
-    local txt="$sysinfo"
+    local sysinfo=`uname -rvm`
+    local txt="sysinfo=$sysinfo"
 
     # Call avahi-publish-service to advertise our presence.
     avahi-publish-service "Systemtap Compile Server on `uname -n`" \
-       $avahi_type $port $txt > /dev/null 2>&1 &
+       $stap_avahi_service_tag $port "$txt" > /dev/null 2>&1 &
 
     echo "Systemtap Compile Server on `uname -n` listening on port $port"
 }
@@ -49,21 +93,224 @@ function advertise_presence {
 #
 # Listen for and handle requests to the server.
 function listen {
-    # Work in a temporary directory
-    tmpdir=`mktemp -dt $tmpdir_prefix_serverd.XXXXXX` || \
-       fatal "ERROR: cannot create temporary directory " $tmpdir
-    cd $tmpdir
-
-    # Create a fifo for communicating with the server
-    local fifo_name=$tmpdir_prefix_serverd.fifo
-    mknod $fifo_name p || \
-       fatal "ERROR: cannot create temporary fifo " $tmpdir/$fifo_name
-
-    # Loop forever accepting requests
-    while true
-    do
-       nc -l $port < $fifo_name | stap-server $((port + 1)) > $fifo_name 2>&1
-    done
+    # The stap-server-connect program will listen forever
+    # accepting requests.
+    ${stap_exec_prefix}stap-server-connect -p $port -n $nss_cert -d $ssl_db -w $nss_pw 2>&1 &
+    wait '%${stap_exec_prefix}stap-server-connect' >/dev/null 2>&1
+}
+
+# function: check_db DBNAME
+#
+# Check the security of the given database directory.
+function check_db {
+    local dir=$1
+    local rc=0
+
+    # Check that we have been given a directory
+    if ! test -e $dir; then
+       warning "Certificate database '$dir' does not exist"
+       return 1
+    fi
+    if ! test -d $dir; then
+       warning "Certificate database '$dir' is not a directory"
+       return 1
+    fi
+
+    # Check that we can read the directory
+    if ! test -r $dir; then
+       warning "Certificate database '$dir' is not readble"
+       rc=1
+    fi
+
+    # We must be the owner of the database.
+    local ownerid=`stat -c "%u" $dir`
+    if test "X$ownerid" != "X$EUID"; then
+       warning "Certificate database '$dir' must be owned by $USER"
+       rc=1
+    fi
+
+    # Check the access permissions of the directory
+    local perm=0`stat -c "%a" $dir`
+    if test $((($perm & 0400) == 0400)) = 0; then
+       warning "Certificate database '$dir' should be readable by the owner"
+    fi
+    if test $((($perm & 0200) == 0200)) = 0; then
+       warning "Certificate database '$dir' should be writeable by the owner"
+    fi
+    if test $((($perm & 0100) == 0100)) = 0; then
+       warning "Certificate database '$dir' should be searchable by the owner"
+    fi
+    if test $((($perm & 0040) == 0040)) = 0; then
+       warning "Certificate database '$dir' should be readable by the group"
+    fi
+    if test $((($perm & 0020) == 0020)) = 1; then
+       warning "Certificate database '$dir' must not be writable by the group"
+       rc=1
+    fi
+    if test $((($perm & 0010) == 0010)) = 0; then
+       warning "Certificate database '$dir' should be searchable by the group"
+    fi
+    if test $((($perm & 0004) == 0004)) = 0; then
+       warning "Certificate database '$dir' should be readable by others"
+    fi
+    if test $((($perm & 0002) == 0002)) = 1; then
+       warning "Certificate database '$dir' must not be writable by others"
+       rc=1
+    fi
+    if test $((($perm & 0001) == 0001)) = 0; then
+       warning "Certificate database '$dir' should be searchable by others"
+    fi
+
+    # Now check the permissions of the critical files.
+    check_db_file $dir/cert8.db || rc=1
+    check_db_file $dir/key3.db || rc=1
+    check_db_file $dir/secmod.db || rc=1
+    check_db_file $dir/pw || rc=1
+    check_cert_file $dir/$stap_certfile || rc=1
+
+    test $rc = 1 && fatal "Unable to use certificate database '$dir' due to errors"
+
+    return $rc
+}
+
+# function: check_db_file FILENAME
+#
+# Check the security of the given database file.
+function check_db_file {
+    local file=$1
+    local rc=0
+
+    # Check that we have been given a file
+    if ! test -e $file; then
+       warning "Certificate database file '$file' does not exist"
+       return 1
+    fi
+    if ! test -f $file; then
+       warning "Certificate database file '$file' is not a regular file"
+       return 1
+    fi
+
+    # We must be the owner of the file.
+    local ownerid=`stat -c "%u" $file`
+    if test "X$ownerid" != "X$EUID"; then
+       warning "Certificate database file '$file' must be owned by $USER"
+       rc=1
+    fi
+
+    # Check that we can read the file
+    if ! test -r $file; then
+       warning "Certificate database file '$file' is not readble"
+       rc=1
+    fi
+
+    # Check the access permissions of the file
+    local perm=0`stat -c "%a" $file`
+    if test $((($perm & 0400) == 0400)) = 0; then
+       warning "Certificate database file '$file' should be readable by the owner"
+    fi
+    if test $((($perm & 0200) == 0200)) = 0; then
+       warning "Certificate database file '$file' should be writeable by the owner"
+    fi
+    if test $((($perm & 0100) == 0100)) = 1; then
+       warning "Certificate database file '$file' must not be executable by the owner"
+       rc=1
+    fi
+    if test $((($perm & 0040) == 0040)) = 1; then
+       warning "Certificate database file '$file' must not be readable by the group"
+       rc=1
+    fi
+    if test $((($perm & 0020) == 0020)) = 1; then
+       warning "Certificate database file '$file' must not be writable by the group"
+       rc=1
+    fi
+    if test $((($perm & 0010) == 0010)) = 1; then
+       warning "Certificate database file '$file' must not be executable by the group"
+       rc=1
+    fi
+    if test $((($perm & 0004) == 0004)) = 1; then
+       warning "Certificate database file '$file' must not be readable by others"
+       rc=1
+    fi
+    if test $((($perm & 0002) == 0002)) = 1; then
+       warning "Certificate database file '$file' must not be writable by others"
+       rc=1
+    fi
+    if test $((($perm & 0001) == 0001)) = 1; then
+       warning "Certificate database file '$file' must not be executable by others"
+       rc=1
+    fi
+
+    return $rc
+}
+
+# function: check_db_file FILENAME
+#
+# Check the security of the given database file.
+function check_cert_file {
+    local file=$1
+    local rc=0
+
+    # Check that we have been given a file
+    if ! test -e $file; then
+       warning "Certificate database file '$file' does not exist"
+       return 1
+    fi
+    if ! test -f $file; then
+       warning "Certificate database file '$file' is not a regular file"
+       return 1
+    fi
+
+    # We must be the owner of the file.
+    local ownerid=`stat -c "%u" $file`
+    if test "X$ownerid" != "X$EUID"; then
+       warning "Certificate file '$file' must be owned by $USER"
+       rc=1
+    fi
+
+    # Check the access permissions of the file
+    local perm=0`stat -c "%a" $file`
+    if test $((($perm & 0400) == 0400)) = 0; then
+       warning "Certificate file '$file' should be readable by the owner"
+    fi
+    if test $((($perm & 0200) == 0200)) = 0; then
+       warning "Certificate file '$file' should be writeable by the owner"
+    fi
+    if test $((($perm & 0100) == 0100)) = 1; then
+       warning "Certificate file '$file' must not be executable by the owner"
+       rc=1
+    fi
+    if test $((($perm & 0040) == 0040)) = 0; then
+       warning "Certificate file '$file' should be readable by the group"
+    fi
+    if test $((($perm & 0020) == 0020)) = 1; then
+       warning "Certificate file '$file' must not be writable by the group"
+       rc=1
+    fi
+    if test $((($perm & 0010) == 0010)) = 1; then
+       warning "Certificate file '$file' must not be executable by the group"
+       rc=1
+    fi
+    if test $((($perm & 0004) == 0004)) = 0; then
+       warning "Certificate file '$file' should be readable by others"
+    fi
+    if test $((($perm & 0002) == 0002)) = 1; then
+       warning "Certificate file '$file' must not be writable by others"
+       rc=1
+    fi
+    if test $((($perm & 0001) == 0001)) = 1; then
+       warning "Certificate file '$file' must not be executable by others"
+       rc=1
+    fi
+
+    return $rc
+}
+
+# function: warning [ MESSAGE ]
+#
+# Warning error
+# Prints its arguments to stderr
+function warning {
+    echo "$0: WARNING:" "$@" >&2
 }
 
 # function: fatal [ MESSAGE ]
@@ -71,17 +318,25 @@ function listen {
 # Fatal error
 # Prints its arguments to stderr and exits
 function fatal {
-    echo "$@" >&2
+    echo "$0: ERROR:" "$@" >&2
+    terminate
     exit 1
 }
 
-# function: handle_sigint
+# function: terminate
 #
-# Terminate gracefully when SIGINT is received.
-function handle_sigint {
-    echo "$0: received SIGINT. Exiting."
-    cd `dirname $tmpdir`
-    rm -fr $tmpdir
+# Terminate gracefully.
+function terminate {
+    echo "$0: Exiting"
+
+    # Kill the running 'avahi-publish-service' job
+    kill -s SIGTERM '%avahi-publish-service' 2> /dev/null
+    wait '%avahi-publish-service' >/dev/null 2>&1
+
+    # Kill any running 'stap-server-connect' job.
+    kill -s SIGTERM '%${stap_exec_prefix}stap-server-connect' 2> /dev/null
+    wait '%${stap_exec_prefix}stap-server-connect'  >/dev/null 2>&1
+
     exit
 }
 
This page took 0.033051 seconds and 5 git commands to generate.