]> rtime.felk.cvut.cz Git - novaboot.git/blob - server/novaboot-shell
server: Use $HOME rather than $XDG_RUNTIME_DIR
[novaboot.git] / server / novaboot-shell
1 #!/bin/sh
2
3 set -e
4
5 die() {
6     echo >&2 "novaboot-shell: $*"
7     exit 1
8 }
9
10 print_help() {
11     cat <<EOF
12 Target commands:
13 - console
14 - reset
15 - on
16 - off
17 - rsync ...
18
19 Management commands:
20 - help
21 EOF
22
23     if [ "$NB_ADMIN" ]; then
24         cat <<EOF
25 - add-key
26 EOF
27     fi
28     exit 0
29 }
30
31 add_key() {
32     local user
33     [ "$NB_ADMIN" ] || return 1
34
35     case $# in
36         0) die "Username argument missing";;
37         1) break;;
38         *) die "User name must not contain spaces: $*";;
39     esac
40     user="$1"
41     key=$(cat)
42
43     tmp=$(mktemp ~/.ssh/authorized_keys.XXXXXXXX)
44     {
45         cat ~/.ssh/authorized_keys
46         echo "command=\"user $user\" $key"
47     } | sort -u > $tmp
48
49     mv $tmp ~/.ssh/authorized_keys
50 }
51
52 lock_queue() {
53     lslocks | awk '{ if ($9 == "'"$RUN_DIR"'") { print $2 } }'
54 }
55
56 print_queue() {
57     local queue
58
59     queue=$(
60         for pid in $(lock_queue); do
61             echo $pid $(sed --null-data -ne '/^NOVABOOT_ID=/ s///p' /proc/$pid/environ)
62         done | sort)
63     if [ "$queue" ]; then
64         echo "Target is occupied by:"
65         ( echo "PID USER LOGIN_TIME FROM"; echo "$queue" ) | column -t
66     fi
67 }
68
69 locked() {
70     print_queue
71     exec flock --no-fork "$RUN_DIR" "$@"
72 }
73
74 unlocked() {
75     exec "$@"
76 }
77
78 check_var() {
79     if eval [ "\"\$$1\"" ]; then
80         return 0
81     else
82         die "$1 variable not defined in $CFG"
83     fi
84 }
85
86 # run_subcommand should be called only after permission checks and/or locking
87 run_subcommand() {
88     case "$*" in
89         "console")
90             trap "rm -f $RUN_DIR/ppid" EXIT
91             echo $NOVABOOT_PPID > $RUN_DIR/ppid
92             echo 'novaboot-shell: Connected'
93             # TODO: $reset_begin_cmd
94             check_var console_cmd && eval exec $console_cmd;;
95         "reset")
96             check_var reset_cmd && eval exec $reset_cmd;;
97         "rsync --server "*" . .")
98             if ! [ $# -eq 5 -o \( $# -eq 6 -a "$4" = '--log-format=X' \) ]; then
99                 die "Unexpected rsync invocation: $*"
100             fi
101             mkdir -p "$HOME/tftproot"
102             cd "$HOME/tftproot"
103             exec "$@";;
104         "on")
105             check_var on_cmd && eval exec $on_cmd;;
106         "off")
107             check_var off_cmd && eval exec $off_cmd;;
108     esac
109 }
110
111 main() {
112     if [ "$1" = "-c" ]; then shift
113     else die "Permission denied"; fi
114
115     NB_ADMIN=
116     if [ "${1%% *}" = "user" ]; then
117         # Get user name encoded in ~/.ssh/authorized_keys
118         set -- $1
119         NB_USER="$2";
120         [ "$3" = "admin" ] && NB_ADMIN=1
121         set -- $SSH_ORIGINAL_COMMAND
122     fi
123
124     if [ $# -eq 0 ]; then print_help; fi
125
126     IP=${SSH_CONNECTION%% *}
127     HOST=$(getent hosts $IP) || HOST=$IP
128     REMOTE=${HOST##* }
129     DATE=$(LANG=C date +'%F_%T')
130     export NOVABOOT_ID="${NB_USER:-?} $DATE ${REMOTE}"
131     export NOVABOOT_PPID=$PPID
132
133     mkdir -p "$RUN_DIR"
134
135     case "$1" in
136         # Commands allowed at any time
137         "console") locked $0 console;;
138         "get-config") target_config; exit;;
139         "add-key") shift; add_key "$@"; exit;;
140         "help") print_help;;
141
142         # Commands allowed only when nobody or the same user is connected
143         # to the console. "The same user" means that we were executed by
144         # the same sshd process that has the lock. This is ensured by
145         # using SSH connection sharing on cline side.
146         reset | rsync | on | off)
147             ALLOWED_PPID=$(cat $RUN_DIR/ppid 2>/dev/null || :)
148             if [ "$PPID" -eq "${ALLOWED_PPID:-0}" ]; then run=unlocked; else run=locked; fi
149             $run $0 "$@";;
150         *)
151             echo >&2 "novaboot-shell: Command not allowed: $*"
152             logger -p error "novaboot-shell: Command not allowed: $*"
153             exit 1;;
154     esac
155 }
156
157 RUN_DIR="$HOME"
158
159 if [ "$NOVABOOT_SHELL_CONFIG" ]; then
160     CFG="$NOVABOOT_SHELL_CONFIG"
161 else
162     CFG="$HOME/.novaboot-shell"
163 fi
164
165 . "$CFG"
166
167 if [ -z "$NOVABOOT_ID" ]; then
168     main "$@"
169 else
170     run_subcommand "$@"
171 fi