summaryrefslogtreecommitdiffstats
path: root/stap-serverd
blob: 818e3ec336bba8b47a555e8fbec39dc9aadcf0e4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
#!/bin/bash

# Compile server manager for systemtap
#
# 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
# Public License (GPL); either version 2, or (at your option) any
# later version.

# This script publishes its presence on the network and then listens for
# incoming connections. When a connection is detected, the stap-server script
# is run to handle the request.

# Catch ctrl-c and other termination signals
trap 'terminate' SIGTERM SIGINT

#-----------------------------------------------------------------------------
# Helper functions.
#-----------------------------------------------------------------------------
# function: initialization PORT
function initialization {
    # Default settings.
    avahi_type=_stap._tcp

    # Where are we installed?
    exec_prefix=`dirname $0`
    exec_prefix=`cd $exec_prefix && pwd`
    prefix=`dirname $exec_prefix`

    # 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
	# If no certificate/key database has been specified, then find/create
	# a local one.
	if test $EUID = 0; then
	    ssl_db=$prefix/etc/systemtap/ssl/server
	else
	    ssl_db=$HOME/.systemtap/ssl/server
	fi
	if ! test -f $ssl_db/stap-server.cert; then
	    $exec_prefix/stap-gen-server-cert `dirname $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 $exec_prefix/stap-add-server-cert -a -f $exec_prefix/stap-add-server-cert; then
		$exec_prefix/stap-add-server-cert $ssl_db/stap-server.cert `dirname $ssl_db`
	    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
#
# Advertise the availability of the server on the network.
function advertise_presence {
    # Build up a string representing our server's properties.
    # TODO: this needs fleshing out.
    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 &

    echo "Systemtap Compile Server on `uname -n` listening on port $port"
}

# function: listen
#
# Listen for and handle requests to the server.
function listen {
    # The stap-server-connect program will listen forever
    # accepting requests.
    $exec_prefix/stap-server-connect -p $port -n $nss_cert -d $ssl_db -w $nss_pw 2>&1 &
    wait '%$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

    # 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-server.cert || 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

    # 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

    # 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 ]
#
# Fatal error
# Prints its arguments to stderr and exits
function fatal {
    echo "$0: FATAL:" "$@" >&2
    terminate
    exit 1
}

# function: terminate
#
# 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 '%$exec_prefix/stap-server-connect' 2> /dev/null
    wait '%$exec_prefix/stap-server-connect'  >/dev/null 2>&1

    exit
}

#-----------------------------------------------------------------------------
# Beginning of main line execution.
#-----------------------------------------------------------------------------
initialization "$@"
advertise_presence
listen