Fix `make distcheck`
[tinc] / test / command-fsck.test
1 #!/bin/sh
2
3 . ./testlib.sh
4
5 foo_dir=$(peer_directory foo)
6 foo_host=$foo_dir/hosts/foo
7 foo_conf=$foo_dir/tinc.conf
8 foo_rsa_priv=$foo_dir/rsa_key.priv
9 foo_ec_priv=$foo_dir/ed25519_key.priv
10 foo_tinc_up=$foo_dir/tinc-up
11 foo_host_up=$foo_dir/host-up
12
13 if is_windows; then
14   foo_tinc_up=$foo_tinc_up.cmd
15   foo_host_up=$foo_host_up.cmd
16 fi
17
18 # Sample RSA key pair (old format). Uses e = 0xFFFF.
19 rsa_n=BB82C3A9B906E98ABF2D99FF9B320B229F5C1E58EC784762DA1F4D3509FFF78ECA7FFF19BA170736CDE458EC8E732DDE2C02009632DF731B4A6BD6C504E50B7B875484506AC1E49FD0DF624F6612F564C562BD20F870592A49195023D744963229C35081C8AE48BE2EBB5CC9A0D64924022DC0EB782A3A8F3EABCA04AA42B24B2A6BD2353A6893A73AE01FA54891DD24BF36CA032F19F7E78C01273334BAA2ECF36B6998754CB012BC985C975503D945E4D925F6F719ACC8FBA7B18C810FF850C3CCACD60565D4FCFE02A98FE793E2D45D481A34D1F90584D096561FF3184C462C606535F3F9BB260541DF0D1FEB16938FFDEC2FF96ACCC6BD5BFBC19471F6AB
20 rsa_d=8CEC9A4316FE45E07900197D8FBB52D3AF01A51C4F8BD08A1E21A662E3CFCF7792AD7680673817B70AC1888A08B49E8C5835357016D9BF56A0EBDE8B5DF214EC422809BC8D88177F273419116EF2EC7951453F129768DE9BC31D963515CC7481559E4C0E65C549169F2B94AE68DB944171189DD654DC6970F2F5843FB7C8E9D057E2B5716752F1F5686811AC075ED3D3CBD06B5D35AE33D01260D9E0560AF545D0C9D89A31D5EAF96D5422F6567FE8A90E23906B840545805644DFD656E526A686D3B978DD271578CA3DA0F7D23FC1252A702A5D597CAE9D4A5BBF6398A75AF72582C7538A7937FB71A2610DCBC39625B77103FA3B7D0A55177FD98C39CD4A27
21
22 # Extracts the PEM key from a config file, leaving the file unchanged.
23 # usage: extract_pem_key_from_config path_to_file
24 extract_pem_key_from_config() {
25   sed -n '/-----BEGIN /,/-----END /p' "$1"
26 }
27
28 # Removes the PEM key from a config file.
29 # usage: rm_pem_key_from_config path_to_file
30 rm_pem_key_from_config() {
31   sed_cmd '/-----BEGIN /,/-----END /d' "$1"
32 }
33
34 reinit_configs() {
35   if [ -d "$foo_dir" ]; then
36     chmod -f 755 "$foo_dir"
37     rm -rf "$foo_dir"
38   fi
39
40   tinc foo <<EOF
41 init foo
42 set DeviceType dummy
43 EOF
44 }
45
46 fsck_test() {
47   echo >&2 "[STEP] $*"
48   reinit_configs
49 }
50
51 run_access_checks() {
52   ! is_root && ! is_windows
53 }
54
55 test_private_keys() {
56   keyfile=$1
57
58   fsck_test "Must fail on broken $keyfile"
59   printf '' >"$foo_dir/$keyfile"
60   if with_legacy; then
61     expect_msg 'no private key is known' tinc foo fsck
62   else
63     must_fail_with_msg 'no Ed25519 private key found' tinc foo fsck
64   fi
65
66   if run_access_checks; then
67     fsck_test "Must fail on inaccessible $keyfile"
68     chmod 000 "$foo_dir/$keyfile"
69     if with_legacy; then
70       expect_msg 'error reading' tinc foo fsck
71     else
72       must_fail_with_msg 'error reading' tinc foo fsck
73     fi
74   fi
75
76   if ! is_windows; then
77     fsck_test "Must warn about unsafe permissions on $keyfile"
78     chmod 666 "$foo_dir/$keyfile"
79     expect_msg 'unsafe file permissions' tinc foo fsck
80   fi
81
82   if with_legacy; then
83     fsck_test "Must pass on missing $keyfile when the other key is present"
84     rm -f "$foo_dir/$keyfile"
85     tinc foo fsck
86   fi
87 }
88
89 test_private_key_var() {
90   var=$1
91   keyfile=$2
92
93   fsck_test "Must find private key at $var"
94   mv "$foo_dir/$keyfile" "$foo_dir/renamed_private_key"
95   echo "$var = $(normalize_path "$foo_dir/renamed_private_key")" >>"$foo_conf"
96   fail_on_msg 'key was found but no private key' tinc foo fsck
97 }
98
99 test_ec_public_key_file_var() {
100   conf=$1
101   fsck_test "EC public key in Ed25519PublicKeyFile in $conf must work"
102   cat >"$foo_dir/ec_pubkey" <<EOF
103 -----BEGIN ED25519 PUBLIC KEY-----
104 $(awk '/^Ed25519PublicKey/ { printf $NF }' "$foo_host")
105 -----END ED25519 PUBLIC KEY-----
106 EOF
107   sed_cmd '/Ed25519PublicKey/d' "$foo_host"
108   echo "Ed25519PublicKeyFile = $(normalize_path "$foo_dir/ec_pubkey")" >>"$foo_dir/$conf"
109   fail_on_msg 'no (usable) public Ed25519' tinc foo fsck
110 }
111
112 test_rsa_public_key_file_var() {
113   conf=$1
114   fsck_test "RSA public key in PublicKeyFile in $conf must work"
115   extract_pem_key_from_config "$foo_host" >"$foo_dir/rsa_pubkey"
116   rm_pem_key_from_config "$foo_host"
117   echo "PublicKeyFile = $(normalize_path "$foo_dir/rsa_pubkey")" >>"$foo_dir/$conf"
118   fail_on_msg 'error reading RSA public key' tinc foo fsck
119 }
120
121 fsck_test 'Newly created configuration should pass'
122 tinc foo fsck
123
124 fsck_test 'Must fail on missing tinc.conf'
125 rm -f "$foo_conf"
126 must_fail_with_msg 'no tinc configuration found' tinc foo fsck
127
128 if run_access_checks; then
129   fsck_test 'Must fail on inaccessible tinc.conf'
130   chmod 000 "$foo_dir"
131   must_fail_with_msg 'not running tinc as root' tinc foo fsck
132 fi
133
134 if ! is_windows; then
135   fsck_test 'Non-executable tinc-up MUST be fixed by tinc --force'
136   chmod a-x "$foo_tinc_up"
137   expect_msg 'cannot read and execute' tinc foo --force fsck
138   test -x "$foo_tinc_up"
139
140   fsck_test 'Non-executable tinc-up MUST NOT be fixed by tinc without --force'
141   chmod a-x "$foo_tinc_up"
142   expect_msg 'cannot read and execute' tinc foo fsck
143   must_fail test -x "$foo_tinc_up"
144 fi
145
146 fsck_test 'Unknown -up script warning'
147 touch "$foo_dir/fake-up"
148 expect_msg 'unknown script' tinc foo fsck
149
150 fsck_test 'Unknown -down script warning'
151 touch "$foo_dir/fake-down"
152 expect_msg 'unknown script' tinc foo fsck
153
154 if ! is_windows; then
155   fsck_test 'Non-executable foo-up MUST be fixed by tinc --force'
156   touch "$foo_host_up"
157   chmod a-x "$foo_host_up"
158   expect_msg 'cannot read and execute' tinc foo --force fsck
159   test -x "$foo_tinc_up"
160
161   fsck_test 'Non-executable bar-up MUST NOT be fixed by tinc'
162   touch "$foo_dir/hosts/bar-up"
163   chmod a-x "$foo_dir/hosts/bar-up"
164   expect_msg 'cannot read and execute' tinc foo fsck
165   must_fail test -x "$foo_dir/bar-up"
166 fi
167
168 if run_access_checks; then
169   fsck_test 'Inaccessible hosts/foo must fail'
170   chmod 000 "$foo_host"
171   must_fail_with_msg 'cannot open config file' tinc foo fsck
172 fi
173
174 fsck_test 'Must fail when all private keys are missing'
175 rm -f "$foo_ec_priv" "$foo_rsa_priv"
176 if with_legacy; then
177   must_fail_with_msg 'neither RSA or Ed25519 private key' tinc foo fsck
178 else
179   must_fail_with_msg 'no Ed25519 private key' tinc foo fsck
180 fi
181
182 if with_legacy; then
183   test_private_keys rsa_key.priv
184
185   if ! is_windows; then
186     fsck_test 'Must warn about unsafe permissions on tinc.conf with PrivateKey'
187     rm -f "$foo_rsa_priv"
188     echo "PrivateKey = $rsa_d" >>"$foo_conf"
189     echo "PublicKey = $rsa_n" >>"$foo_host"
190     chmod 666 "$foo_conf"
191     expect_msg 'unsafe file permissions' tinc foo fsck
192   fi
193
194   fsck_test 'Must warn about missing RSA private key if public key is present'
195   rm -f "$foo_rsa_priv"
196   expect_msg 'public RSA key was found but no private key' tinc foo fsck
197
198   fsck_test 'Must warn about missing RSA public key'
199   rm_pem_key_from_config "$foo_host"
200   expect_msg 'no (usable) public RSA' tinc foo fsck
201   must_fail grep -q 'BEGIN RSA PUBLIC KEY' "$foo_host"
202
203   fsck_test 'Must fix missing RSA public key on --force'
204   rm_pem_key_from_config "$foo_host"
205   expect_msg 'wrote RSA public key' tinc foo --force fsck
206   grep -q 'BEGIN RSA PUBLIC KEY' "$foo_host"
207
208   test_private_key_var PrivateKeyFile rsa_key.priv
209
210   test_rsa_public_key_file_var tinc.conf
211   test_rsa_public_key_file_var hosts/foo
212
213   fsck_test 'RSA PublicKey + PrivateKey must work'
214   rm -f "$foo_rsa_priv"
215   rm_pem_key_from_config "$foo_host"
216   echo "PrivateKey = $rsa_d" >>"$foo_conf"
217   echo "PublicKey = $rsa_n" >>"$foo_host"
218   fail_on_msg 'no (usable) public RSA' tinc foo fsck
219
220   fsck_test 'RSA PrivateKey without PublicKey must warn'
221   rm -f "$foo_rsa_priv"
222   rm_pem_key_from_config "$foo_host"
223   echo "PrivateKey = $rsa_d" >>"$foo_conf"
224   expect_msg 'PrivateKey used but no PublicKey found' tinc foo fsck
225
226   fsck_test 'Must warn about missing EC private key if public key is present'
227   rm -f "$foo_ec_priv"
228   expect_msg 'public Ed25519 key was found but no private key' tinc foo fsck
229
230   fsck_test 'Must fix broken RSA public key with --force'
231   sed_cmd 2d "$foo_host"
232   expect_msg 'old key(s) found and disabled' tinc foo --force fsck
233   tinc foo fsck
234
235   fsck_test 'Must fix missing RSA public key with --force'
236   rm_pem_key_from_config "$foo_host"
237   expect_msg 'no (usable) public RSA key found' tinc foo --force fsck
238   tinc foo fsck
239 fi
240
241 fsck_test 'Must fix broken Ed25519 public key with --force'
242 sed_cmd 's/Ed25519PublicKey.*/Ed25519PublicKey = foobar/' "$foo_host"
243 expect_msg 'no (usable) public Ed25519 key' tinc foo --force fsck
244 tinc foo fsck
245
246 fsck_test 'Must fix missing Ed25519 public key with --force'
247 sed_cmd '/Ed25519PublicKey/d' "$foo_host"
248 expect_msg 'no (usable) public Ed25519 key' tinc foo --force fsck
249 tinc foo fsck
250
251 test_private_keys ed25519_key.priv
252 test_private_key_var Ed25519PrivateKeyFile ed25519_key.priv
253
254 test_ec_public_key_file_var tinc.conf
255 test_ec_public_key_file_var hosts/foo
256
257 fsck_test 'Must warn about missing EC public key and NOT fix without --force'
258 sed_cmd '/Ed25519PublicKey/d' "$foo_host"
259 expect_msg 'no (usable) public Ed25519' tinc foo fsck
260 must_fail grep -q 'ED25519 PUBLIC KEY' "$foo_host"
261
262 fsck_test 'Must fix missing EC public key on --force'
263 sed_cmd '/Ed25519PublicKey/d' "$foo_host"
264 expect_msg 'wrote Ed25519 public key' tinc foo --force fsck
265 grep -q 'ED25519 PUBLIC KEY' "$foo_host"
266
267 fsck_test 'Must warn about obsolete variables'
268 echo 'GraphDumpFile = /dev/null' >>"$foo_host"
269 expect_msg 'obsolete variable GraphDumpFile' tinc foo fsck
270
271 fsck_test 'Must warn about missing values'
272 echo 'Weight = ' >>"$foo_host"
273 must_fail_with_msg 'no value for variable `Weight' tinc foo fsck
274
275 fsck_test 'Must warn about duplicate variables'
276 echo 'Weight = 0' >>"$foo_host"
277 echo 'Weight = 1' >>"$foo_host"
278 expect_msg 'multiple instances of variable Weight' tinc foo fsck
279
280 fsck_test 'Must warn about server variables in host config'
281 echo 'Interface = fake0' >>"$foo_host"
282 expect_msg 'server variable Interface found' tinc foo fsck
283
284 fsck_test 'Must warn about host variables in server config'
285 echo 'Port = 1337' >>"$foo_conf"
286 expect_msg 'host variable Port found' tinc foo fsck
287
288 fsck_test 'Must warn about missing Name'
289 sed_cmd '/^Name =/d' "$foo_conf"
290 must_fail_with_msg 'without a valid Name' tinc foo fsck