예제 #1
0
 def test_sync(self):
     with TempConfig(MOCKDUO_CONF) as temp:
         result = login_duo(
             ["-d", "-c", temp.name, "-f", "whatever", "true"], )
         self.assertRegexpMatches(
             result["stderr"][0],
             r"Successful Duo login for 'whatever'",
         )
예제 #2
0
 def test_su_service_bad_user(self):
     """Test that we return user unknown if we can't find the calling user"""
     with TempConfig(MOCKDUO_CONF) as temp:
         result = pam_duo(
             ["-d", "-c", temp.name],
             env={"PAM_SERVICE": "su", "NO_USER": "******"},
         )
         self.assertEqual(result["returncode"], 1)
예제 #3
0
 def test_gecos_field_unparsed(self):
     with TempConfig(MOCKDUO_GECOS_SEND_UNPARSED) as temp:
         result = pam_duo(
             ["-d", "-c", temp.name, "-f", "fullgecos", "true"],
         )
         self.assertRegexpMatches(
             result["stderr"][0],
             r"Skipped Duo login for 'full_gecos_field': full-gecos-field",
         )
예제 #4
0
 def test_gecos_delimiter_default_position_6(self):
     with TempConfig(MOCKDUO_GECOS_DEFAULT_DELIM_6_POS) as temp:
         result = pam_duo(
             ["-d", "-c", temp.name, "-f", "gecos,6", "true"],
         )
         self.assertRegexpMatches(
             result["stderr"][0],
             "Skipped Duo login for 'gecos_user_gecos_field6': gecos-user-gecos-field6-allowed",
         )
예제 #5
0
 def test_gecos_delimiter_slash_position_3(self):
     with TempConfig(MOCKDUO_GECOS_SLASH_DELIM_3_POS) as temp:
         result = pam_duo(
             ["-d", "-c", temp.name, "-f", "gecos/3", "true"],
         )
         self.assertRegexpMatches(
             result["stderr"][0],
             r"Skipped Duo login for 'gecos_user_gecos_field3': gecos-user-gecos-field3-allowed",
         )
예제 #6
0
 def test_gecos_delimiter_slash_position_3(self):
     with TempConfig(MOCKDUO_GECOS_SLASH_DELIM_3_POS) as temp:
         result = login_duo(
             ["-d", "-c", temp.name, "true"],
             env={"UID": "1011"},
             preload_script=os.path.join(TESTDIR, "login_duo.py"),
         )
         self.assertRegexpMatches(
             result["stderr"][0],
             r"Skipped Duo login for 'gecos_user_gecos_field3': gecos-user-gecos-field3-allowed",
         )
예제 #7
0
 def test_gecos_empty(self):
     with TempConfig(MOCKDUO_GECOS_SEND_UNPARSED) as temp:
         result = login_duo(
             ["-d", "-c", temp.name, "true"],
             env={"UID": "1016"},
             preload_script=os.path.join(TESTDIR, "login_duo.py"),
         )
         self.assertRegexpMatches(
             result["stderr"][0],
             r"Empty GECOS field",
         )
예제 #8
0
 def test_invalid_argument(self):
     with TempConfig(MOCKDUO_CONF) as duo_config:
         pamd_conf = "auth  required  {libpath}/pam_duo.so conf={duo_config_path} notanarg".format(
             libpath=os.path.join(topbuilddir, "pam_duo", ".libs"),
             duo_config_path=duo_config.name,
         )
         with TempPamConfig(pamd_conf) as pam_config:
             process = testpam(
                 ["-d", "-c", duo_config.name, "-f", "whatever"], pam_config.name
             )
             self.assertEqual(process.returncode, 1)
예제 #9
0
 def test_gecos_parsing_error(self):
     with TempConfig(MOCKDUO_GECOS_SLASH_DELIM_3_POS) as temp:
         result = login_duo(
             ["-d", "-c", temp.name, "true"],
             env={"UID": "1012"},
             preload_script=os.path.join(TESTDIR, "login_duo.py"),
         )
         self.assertRegexpMatches(
             result["stderr"][0],
             r"Could not parse GECOS field",
         )
예제 #10
0
 def test_gecos_field_unparsed(self):
     with TempConfig(MOCKDUO_GECOS_SEND_UNPARSED) as temp:
         result = login_duo(
             ["-d", "-c", temp.name, "true"],
             env={"UID": "1010"},
             preload_script=os.path.join(TESTDIR, "login_duo.py"),
         )
         self.assertRegexpMatches(
             result["stderr"][0],
             r"Successful Duo login for '1/2/3/4/5/gecos_user_gecos_field6'",
         )
예제 #11
0
 def test_shell_as_command(self):
     with TempConfig(MOCKDUO_AUTOPUSH) as temp:
         process = login_duo_interactive(
             ["-d", "-c", temp.name, "echo", "SUCCESS"],
             env={
                 "PS1": "> ",
                 "UID": "1017"
             },
             preload_script=os.path.join(TESTDIR, "login_duo.py"),
         )
         self.assertEqual(process.expect("-c echo SUCCESS", timeout=10), 0)
예제 #12
0
 def test_users_bypass(self):
     with TempConfig(MOCKDUO_USERS) as temp:
         result = login_duo(
             ["-d", "-c", temp.name, "-f", "preauth-allow", "true"],
             env={"UID": "1004"},
             preload_script=os.path.join(TESTDIR, "groups.py"),
         )
         self.assertRegexpMatches(
             result["stderr"][0],
             r"User preauth-allow bypassed Duo 2FA due to user's UNIX group",
         )
예제 #13
0
 def test_max_prompts_equals_one(self):
     with TempConfig(MOCKDUO_PROMPTS_1) as temp:
         result = pam_duo(["-d", "-f", "pam_prompt", "-c", temp.name, "true"])
         self.assertRegexpMatches(
             result["stderr"][0], "Failed Duo login for 'pam_prompt'"
         )
         self.assertRegexpMatches(
             result["stdout"][0], "Autopushing login request to phone..."
         )
         self.assertRegexpMatches(
             result["stdout"][1], "Invalid passcode, please try again."
         )
예제 #14
0
 def test_deprecated_gecos_parsed_flag(self):
     with TempConfig(MOCKDUO_GECOS_DEPRECATED_PARSE_FLAG) as temp:
         result = pam_duo(
             ["-d", "-c", temp.name, "-f", "gecos/6", "true"],
         )
         self.assertRegexpMatches(
             result["stderr"][0],
             r"The gecos_parsed configuration item for Duo Unix is deprecated and no longer has any effect. Use gecos_delim and gecos_username_pos instead",
         )
         self.assertRegexpMatches(
             result["stderr"][1],
             "Skipped Duo login for 'gecos/6': gecos/6",
         )
예제 #15
0
 def test_admins_and_not_users_match_admins(self):
     with TempConfig(MOCKDUO_ADMINS_NO_USERS) as temp:
         result = login_duo(
             ["-d", "-c", temp.name, "-f", "preauth-allow", "true"],
             env={
                 "UID": "1003",
             },
             preload_script=os.path.join(TESTDIR, "groups.py"),
         )
         self.assertRegexpMatches(
             result["stderr"][0],
             r"Skipped Duo login for 'preauth-allow': preauth-allowed",
         )
예제 #16
0
 def test_default_shell(self):
     """Test that we fallback to /bin/sh if there is no shell specified for the user"""
     with TempConfig(MOCKDUO_AUTOPUSH) as temp:
         process = login_duo_interactive(
             ["-d", "-c", temp.name],
             env={
                 "PS1": "$ ",
                 "UID": "1015"
             },
             preload_script=os.path.join(TESTDIR, "login_duo.py"),
         )
         # this double escaping is needed to check for a literal "$"
         self.assertEqual(process.expect("\\$", timeout=10), 0)
예제 #17
0
 def test_missing_uid(self):
     with TempConfig(MOCKDUO_CONF) as temp:
         result = login_duo(
             ["-d", "-c", temp.name, "-f", "timeout", "true"],
             env={
                 "TIMEOUT": "1",
             },
             preload_script=os.path.join(TESTDIR, "login_duo.py"),
         )
         self.assertRegexpMatches(
             result["stderr"][0],
             r"Who are you?",
         )
예제 #18
0
 def test_users_only_match_users(self):
     for uid in range(1000, 1003):
         with TempConfig(MOCKDUO_USERS) as temp:
             result = login_duo(
                 ["-d", "-c", temp.name, "-f", "preauth-allow", "true"],
                 env={
                     "UID": str(uid),
                 },
                 preload_script=os.path.join(TESTDIR, "groups.py"),
             )
             self.assertRegexpMatches(
                 result["stderr"][0],
                 r"Skipped Duo login for 'preauth-allow': preauth-allowed",
             )
예제 #19
0
 def test_nonroot(self):
     with TempConfig(MOCKDUO_CONF) as temp:
         result = login_duo(
             ["-d", "-c", temp.name, "-f", "preauth-allow"],
             env={
                 "EUID": "1002",
                 "UID": "1001",
             },
             preload_script=os.path.join(TESTDIR, "login_duo.py"),
         )
         self.assertRegexpMatches(
             result["stderr"][0],
             r"Only root may specify -c or -f",
         )
예제 #20
0
 def test_command_from_env(self):
     with TempConfig(MOCKDUO_CONF) as temp:
         result = login_duo(
             ["-d", "-c", temp.name, "-f", "preauth-allow"],
             env={
                 "UID": "1001",
                 "SSH_ORIGINAL_COMMAND": "echo 'hello'",
             },
             preload_script=os.path.join(TESTDIR, "login_duo.py"),
         )
         self.assertRegexpMatches(
             result["stdout"][0],
             r"hello",
         )
예제 #21
0
 def test_unprivileged(self):
     with TempConfig(MOCKDUO_CONF) as temp:
         result = login_duo(
             ["-d"],
             env={
                 "EUID": "1000",
                 "UID": "1001",
             },
             preload_script=os.path.join(TESTDIR, "login_duo.py"),
             timeout=10,
         )
         self.assertRegexpMatches(
             result["stderr"][0],
             r"couldn't drop privileges:",
         )
예제 #22
0
 def test_deprecated_gecos_parsed_flag(self):
     with TempConfig(MOCKDUO_GECOS_DEPRECATED_PARSE_FLAG) as temp:
         result = login_duo(
             ["-d", "-c", temp.name, "true"],
             env={"UID": "1010"},
             preload_script=os.path.join(TESTDIR, "login_duo.py"),
         )
         self.assertRegexpMatches(
             result["stderr"][0],
             r"The gecos_parsed configuration item for Duo Unix is deprecated and no longer has any effect. Use gecos_delim and gecos_username_pos instead",
         )
         self.assertRegexpMatches(
             result["stderr"][1],
             "Skipped Duo login for 'gecos/6': gecos/6",
         )
예제 #23
0
 def test_invalid_pos_value(self):
     with TempConfig(MOCKDUO_GECOS_INVALID_POS) as temp:
         result = login_duo(["-d", "-c", temp.name, "true"], )
         self.assertEquals(
             result["stderr"][0],
             "Gecos position starts at 1",
         )
         self.assertRegexpMatches(
             result["stderr"][1],
             r"Invalid login_duo option: 'gecos_username_pos'",
         )
         self.assertRegexpMatches(
             result["stderr"][2],
             r"Parse error in {config}, line \d+".format(config=temp.name),
         )
예제 #24
0
    def test_motd(self):
        with TempConfig(MOTD_CONF) as temp:
            test_motd = "test_string"
            with open("/tmp/duomotdtest", "w") as fh:
                fh.write("{motd}\n".format(motd=test_motd))

            process = login_duo_interactive(
                ["-d", "-c", temp.name, "-f", "whatever", "echo", "SUCCESS"],
                env={
                    "UID": "1001",
                },
                preload_script=os.path.join(TESTDIR, "login_duo.py"),
            )
            process.sendline("1")
            self.assertEqual(process.expect("test_string", timeout=10), 0)
예제 #25
0
 def test_invalid_delimiter_value_whitespace(self):
     with TempConfig(MOCKDUO_GECOS_INVALID_DELIM_WHITESPACE) as temp:
         result = login_duo(["-d", "-c", temp.name, "true"], )
         self.assertEquals(
             result["stderr"][0],
             "Invalid character option length. Character fields must be 1 character long: ''",
         )
         self.assertRegexpMatches(
             result["stderr"][1],
             r"Invalid login_duo option: 'gecos_delim'",
         )
         self.assertRegexpMatches(
             result["stderr"][2],
             r"Parse error in {config}, line \d+".format(config=temp.name),
         )
예제 #26
0
 def test_gecos_invalid_delimiter_length(self):
     with TempConfig(MOCKDUO_GECOS_LONG_DELIM) as temp:
         result = login_duo(["-d", "-c", temp.name, "true"], )
         self.assertRegexpMatches(
             result["stderr"][0],
             r"Invalid character option length. Character fields must be 1 character long: ',,'",
         )
         self.assertRegexpMatches(
             result["stderr"][1],
             r"Invalid login_duo option: 'gecos_delim'",
         )
         self.assertRegexpMatches(
             result["stderr"][2],
             r"Parse error in {config}, line \d+".format(config=temp.name),
         )
예제 #27
0
 def test_privsep_user_not_found(self):
     with TempConfig(MOCKDUO_CONF) as temp:
         result = login_duo(
             ["-d"],
             env={
                 "EUID": "0",
                 "UID": "1001",
                 "NO_PRIVSEP_USER": "******",
             },
             preload_script=os.path.join(TESTDIR, "login_duo.py"),
             timeout=10,
         )
         self.assertRegexpMatches(
             result["stderr"][0],
             r"User .* not found",
         )
예제 #28
0
 def test_connection_timeout(self):
     with TempConfig(MOCKDUO_CONF) as temp:
         result = login_duo(
             ["-d", "-c", temp.name, "-f", "timeout", "true"],
             env={
                 "UID": "1001",
                 "TIMEOUT": "1",
             },
             preload_script=os.path.join(TESTDIR, "login_duo.py"),
             timeout=10,
         )
         for line in result["stderr"][:3]:
             self.assertEqual(line, "Attempting connection")
         self.assertRegexpMatches(
             result["stderr"][3],
             r"Failsafe Duo login for 'timeout': Couldn't connect to localhost:4443: Failed to connect",
         )
예제 #29
0
    def test_env_factor(self):
        config = DuoUnixConfig(
            ikey="DIXYZV6YM8IFYVWBINCA",
            skey="yWHSMhWucAcp7qvuH3HWTaSaKABs8Gaddiv1NIRo",
            host="localhost:4443",
            cafile="certs/mockduo-ca.pem",
            accept_env_factor="yes",
        )

        with TempConfig(config) as temp:
            process = login_duo_interactive(
                ["-d", "-c", temp.name, "-f", "whatever", "echo", "SUCCESS"],
                env={
                    "UID": "1001",
                    "DUO_PASSCODE": "push1",
                },
            )
            self.assertEqual(process.expect("SUCCESS", timeout=10), 0)
예제 #30
0
 def test_invalid_delimiter_value(self):
     for config in [
             MOCKDUO_GECOS_INVALID_DELIM_COLON,
             MOCKDUO_GECOS_INVALID_DELIM_PUNC,
     ]:
         with TempConfig(config) as temp:
             result = login_duo(["-d", "-c", temp.name, "true"], )
             self.assertEquals(
                 result["stderr"][0],
                 "Invalid gecos_delim '{delim}' (delimiter must be punctuation other than ':')"
                 .format(delim=config["gecos_delim"]),
             )
             self.assertRegexpMatches(
                 result["stderr"][1],
                 r"Invalid login_duo option: 'gecos_delim'",
             )
             self.assertRegexpMatches(
                 result["stderr"][2],
                 r"Parse error in {config}, line \d+".format(
                     config=temp.name),
             )