test_keygen.sh (15650B)
1 #!/bin/sh 2 3 # Note: some of this code is lifted from zero_length_keys.sh, and could be 4 # unified. 5 6 umask 077 7 set -e 8 9 # emulate realpath(), in case coreutils or equivalent is not installed. 10 abspath() { 11 f="$*" 12 if [ -d "$f" ]; then 13 dir="$f" 14 base="" 15 else 16 dir="$(dirname "$f")" 17 base="/$(basename "$f")" 18 fi 19 dir="$(cd "$dir" && pwd)" 20 echo "$dir$base" 21 } 22 23 if [ $# -eq 0 ] || [ ! -f "${1}" ] || [ ! -x "${1}" ]; then 24 if [ "$TESTING_TOR_BINARY" = "" ] ; then 25 echo "Usage: ${0} PATH_TO_TOR [case-number]" 26 exit 1 27 fi 28 fi 29 30 UNAME_OS=$(uname -s | cut -d_ -f1) 31 if test "$UNAME_OS" = 'CYGWIN' || \ 32 test "$UNAME_OS" = 'MSYS' || \ 33 test "$UNAME_OS" = 'MINGW'; then 34 echo "This test is unreliable on Windows. See trac #26076. Skipping." >&2 35 exit 77 36 fi 37 38 # find the tor binary 39 if [ $# -ge 1 ]; then 40 TOR_BINARY="${1}" 41 shift 42 else 43 TOR_BINARY="${TESTING_TOR_BINARY:-./src/app/tor}" 44 fi 45 46 TOR_BINARY="$(abspath "$TOR_BINARY")" 47 48 echo "TOR BINARY IS ${TOR_BINARY}" 49 50 if "$TOR_BINARY" --list-modules | grep -q "relay: no"; then 51 echo "This test requires the relay module. Skipping." >&2 52 exit 77 53 fi 54 55 if [ $# -ge 1 ]; then 56 dflt=0 57 else 58 dflt=1 59 fi 60 61 CASE2A=$dflt 62 CASE2B=$dflt 63 CASE3A=$dflt 64 CASE3B=$dflt 65 CASE3C=$dflt 66 CASE4=$dflt 67 CASE5=$dflt 68 CASE6=$dflt 69 CASE7=$dflt 70 CASE8=$dflt 71 CASE9=$dflt 72 CASE10=$dflt 73 CASE11A=$dflt 74 CASE11B=$dflt 75 CASE11C=$dflt 76 CASE11D=$dflt 77 CASE11E=$dflt 78 CASE11F=$dflt 79 80 if [ $# -ge 1 ]; then 81 eval "CASE${1}"=1 82 fi 83 84 85 dump() { xxd -p "$1" | tr -d '\n '; } 86 die() { echo "$1" >&2 ; exit 5; } 87 check_dir() { [ -d "$1" ] || die "$1 did not exist"; } 88 check_file() { [ -e "$1" ] || die "$1 did not exist"; } 89 check_no_file() { if [ -e "$1" ]; then die "$1 was not supposed to exist"; fi } 90 check_files_eq() { cmp "$1" "$2" || die "$1 and $2 did not match: $(dump "$1") vs $(dump "$2")"; } 91 check_keys_eq() { check_files_eq "${SRC}/keys/${1}" "${ME}/keys/${1}"; } 92 93 DATA_DIR=$(mktemp -d -t tor_keygen_tests.XXXXXX) 94 if [ -z "$DATA_DIR" ]; then 95 echo "Failure: mktemp invocation returned empty string" >&2 96 exit 3 97 fi 98 if [ ! -d "$DATA_DIR" ]; then 99 echo "Failure: mktemp invocation result doesn't point to directory" >&2 100 exit 3 101 fi 102 trap 'rm -rf "$DATA_DIR"' 0 103 104 # Use an absolute path for this or Tor will complain 105 DATA_DIR=$(cd "${DATA_DIR}" && pwd) 106 107 touch "${DATA_DIR}/empty_torrc" 108 touch "${DATA_DIR}/empty_defaults_torrc" 109 110 QUIETLY="--hush" 111 SILENTLY="--quiet" 112 TOR="${TOR_BINARY} ${QUIETLY} --DisableNetwork 1 --ShutdownWaitLength 0 --ORPort 12345 --ExitRelay 0 -f ${DATA_DIR}/empty_torrc --defaults-torrc ${DATA_DIR}/empty_defaults_torrc" 113 114 ##### SETUP 115 # 116 # Here we create three sets of keys: one using "tor", one using "tor 117 # --keygen", and one using "tor --keygen" and encryption. We'll be 118 # copying them into different keys directories in order to simulate 119 # different kinds of configuration problems/issues. 120 121 # Step 1: Start Tor with --list-fingerprint --quiet. Make sure everything is there. 122 mkdir "${DATA_DIR}/orig" 123 ${TOR} --DataDirectory "${DATA_DIR}/orig" ${SILENTLY} --list-fingerprint > /dev/null 124 125 check_dir "${DATA_DIR}/orig/keys" 126 check_file "${DATA_DIR}/orig/keys/ed25519_master_id_public_key" 127 check_file "${DATA_DIR}/orig/keys/ed25519_master_id_secret_key" 128 check_file "${DATA_DIR}/orig/keys/ed25519_signing_cert" 129 check_file "${DATA_DIR}/orig/keys/ed25519_signing_secret_key" 130 131 # Step 2: Start Tor with --keygen. Make sure everything is there. 132 mkdir "${DATA_DIR}/keygen" 133 ${TOR} --DataDirectory "${DATA_DIR}/keygen" --keygen --no-passphrase 2>"${DATA_DIR}/keygen/stderr" 134 grep "Not encrypting the secret key" "${DATA_DIR}/keygen/stderr" >/dev/null || die "Tor didn't declare that there would be no encryption" 135 136 check_dir "${DATA_DIR}/keygen/keys" 137 check_file "${DATA_DIR}/keygen/keys/ed25519_master_id_public_key" 138 check_file "${DATA_DIR}/keygen/keys/ed25519_master_id_secret_key" 139 check_file "${DATA_DIR}/keygen/keys/ed25519_signing_cert" 140 check_file "${DATA_DIR}/keygen/keys/ed25519_signing_secret_key" 141 142 # Step 3: Start Tor with --keygen and a passphrase. 143 # Make sure everything is there. 144 mkdir "${DATA_DIR}/encrypted" 145 echo "passphrase" | ${TOR} --DataDirectory "${DATA_DIR}/encrypted" --keygen --passphrase-fd 0 146 147 check_dir "${DATA_DIR}/encrypted/keys" 148 check_file "${DATA_DIR}/encrypted/keys/ed25519_master_id_public_key" 149 check_file "${DATA_DIR}/encrypted/keys/ed25519_master_id_secret_key_encrypted" 150 check_file "${DATA_DIR}/encrypted/keys/ed25519_signing_cert" 151 check_file "${DATA_DIR}/encrypted/keys/ed25519_signing_secret_key" 152 153 154 echo "=== Starting keygen tests." 155 156 # 157 # The "case X" numbers below come from s7r's email on 158 # https://lists.torproject.org/pipermail/tor-dev/2015-August/009204.html 159 160 161 # Case 2a: Missing secret key, public key exists, start tor. 162 163 if [ "$CASE2A" = 1 ]; then 164 165 ME="${DATA_DIR}/case2a" 166 SRC="${DATA_DIR}/orig" 167 mkdir -p "${ME}/keys" 168 cp "${SRC}/keys/ed25519_master_id_public_key" "${ME}/keys/" 169 if ${TOR} --DataDirectory "${ME}" --list-fingerprint > "${ME}/stdout"; then 170 die "Somehow succeeded when missing secret key, certs: $(cat "${ME}/stdout")" 171 fi 172 check_files_eq "${SRC}/keys/ed25519_master_id_public_key" "${ME}/keys/ed25519_master_id_public_key" 173 174 grep "We needed to load a secret key.*but couldn't find it" "${ME}/stdout" >/dev/null || die "Tor didn't declare that it was missing a secret key" 175 176 echo "==== Case 2A ok" 177 fi 178 179 # Case 2b: Encrypted secret key, public key exists, start tor. 180 181 if [ "$CASE2B" = 1 ]; then 182 183 ME="${DATA_DIR}/case2b" 184 SRC="${DATA_DIR}/encrypted" 185 186 mkdir -p "${ME}/keys" 187 cp "${SRC}/keys/ed25519_master_id_public_key" "${ME}/keys/" 188 cp "${SRC}/keys/ed25519_master_id_secret_key_encrypted" "${ME}/keys/" 189 ${TOR} --DataDirectory "${ME}" --list-fingerprint > "${ME}/stdout" && dir "Somehow succeeded with encrypted secret key, missing certs" 190 191 check_files_eq "${SRC}/keys/ed25519_master_id_public_key" "${ME}/keys/ed25519_master_id_public_key" 192 check_files_eq "${SRC}/keys/ed25519_master_id_secret_key_encrypted" "${ME}/keys/ed25519_master_id_secret_key_encrypted" 193 194 grep "We needed to load a secret key.*but it was encrypted.*--keygen" "${ME}/stdout" >/dev/null || die "Tor didn't declare that it was missing a secret key and suggest --keygen." 195 196 echo "==== Case 2B ok" 197 198 fi 199 200 # Case 3a: Start Tor with only master key. 201 202 if [ "$CASE3A" = 1 ]; then 203 204 ME="${DATA_DIR}/case3a" 205 SRC="${DATA_DIR}/orig" 206 207 mkdir -p "${ME}/keys" 208 cp "${SRC}/keys/ed25519_master_id_"* "${ME}/keys/" 209 ${TOR} --DataDirectory "${ME}" ${SILENTLY} --list-fingerprint >/dev/null || die "Tor failed when starting with only master key" 210 check_files_eq "${SRC}/keys/ed25519_master_id_public_key" "${ME}/keys/ed25519_master_id_public_key" 211 check_files_eq "${SRC}/keys/ed25519_master_id_secret_key" "${ME}/keys/ed25519_master_id_secret_key" 212 check_file "${ME}/keys/ed25519_signing_cert" 213 check_file "${ME}/keys/ed25519_signing_secret_key" 214 215 echo "==== Case 3A ok" 216 217 fi 218 219 # Case 3b: Call keygen with only unencrypted master key. 220 221 if [ "$CASE3B" = 1 ]; then 222 223 ME="${DATA_DIR}/case3b" 224 SRC="${DATA_DIR}/orig" 225 226 mkdir -p "${ME}/keys" 227 cp "${SRC}/keys/ed25519_master_id_"* "${ME}/keys/" 228 ${TOR} --DataDirectory "${ME}" --keygen || die "Keygen failed with only master key" 229 check_files_eq "${SRC}/keys/ed25519_master_id_public_key" "${ME}/keys/ed25519_master_id_public_key" 230 check_files_eq "${SRC}/keys/ed25519_master_id_secret_key" "${ME}/keys/ed25519_master_id_secret_key" 231 check_file "${ME}/keys/ed25519_signing_cert" 232 check_file "${ME}/keys/ed25519_signing_secret_key" 233 234 echo "==== Case 3B ok" 235 236 fi 237 238 # Case 3c: Call keygen with only encrypted master key. 239 240 if [ "$CASE3C" = 1 ]; then 241 242 ME="${DATA_DIR}/case3c" 243 SRC="${DATA_DIR}/encrypted" 244 245 mkdir -p "${ME}/keys" 246 cp "${SRC}/keys/ed25519_master_id_"* "${ME}/keys/" 247 echo "passphrase" | ${TOR} --DataDirectory "${ME}" --keygen --passphrase-fd 0 || die "Keygen failed with only encrypted master key" 248 check_files_eq "${SRC}/keys/ed25519_master_id_public_key" "${ME}/keys/ed25519_master_id_public_key" 249 check_files_eq "${SRC}/keys/ed25519_master_id_secret_key_encrypted" "${ME}/keys/ed25519_master_id_secret_key_encrypted" 250 check_file "${ME}/keys/ed25519_signing_cert" 251 check_file "${ME}/keys/ed25519_signing_secret_key" 252 253 echo "==== Case 3C ok" 254 255 fi 256 257 # Case 4: Make a new data directory with only an unencrypted secret key. 258 # Then start tor. The rest should become correct. 259 260 if [ "$CASE4" = 1 ]; then 261 262 ME="${DATA_DIR}/case4" 263 SRC="${DATA_DIR}/orig" 264 265 mkdir -p "${ME}/keys" 266 cp "${SRC}/keys/ed25519_master_id_secret_key" "${ME}/keys/" 267 ${TOR} --DataDirectory "${ME}" ${SILENTLY} --list-fingerprint > "${ME}/fp1" || die "Tor wouldn't start with only unencrypted secret key" 268 check_file "${ME}/keys/ed25519_master_id_public_key" 269 check_file "${ME}/keys/ed25519_signing_cert" 270 check_file "${ME}/keys/ed25519_signing_secret_key" 271 ${TOR} --DataDirectory "${ME}" ${SILENTLY} --list-fingerprint > "${ME}/fp2" || die "Tor wouldn't start again after starting once with only unencrypted secret key." 272 273 check_files_eq "${ME}/fp1" "${ME}/fp2" 274 275 echo "==== Case 4 ok" 276 277 fi 278 279 # Case 5: Make a new data directory with only an encrypted secret key. 280 281 if [ "$CASE5" = 1 ]; then 282 283 ME="${DATA_DIR}/case5" 284 SRC="${DATA_DIR}/encrypted" 285 286 mkdir -p "${ME}/keys" 287 cp "${SRC}/keys/ed25519_master_id_secret_key_encrypted" "${ME}/keys/" 288 ${TOR} --DataDirectory "${ME}" --list-fingerprint >"${ME}/stdout" && die "Tor started with only encrypted secret key!" 289 check_no_file "${ME}/keys/ed25519_master_id_public_key" 290 check_no_file "${ME}/keys/ed25519_master_id_public_key" 291 292 grep "but not public key file" "${ME}/stdout" >/dev/null || die "Tor didn't declare it couldn't find a public key." 293 294 echo "==== Case 5 ok" 295 296 fi 297 298 # Case 6: Make a new data directory with encrypted secret key and public key 299 300 if [ "$CASE6" = 1 ]; then 301 302 ME="${DATA_DIR}/case6" 303 SRC="${DATA_DIR}/encrypted" 304 305 mkdir -p "${ME}/keys" 306 cp "${SRC}/keys/ed25519_master_id_secret_key_encrypted" "${ME}/keys/" 307 cp "${SRC}/keys/ed25519_master_id_public_key" "${ME}/keys/" 308 if ${TOR} --DataDirectory "${ME}" --list-fingerprint > "${ME}/stdout"; then 309 die "Tor started with encrypted secret key and no certs" 310 fi 311 check_no_file "${ME}/keys/ed25519_signing_cert" 312 check_no_file "${ME}/keys/ed25519_signing_secret_key" 313 314 grep "but it was encrypted" "${ME}/stdout" >/dev/null || die "Tor didn't declare that the secret key was encrypted." 315 316 echo "==== Case 6 ok" 317 318 fi 319 320 # Case 7: Make a new data directory with unencrypted secret key and 321 # certificates; missing master public. 322 323 if [ "$CASE7" = 1 ]; then 324 325 ME="${DATA_DIR}/case7" 326 SRC="${DATA_DIR}/keygen" 327 328 mkdir -p "${ME}/keys" 329 cp "${SRC}/keys/ed25519_master_id_secret_key" "${ME}/keys/" 330 cp "${SRC}/keys/ed25519_signing_cert" "${ME}/keys/" 331 cp "${SRC}/keys/ed25519_signing_secret_key" "${ME}/keys/" 332 333 ${TOR} --DataDirectory "${ME}" ${SILENTLY} --list-fingerprint >/dev/null || die "Failed when starting with missing public key" 334 check_keys_eq ed25519_master_id_secret_key 335 check_keys_eq ed25519_master_id_public_key 336 check_keys_eq ed25519_signing_secret_key 337 check_keys_eq ed25519_signing_cert 338 339 echo "==== Case 7 ok" 340 341 fi 342 343 # Case 8: offline master secret key. 344 345 if [ "$CASE8" = 1 ]; then 346 347 ME="${DATA_DIR}/case8" 348 SRC="${DATA_DIR}/keygen" 349 350 mkdir -p "${ME}/keys" 351 cp "${SRC}/keys/ed25519_master_id_public_key" "${ME}/keys/" 352 cp "${SRC}/keys/ed25519_signing_cert" "${ME}/keys/" 353 cp "${SRC}/keys/ed25519_signing_secret_key" "${ME}/keys/" 354 355 ${TOR} --DataDirectory "${ME}" ${SILENTLY} --list-fingerprint >/dev/null || die "Failed when starting with offline secret key" 356 check_no_file "${ME}/keys/ed25519_master_id_secret_key" 357 check_keys_eq ed25519_master_id_public_key 358 check_keys_eq ed25519_signing_secret_key 359 check_keys_eq ed25519_signing_cert 360 361 echo "==== Case 8 ok" 362 363 fi 364 365 # Case 9: signing cert and secret key provided; could infer master key. 366 367 if [ "$CASE9" = 1 ]; then 368 369 ME="${DATA_DIR}/case9" 370 SRC="${DATA_DIR}/keygen" 371 372 mkdir -p "${ME}/keys" 373 cp "${SRC}/keys/ed25519_signing_cert" "${ME}/keys/" 374 cp "${SRC}/keys/ed25519_signing_secret_key" "${ME}/keys/" 375 376 ${TOR} --DataDirectory "${ME}" ${SILENTLY} --list-fingerprint >/dev/null || die "Failed when starting with only signing material" 377 check_no_file "${ME}/keys/ed25519_master_id_secret_key" 378 check_file "${ME}/keys/ed25519_master_id_public_key" 379 check_keys_eq ed25519_signing_secret_key 380 check_keys_eq ed25519_signing_cert 381 382 echo "==== Case 9 ok" 383 384 fi 385 386 387 # Case 10: master key mismatch. 388 389 if [ "$CASE10" = 1 ]; then 390 391 ME="${DATA_DIR}/case10" 392 SRC="${DATA_DIR}/keygen" 393 OTHER="${DATA_DIR}/orig" 394 395 mkdir -p "${ME}/keys" 396 cp "${SRC}/keys/ed25519_master_id_public_key" "${ME}/keys/" 397 cp "${OTHER}/keys/ed25519_master_id_secret_key" "${ME}/keys/" 398 399 if ${TOR} --DataDirectory "${ME}" --list-fingerprint >"${ME}/stdout"; then 400 die "Successfully started with mismatched keys!?" 401 fi 402 403 grep "public_key does not match.*secret_key" "${ME}/stdout" >/dev/null || die "Tor didn't declare that there was a key mismatch" 404 405 echo "==== Case 10 ok" 406 407 fi 408 409 # Case 11a: -passphrase-fd without --keygen 410 411 if [ "$CASE11A" = 1 ]; then 412 413 ME="${DATA_DIR}/case11a" 414 415 mkdir -p "${ME}/keys" 416 417 if ${TOR} --DataDirectory "${ME}" --passphrase-fd 1 > "${ME}/stdout"; then 418 die "Successfully started with passphrase-fd but no keygen?" 419 fi 420 421 grep "passphrase-fd specified without --keygen" "${ME}/stdout" >/dev/null || die "Tor didn't declare that there was a problem with the arguments." 422 423 echo "==== Case 11A ok" 424 425 fi 426 427 # Case 11b: --no-passphrase without --keygen 428 429 if [ "$CASE11B" = 1 ]; then 430 431 ME="${DATA_DIR}/case11b" 432 433 mkdir -p "${ME}/keys" 434 435 if ${TOR} --DataDirectory "${ME}" --no-passphrase > "${ME}/stdout"; then 436 die "Successfully started with no-passphrase but no keygen?" 437 fi 438 439 grep "no-passphrase specified without --keygen" "${ME}/stdout" >/dev/null || die "Tor didn't declare that there was a problem with the arguments." 440 441 echo "==== Case 11B ok" 442 443 fi 444 445 # Case 11c: --newpass without --keygen 446 447 if [ "$CASE11C" = 1 ]; then 448 449 ME="${DATA_DIR}/case11C" 450 451 mkdir -p "${ME}/keys" 452 453 if ${TOR} --DataDirectory "${ME}" --newpass > "${ME}/stdout"; then 454 die "Successfully started with newpass but no keygen?" 455 fi 456 457 grep "newpass specified without --keygen" "${ME}/stdout" >/dev/null || die "Tor didn't declare that there was a problem with the arguments." 458 459 echo "==== Case 11C ok" 460 461 fi 462 463 ######## --master-key does not work yet, but this will test the error case 464 ######## when it does. 465 # 466 # Case 11d: --master-key without --keygen 467 # 468 if [ "$CASE11D" = 1 ]; then 469 # 470 # ME="${DATA_DIR}/case11d" 471 # 472 # mkdir -p "${ME}/keys" 473 # 474 # ${TOR} --DataDirectory "${ME}" --master-key "${ME}/foobar" > "${ME}/stdout" && die "Successfully started with master-key but no keygen?" || true 475 # 476 # cat "${ME}/stdout" 477 # 478 # grep "master-key without --keygen" "${ME}/stdout" >/dev/null || die "Tor didn't declare that there was a problem with the arguments." 479 480 echo "==== Case 11D skipped" 481 482 fi 483 484 485 # Case 11E: Silly passphrase-fd 486 487 if [ "$CASE11E" = 1 ]; then 488 489 ME="${DATA_DIR}/case11E" 490 491 mkdir -p "${ME}/keys" 492 493 if ${TOR} --DataDirectory "${ME}" --keygen --passphrase-fd ewigeblumenkraft > "${ME}/stdout"; then 494 die "Successfully started with bogus passphrase-fd?" 495 fi 496 497 grep "Invalid --passphrase-fd value" "${ME}/stdout" >/dev/null || die "Tor didn't declare that there was a problem with the arguments." 498 499 echo "==== Case 11E ok" 500 501 fi 502 503 504 # Case 11F: --no-passphrase with --passphrase-fd 505 506 if [ "$CASE11F" = 1 ]; then 507 508 ME="${DATA_DIR}/case11F" 509 510 mkdir -p "${ME}/keys" 511 512 if ${TOR} --DataDirectory "${ME}" --keygen --passphrase-fd 1 --no-passphrase > "${ME}/stdout"; then 513 die "Successfully started with bogus passphrase-fd combination?" 514 fi 515 516 grep "no-passphrase specified with --passphrase-fd" "${ME}/stdout" >/dev/null || die "Tor didn't declare that there was a problem with the arguments." 517 518 echo "==== Case 11F ok" 519 520 fi 521 522 523 # Check cert-only.