geom_gate userland utility improvements
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

477 lines
10 KiB

  1. # $FreeBSD$
  2. PIDFILE=ggatessh.pid
  3. TESTIMG="test.img"
  4. TEMPFILE="random.data"
  5. SFTPSERVER="/usr/libexec/sftp-server"
  6. PORT=2222
  7. atf_test_case ggatessh cleanup
  8. ggatessh_head()
  9. {
  10. atf_set "descr" "ggatessh can proxy to sftp"
  11. atf_set "require.progs" "ggatessh"
  12. atf_set "require.user" "root"
  13. atf_set "timeout" 10
  14. }
  15. ggatessh_body()
  16. {
  17. load_ggate
  18. us=$(alloc_ggate_dev)
  19. n1mchunks=3
  20. secsize=4096
  21. atf_check -e ignore -o ignore \
  22. dd if=/dev/random of="$TEMPFILE" bs=1m count=$n1mchunks conv=notrunc
  23. startup_sshd
  24. truncate -s ${n1mchunks}m "$TESTIMG"
  25. # sshd authenticates and switches to USER
  26. chown "$USER" "$TESTIMG"
  27. echo 'WARNING: ggatessh error messages goes to syslog' \
  28. '(aka /var/log/messages)'
  29. atf_check \
  30. ggatessh create -i "$(pwd)/id_rsa" -p "$PORT" -F "$PIDFILE" \
  31. -u $us -l "$USER" 127.0.0.1 "$(pwd)/$TESTIMG"
  32. ggate_dev=/dev/ggate${us}
  33. wait_for_ggate_device ${ggate_dev}
  34. # make sure it has correct size and sector size
  35. read _dev _secsize _size _nsecs _stripesize _stripeoff <<EOF
  36. $(diskinfo /dev/ggate$us)
  37. EOF
  38. atf_check_equal "$_secsize" $secsize
  39. atf_check_equal "$_size" $(($n1mchunks * 1024 * 1024))
  40. atf_check_equal "$_nsecs" $(($n1mchunks * 1024 * 1024 / $secsize))
  41. # Test writing
  42. atf_check -e ignore -o ignore \
  43. dd if="$TEMPFILE" of=${ggate_dev} bs=1m count=$n1mchunks \
  44. conv=notrunc
  45. # Test reading
  46. atf_check -e ignore -o ignore \
  47. dd of="$TEMPFILE"2 if=${ggate_dev} bs=1m count=$n1mchunks \
  48. conv=notrunc
  49. # Verify that we read what we wrote
  50. atf_check cmp "$TEMPFILE" "$TEMPFILE"2
  51. # Verify that the image matches
  52. atf_check cmp "$TEMPFILE" "$TESTIMG"
  53. rm "$TEMPFILE" "$TEMPFILE"2
  54. }
  55. ggatessh_cleanup()
  56. {
  57. common_cleanup
  58. }
  59. atf_test_case ggatessh_resize cleanup
  60. ggatessh_resize_head()
  61. {
  62. atf_set "descr" "ggatessh will resize the devices"
  63. atf_set "require.progs" "ggatessh"
  64. atf_set "require.user" "root"
  65. atf_set "timeout" 20
  66. }
  67. ggatessh_resize_body()
  68. {
  69. n1mchunks=4
  70. secsize=4096
  71. us=$(alloc_ggate_dev)
  72. startup_sshd
  73. truncate -s ${n1mchunks}m "$TESTIMG"
  74. # sshd authenticates and switches to USER
  75. chown "$USER" "$TESTIMG"
  76. echo 'WARNING: ggatessh error messages goes to syslog' \
  77. '(aka /var/log/messages)'
  78. atf_check \
  79. ggatessh create -i "$(pwd)/id_rsa" -p "$PORT" -F "$PIDFILE" \
  80. -u $us -l "$USER" 127.0.0.1 "$(pwd)/$TESTIMG"
  81. ggate_dev=/dev/ggate${us}
  82. wait_for_ggate_device ${ggate_dev}
  83. # make sure it has correct size and sector size
  84. read _dev _secsize _size _nsecs _stripesize _stripeoff <<EOF
  85. $(diskinfo /dev/ggate$us)
  86. EOF
  87. atf_check_equal "$_secsize" $secsize
  88. atf_check_equal "$_size" $(($n1mchunks * 1024 * 1024))
  89. atf_check_equal "$_nsecs" $(($n1mchunks * 1024 * 1024 / $secsize))
  90. # kill off old ggate
  91. pkill -F "$PIDFILE"
  92. # Test resizing
  93. n1mchunks=6
  94. truncate -s ${n1mchunks}m "$TESTIMG"
  95. ps auxwww | grep ggatessh
  96. cat "$PIDFILE"
  97. sleep 1
  98. # restart ggate
  99. atf_check \
  100. ggatessh rescue -v -i "$(pwd)/id_rsa" -p "$PORT" -F "$PIDFILE" \
  101. -u $us -l "$USER" 127.0.0.1 "$(pwd)/$TESTIMG" &
  102. sleep 1
  103. # make sure it has correct size and sector size
  104. read _dev _secsize _size _nsecs _stripesize _stripeoff <<EOF
  105. $(diskinfo /dev/ggate$us)
  106. EOF
  107. atf_check_equal "$_secsize" $secsize
  108. atf_check_equal "$_size" $(($n1mchunks * 1024 * 1024))
  109. atf_check_equal "$_nsecs" $(($n1mchunks * 1024 * 1024 / $secsize))
  110. dd if=/dev/ggate$us of=/dev/null bs=1m
  111. }
  112. ggatessh_resize_cleanup()
  113. {
  114. common_cleanup
  115. }
  116. atf_test_case ggatessh_multises cleanup
  117. ggatessh_multises_head()
  118. {
  119. atf_set "descr" "ggatessh will handle multiple sessions w/o looping"
  120. atf_set "require.progs" "ggatessh"
  121. atf_set "require.user" "root"
  122. atf_set "timeout" 20
  123. }
  124. ggatessh_multises_body()
  125. {
  126. n1mchunks=1
  127. secsize=4096
  128. us=$(alloc_ggate_dev)
  129. startup_sshd
  130. set -x
  131. truncate -s ${n1mchunks}m "$TESTIMG"
  132. # sshd authenticates and switches to USER
  133. chown "$USER" "$TESTIMG"
  134. echo 'WARNING: ggatessh error messages goes to syslog' \
  135. '(aka /var/log/messages)'
  136. ggatessh create -i "$(pwd)/id_rsa" -p "$PORT" -F "$PIDFILE" \
  137. -u $us -l "$USER" 127.0.0.1 "$(pwd)/$TESTIMG"
  138. ggate_dev=/dev/ggate${us}
  139. wait_for_ggate_device ${ggate_dev}
  140. # kill off ggate so we can schedule I/O
  141. pkill -F "$PIDFILE"
  142. # schedule some IO, to create a second session
  143. dd if=/dev/ggate$us of=/dev/null bs=1m &
  144. dd1pid="$!"
  145. dd if=/dev/ggate$us of=/dev/null bs=1m &
  146. dd2pid="$!"
  147. # restart ggate
  148. ggatessh rescue -v -i "$(pwd)/id_rsa" -p "$PORT" \
  149. -u $us -l "$USER" 127.0.0.1 "$(pwd)/$TESTIMG" > ggatessh.log &
  150. ggatepid="$!"
  151. # This test will timeout if ggatessh exits before dd does, dump
  152. # the log to find out why
  153. # wait for IO to complete
  154. wait "$dd1pid"
  155. echo "dd exit:" $?
  156. wait "$dd2pid"
  157. echo "dd exit:" $?
  158. # kill off ggate
  159. kill "$ggatepid"
  160. wait "$ggatepid"
  161. #echo 'log:'
  162. #cat ggatessh.log
  163. #echo 'end of log'
  164. # make sure the second session was successfully created
  165. cnt=$(grep "new session created" ggatessh.log | wc -l)
  166. if [ "$cnt" -ne 1 ]; then
  167. echo "not the correct number of new sessions: $cnt"
  168. return 1
  169. fi
  170. }
  171. ggatessh_multises_cleanup()
  172. {
  173. common_cleanup
  174. }
  175. atf_test_case ggatessh_rowotest cleanup
  176. ggatessh_rowotest_head()
  177. {
  178. atf_set "descr" "ggatessh properly handles the -o flag"
  179. atf_set "require.progs" "ggatessh"
  180. atf_set "require.user" "root"
  181. atf_set "timeout" 10
  182. }
  183. ggatessh_rowotest_body()
  184. {
  185. n1mchunks=4
  186. secsize=4096
  187. us=$(alloc_ggate_dev)
  188. startup_sshd
  189. truncate -s ${n1mchunks}m "$TESTIMG"
  190. # sshd authenticates and switches to USER
  191. chmod 444 "$TESTIMG"
  192. echo 'WARNING: ggatessh error messages goes to syslog' \
  193. '(aka /var/log/messages)'
  194. # make sure it fails in rw mode
  195. atf_check -s not-exit:0 \
  196. ggatessh create -i "$(pwd)/id_rsa" -p "$PORT" -F "$PIDFILE" \
  197. -u $us -l "$USER" 127.0.0.1 "$(pwd)/$TESTIMG"
  198. # open it in read-only mode
  199. atf_check \
  200. ggatessh create -o ro -i "$(pwd)/id_rsa" -p "$PORT" -F "$PIDFILE" \
  201. -u $us -l "$USER" 127.0.0.1 "$(pwd)/$TESTIMG"
  202. ggate_dev=/dev/ggate${us}
  203. wait_for_ggate_device ${ggate_dev}
  204. # make sure it has correct size and sector size
  205. read _dev _secsize _size _nsecs _stripesize _stripeoff <<EOF
  206. $(diskinfo /dev/ggate$us)
  207. EOF
  208. atf_check_equal "$_secsize" $secsize
  209. atf_check_equal "$_size" $(($n1mchunks * 1024 * 1024))
  210. atf_check_equal "$_nsecs" $(($n1mchunks * 1024 * 1024 / $secsize))
  211. # that we can read a read-only ggate device
  212. atf_check -e ignore \
  213. dd if=${ggate_dev} of=/dev/null bs=1m count=$n1mchunks
  214. # that we can not write a read-only ggate device
  215. atf_check -e ignore -s not-exit:0 \
  216. dd of=${ggate_dev} if=/dev/zero bs=1m count=1
  217. # kill off old ggate
  218. pkill -F "$PIDFILE"
  219. ggatessh destroy -f -u $us >/dev/null
  220. # test write-only
  221. chmod 222 "$TESTIMG"
  222. # make sure it fails in rw mode
  223. atf_check -s not-exit:0 \
  224. ggatessh create -i "$(pwd)/id_rsa" -p "$PORT" -F "$PIDFILE" \
  225. -u $us -l "$USER" 127.0.0.1 "$(pwd)/$TESTIMG"
  226. # open it in write-only mode
  227. atf_check \
  228. ggatessh create -o wo -i "$(pwd)/id_rsa" -p "$PORT" \
  229. -F "$PIDFILE" -u $us -l "$USER" 127.0.0.1 "$(pwd)/$TESTIMG"
  230. ggate_dev=/dev/ggate${us}
  231. wait_for_ggate_device ${ggate_dev}
  232. # Note: diskinfo opens w/ read, can't verify device info
  233. # that we can not read a write-only ggate device
  234. atf_check -e ignore -s not-exit:0 \
  235. dd if=${ggate_dev} of=/dev/null bs=1m count=$n1mchunks
  236. # that we can write a write-only ggate device
  237. atf_check -e ignore \
  238. dd of=${ggate_dev} if=/dev/zero bs=1m count=1
  239. }
  240. ggatessh_rowotest_cleanup()
  241. {
  242. common_cleanup
  243. }
  244. atf_init_test_cases()
  245. {
  246. atf_add_test_case ggatessh
  247. atf_add_test_case ggatessh_resize
  248. atf_add_test_case ggatessh_multises
  249. atf_add_test_case ggatessh_rowotest
  250. }
  251. alloc_ggate_dev()
  252. {
  253. local us
  254. us=0
  255. while [ -c /dev/ggate${us} ]; do
  256. : $(( us += 1 ))
  257. done
  258. echo ${us} > ggate.devs
  259. echo ${us}
  260. }
  261. alloc_md()
  262. {
  263. local md
  264. md=$(mdconfig -a -t malloc -s 1M) || \
  265. atf_fail "failed to allocate md device"
  266. echo ${md} >> md.devs
  267. echo ${md}
  268. }
  269. # slightly modified from:
  270. # https://serverfault.com/questions/344295/is-it-possible-to-run-sshd-as-a-normal-user
  271. startup_sshd()
  272. {
  273. # ===============================================================
  274. # Note: using shorter keys to speed up tests, these are insecure.
  275. # ===============================================================
  276. # Host keys
  277. ssh-keygen -f ssh_host_rsa_key -b 1024 -N '' -t rsa > /dev/null
  278. # user key
  279. ssh-keygen -f id_rsa -b 1024 -N '' -t rsa > /dev/null
  280. (echo -n 'command="/usr/libexec/sftp-server" '; cat id_rsa.pub) > authorized_keys
  281. cat > sshd_config <<EOF
  282. ListenAddress 127.0.0.1:$PORT
  283. HostKey /home/freebsd/custom_ssh/ssh_host_rsa_key
  284. AuthorizedKeysFile $(pwd)/authorized_keys
  285. ChallengeResponseAuthentication no
  286. PasswordAuthentication no
  287. # to allow writable tmp w/ sticky bit
  288. StrictModes no
  289. UsePAM no
  290. Subsystem sftp ${SFTPSERVER}
  291. PidFile $(pwd)/sshd.pid
  292. EOF
  293. if ! :; then
  294. /usr/sbin/sshd -dD -f $(pwd)/sshd_config &
  295. sleep .2
  296. else
  297. /usr/sbin/sshd -f $(pwd)/sshd_config
  298. while ! [ -f sshd.pid ]; do
  299. sleep .2
  300. done
  301. fi
  302. }
  303. checksum()
  304. {
  305. local src work
  306. src=$1
  307. work=$2
  308. src_checksum=$(md5 -q $src)
  309. work_checksum=$(md5 -q $work)
  310. if [ "$work_checksum" != "$src_checksum" ]; then
  311. atf_fail "work md5 checksum didn't match"
  312. fi
  313. ggate_checksum=$(md5 -q /dev/ggate${us})
  314. if [ "$ggate_checksum" != "$src_checksum" ]; then
  315. atf_fail "ggate md5 checksum didn't match"
  316. fi
  317. }
  318. common_cleanup()
  319. {
  320. if [ -f "ggate.devs" ]; then
  321. while read test_ggate; do
  322. ggatessh destroy -f -u $test_ggate >/dev/null
  323. done < ggate.devs
  324. rm ggate.devs
  325. fi
  326. if [ -f "sshd.pid" ]; then
  327. pkill -F sshd.pid
  328. # clean up after startup_sshd
  329. rm ssh_host_rsa_key
  330. rm id_rsa id_rsa.pub
  331. rm authorized_keys
  332. fi
  333. if [ -f "$PIDFILE" ]; then
  334. pkill -F "$PIDFILE"
  335. rm $PIDFILE
  336. fi
  337. if [ -f "PLAINFILES" ]; then
  338. while read f; do
  339. rm -f ${f}
  340. done < ${PLAINFILES}
  341. rm ${PLAINFILES}
  342. fi
  343. if [ -f "md.devs" ]; then
  344. while read test_md; do
  345. mdconfig -d -u $test_md 2>/dev/null
  346. done < md.devs
  347. rm md.devs
  348. fi
  349. true
  350. }
  351. load_ggate()
  352. {
  353. local class=gate
  354. # If the geom class isn't already loaded, try loading it.
  355. if ! kldstat -q -m g_${class}; then
  356. if ! geom ${class} load; then
  357. atf_skip "could not load module for geom class=${class}"
  358. fi
  359. fi
  360. }
  361. # Bug 204616: ggatel(8) creates /dev/ggate* asynchronously if `ggatel create`
  362. # isn't called with `-v`.
  363. wait_for_ggate_device()
  364. {
  365. ggate_device=$1
  366. while [ ! -c $ggate_device ]; do
  367. sleep 0.5
  368. done
  369. }