args_test.py 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. # Copyright (C) 2010,2013 Internet Systems Consortium.
  2. #
  3. # Permission to use, copy, modify, and distribute this software for any
  4. # purpose with or without fee is hereby granted, provided that the above
  5. # copyright notice and this permission notice appear in all copies.
  6. #
  7. # THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SYSTEMS CONSORTIUM
  8. # DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
  9. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
  10. # INTERNET SYSTEMS CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
  11. # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
  12. # FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
  13. # NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
  14. # WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  15. """
  16. This program tests the b10-init process to make sure that it runs while
  17. dropping permissions. It must be run as a user that can set permission.
  18. """
  19. import unittest
  20. import os
  21. import sys
  22. import subprocess
  23. import select
  24. import time
  25. import pwd
  26. # Set to a valid user name on the system to run setuid() test
  27. #SUID_USER=None
  28. SUID_USER="shane"
  29. BIND10_EXE="../run_bind10.sh"
  30. TIMEOUT=3
  31. class TestInitArgs(unittest.TestCase):
  32. def _waitForString(self, init, s):
  33. found_string = False
  34. start_time = time.time()
  35. while time.time() < start_time + TIMEOUT:
  36. (r,w,x) = select.select((init.stdout,), (), (), TIMEOUT)
  37. if init.stdout in r:
  38. s = init.stdout.readline()
  39. if s == '':
  40. break
  41. if s.startswith(s):
  42. found_string = True
  43. break
  44. return found_string
  45. def testNoArgs(self):
  46. """Run bind10 without any arguments"""
  47. init = subprocess.Popen(args=(BIND10_EXE,),
  48. stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
  49. started_ok = self._waitForString(init, '[bind10] BIND 10 started')
  50. time.sleep(0.1)
  51. init.terminate()
  52. init.wait()
  53. self.assertTrue(started_ok)
  54. def testBadOption(self):
  55. """Run bind10 with a bogus option"""
  56. init = subprocess.Popen(args=(BIND10_EXE, "--badoption"),
  57. stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
  58. failed = self._waitForString(init, 'bind10: error: no such option: --badoption')
  59. time.sleep(0.1)
  60. init.terminate()
  61. self.assertTrue(init.wait() == 2)
  62. self.assertTrue(failed)
  63. def testArgument(self):
  64. """Run bind10 with an argument (this is not allowed)"""
  65. init = subprocess.Popen(args=(BIND10_EXE, "argument"),
  66. stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
  67. failed = self._waitForString(init, 'Usage: bind10 [options]')
  68. time.sleep(0.1)
  69. init.terminate()
  70. self.assertTrue(init.wait() == 1)
  71. self.assertTrue(failed)
  72. def testBadUser(self):
  73. """Run bind10 with a bogus user"""
  74. init = subprocess.Popen(args=(BIND10_EXE, "-u", "bogus_user"),
  75. stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
  76. failed = self._waitForString(init, "bind10: invalid user: 'bogus_user'")
  77. time.sleep(0.1)
  78. init.terminate()
  79. self.assertTrue(init.wait() == 1)
  80. self.assertTrue(failed)
  81. def testBadUid(self):
  82. """Run bind10 with a bogus user ID"""
  83. init = subprocess.Popen(args=(BIND10_EXE, "-u", "999999999"),
  84. stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
  85. failed = self._waitForString(init, "bind10: invalid user: '999999999'")
  86. time.sleep(0.1)
  87. init.terminate()
  88. self.assertTrue(init.wait() == 1)
  89. self.assertTrue(failed)
  90. def testFailSetUser(self):
  91. """Try the -u option when we don't run as root"""
  92. global SUID_USER
  93. if SUID_USER is None:
  94. self.skipTest("test needs a valid user (set when run)")
  95. if os.getuid() == 0:
  96. self.skipTest("test must not be run as root (uid is 0)")
  97. # XXX: we depend on the "nobody" user
  98. init = subprocess.Popen(args=(BIND10_EXE, "-u", "nobody"),
  99. stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
  100. failed = self._waitForString(init, "[bind10] Error on startup: Unable to start b10-msgq; Unable to change to user nobody")
  101. time.sleep(0.1)
  102. init.terminate()
  103. self.assertTrue(init.wait() == 1)
  104. self.assertTrue(failed)
  105. def testSetUser(self):
  106. """Try the -u option"""
  107. global SUID_USER
  108. if SUID_USER is None:
  109. self.skipTest("test needs a valid user (set when run)")
  110. if os.getuid() != 0:
  111. self.skipTest("test must run as root (uid is not 0)")
  112. if os.geteuid() != 0:
  113. self.skipTest("test must run as root (euid is not 0)")
  114. init = subprocess.Popen(args=(BIND10_EXE, "-u", SUID_USER),
  115. stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
  116. started_ok = self._waitForString(init, '[bind10] BIND 10 started')
  117. self.assertTrue(started_ok)
  118. ps = subprocess.Popen(args=("ps", "axo", "user,pid"),
  119. stdout=subprocess.PIPE)
  120. s = ps.stdout.readline()
  121. ps_user = None
  122. while True:
  123. s = ps.stdout.readline()
  124. if s == '': break
  125. (user, pid) = s.split()
  126. if int(pid) == init.pid:
  127. ps_user = user.decode()
  128. break
  129. self.assertTrue(ps_user is not None)
  130. self.assertTrue(ps_user == SUID_USER)
  131. time.sleep(0.1)
  132. init.terminate()
  133. x = init.wait()
  134. self.assertTrue(init.wait() == 0)
  135. def testPrettyName(self):
  136. """Try the --pretty-name option."""
  137. CMD_PRETTY_NAME = b'init-name-test'
  138. init = subprocess.Popen(args=(BIND10_EXE, '--pretty-name',
  139. CMD_PRETTY_NAME), stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
  140. started_ok = self._waitForString(init, '[bind10] BIND 10 started')
  141. self.assertTrue(started_ok)
  142. ps = subprocess.Popen(args=("ps", "axo", "pid,comm"),
  143. stdout=subprocess.PIPE)
  144. s = ps.stdout.readline()
  145. command = None
  146. while True:
  147. s = ps.stdout.readline()
  148. if s == '': break
  149. (pid,comm) = s.split(None, 1)
  150. if int(pid) == init.pid:
  151. command = comm
  152. break
  153. self.assertEqual(command, CMD_PRETTY_NAME + b'\n')
  154. time.sleep(0.1)
  155. init.terminate()
  156. init.wait()
  157. if __name__ == '__main__':
  158. unittest.main()