3 password2 = "helloworld";
6 hashed_bcrypt = "$2b$05$8xIEflrk2RxQtcVXbGIxs.Vl0x7dF1/JSv3cyX6JJt0npzkTCWvxK"; # fnord
7 hashed_yeshash = "$y$j9T$d8Z4EAf8P1SvM/aDFbxMS0$VnTXMp/Hnc7QdCBEaLTq5ZFOAFo2/PM0/xEAFuOE88."; # fnord
8 hashed_sha512crypt = "$6$ymzs8WINZ5wGwQcV$VC2S0cQiX8NVukOLymysTPn4v1zJoJp3NGyhnqyv/dAf4NWZsBWYveQcj6gEJr4ZUjRBRjM0Pj1L8TCQ8hUUp0"; # meow
9 in import ./make-test-python.nix ({ pkgs, ... }: {
11 meta = with pkgs.lib.maintainers; { maintainers = [ nequissimus ]; };
13 nodes.shadow = { pkgs, ... }: {
14 environment.systemPackages = [ pkgs.shadow ];
35 hashedPasswordFile = (pkgs.writeText "hashed_bcrypt" hashed_bcrypt).outPath;
40 hashedPassword = hashed_yeshash;
45 initialHashedPassword = "!";
46 hashedPassword = hashed_sha512crypt; # should take precedence over initialHashedPassword
53 shadow.wait_for_unit("multi-user.target")
54 shadow.wait_until_succeeds("pgrep -f 'agetty.*tty1'")
56 with subtest("Normal login"):
57 shadow.send_key("alt-f2")
58 shadow.wait_until_succeeds("[ $(fgconsole) = 2 ]")
59 shadow.wait_for_unit("getty@tty2.service")
60 shadow.wait_until_succeeds("pgrep -f 'agetty.*tty2'")
61 shadow.wait_until_tty_matches("2", "login: ")
62 shadow.send_chars("emma\n")
63 shadow.wait_until_tty_matches("2", "login: emma")
64 shadow.wait_until_succeeds("pgrep login")
66 shadow.send_chars("${password1}\n")
67 shadow.send_chars("whoami > /tmp/1\n")
68 shadow.wait_for_file("/tmp/1")
69 assert "emma" in shadow.succeed("cat /tmp/1")
71 with subtest("Switch user"):
72 shadow.send_chars("su - ash\n")
74 shadow.send_chars("${password4}\n")
76 shadow.send_chars("whoami > /tmp/3\n")
77 shadow.wait_for_file("/tmp/3")
78 assert "ash" in shadow.succeed("cat /tmp/3")
80 with subtest("Change password"):
81 shadow.send_key("alt-f3")
82 shadow.wait_until_succeeds("[ $(fgconsole) = 3 ]")
83 shadow.wait_for_unit("getty@tty3.service")
84 shadow.wait_until_succeeds("pgrep -f 'agetty.*tty3'")
85 shadow.wait_until_tty_matches("3", "login: ")
86 shadow.send_chars("emma\n")
87 shadow.wait_until_tty_matches("3", "login: emma")
88 shadow.wait_until_succeeds("pgrep login")
90 shadow.send_chars("${password1}\n")
91 shadow.send_chars("passwd\n")
93 shadow.send_chars("${password1}\n")
95 shadow.send_chars("${password3}\n")
97 shadow.send_chars("${password3}\n")
99 shadow.send_key("alt-f4")
100 shadow.wait_until_succeeds("[ $(fgconsole) = 4 ]")
101 shadow.wait_for_unit("getty@tty4.service")
102 shadow.wait_until_succeeds("pgrep -f 'agetty.*tty4'")
103 shadow.wait_until_tty_matches("4", "login: ")
104 shadow.send_chars("emma\n")
105 shadow.wait_until_tty_matches("4", "login: emma")
106 shadow.wait_until_succeeds("pgrep login")
108 shadow.send_chars("${password1}\n")
109 shadow.wait_until_tty_matches("4", "Login incorrect")
110 shadow.wait_until_tty_matches("4", "login:")
111 shadow.send_chars("emma\n")
112 shadow.wait_until_tty_matches("4", "login: emma")
113 shadow.wait_until_succeeds("pgrep login")
115 shadow.send_chars("${password3}\n")
116 shadow.send_chars("whoami > /tmp/2\n")
117 shadow.wait_for_file("/tmp/2")
118 assert "emma" in shadow.succeed("cat /tmp/2")
120 with subtest("Groups"):
121 assert "foobar" not in shadow.succeed("groups emma")
122 shadow.succeed("groupadd foobar")
123 shadow.succeed("usermod -a -G foobar emma")
124 assert "foobar" in shadow.succeed("groups emma")
126 with subtest("nologin shell"):
127 shadow.send_key("alt-f5")
128 shadow.wait_until_succeeds("[ $(fgconsole) = 5 ]")
129 shadow.wait_for_unit("getty@tty5.service")
130 shadow.wait_until_succeeds("pgrep -f 'agetty.*tty5'")
131 shadow.wait_until_tty_matches("5", "login: ")
132 shadow.send_chars("layla\n")
133 shadow.wait_until_tty_matches("5", "login: layla")
134 shadow.wait_until_succeeds("pgrep login")
135 shadow.send_chars("${password2}\n")
136 shadow.wait_until_tty_matches("5", "login:")
138 with subtest("check alternate password hashes"):
139 shadow.send_key("alt-f6")
140 shadow.wait_until_succeeds("[ $(fgconsole) = 6 ]")
141 for u in ["berta", "yesim"]:
142 shadow.wait_for_unit("getty@tty6.service")
143 shadow.wait_until_succeeds("pgrep -f 'agetty.*tty6'")
144 shadow.wait_until_tty_matches("6", "login: ")
145 shadow.send_chars(f"{u}\n")
146 shadow.wait_until_tty_matches("6", f"login: {u}")
147 shadow.wait_until_succeeds("pgrep login")
149 shadow.send_chars("fnord\n")
150 shadow.send_chars(f"whoami > /tmp/{u}\n")
151 shadow.wait_for_file(f"/tmp/{u}")
152 print(shadow.succeed(f"cat /tmp/{u}"))
153 assert u in shadow.succeed(f"cat /tmp/{u}")
154 shadow.send_chars("logout\n")
156 with subtest("Ensure hashedPassword does not get overridden by initialHashedPassword"):
157 shadow.send_key("alt-f6")
158 shadow.wait_until_succeeds("[ $(fgconsole) = 6 ]")
159 shadow.wait_for_unit("getty@tty6.service")
160 shadow.wait_until_succeeds("pgrep -f 'agetty.*tty6'")
161 shadow.wait_until_tty_matches("6", "login: ")
162 shadow.send_chars("leo\n")
163 shadow.wait_until_tty_matches("6", "login: leo")
164 shadow.wait_until_succeeds("pgrep login")
166 shadow.send_chars("meow\n")
167 shadow.send_chars("whoami > /tmp/leo\n")
168 shadow.wait_for_file("/tmp/leo")
169 assert "leo" in shadow.succeed("cat /tmp/leo")
170 shadow.send_chars("logout\n")