gardesk/garcard / c762821

Browse files

Test visible prompts and inline errors

Authored by mfwolffe <wolffemf@dukes.jmu.edu>
SHA
c7628219aa287d6de239a3e0b2278bef49448f18
Parents
676af33
Tree
b9be3c3

1 changed file

StatusFile+-
M garcard/src/polkit_helper.rs 101 0
garcard/src/polkit_helper.rsmodified
@@ -1181,6 +1181,107 @@ mod tests {
1181
         let _ = std::fs::remove_file(&socket_path);
1181
         let _ = std::fs::remove_file(&socket_path);
1182
     }
1182
     }
1183
 
1183
 
1184
+    #[test]
1185
+    fn helper_client_handles_visible_prompt_round_trip() {
1186
+        let socket_path = temp_socket_path();
1187
+        let listener = UnixListener::bind(&socket_path).expect("bind test socket");
1188
+
1189
+        let server = thread::spawn(move || {
1190
+            let (mut stream, _) = listener.accept().expect("accept");
1191
+            let read_stream = stream.try_clone().expect("clone");
1192
+            let mut reader = BufReader::new(read_stream);
1193
+
1194
+            let mut first_line = String::new();
1195
+            reader.read_line(&mut first_line).expect("read first line");
1196
+            let first = first_line.trim().to_string();
1197
+            if first == "operator" {
1198
+                let mut cookie = String::new();
1199
+                reader.read_line(&mut cookie).expect("read cookie");
1200
+            }
1201
+
1202
+            stream
1203
+                .write_all(b"PAM_TEXT_INFO Enter one-time code\n")
1204
+                .expect("write info");
1205
+            stream
1206
+                .write_all(b"PAM_PROMPT_ECHO_ON Code:\n")
1207
+                .expect("write prompt");
1208
+            stream.flush().expect("flush prompt");
1209
+
1210
+            let mut code = String::new();
1211
+            reader.read_line(&mut code).expect("read code");
1212
+            assert_eq!(code.trim(), "123456");
1213
+
1214
+            stream.write_all(b"SUCCESS\n").expect("write success");
1215
+            stream.flush().expect("flush success");
1216
+        });
1217
+
1218
+        let client = HelperSocketClient::new(&socket_path);
1219
+        let mut prompts = FakePrompt {
1220
+            plain_response: PromptResponse::Submitted("123456".to_string()),
1221
+            ..FakePrompt::default()
1222
+        };
1223
+
1224
+        let outcome = client
1225
+            .authenticate("operator", "cookie-visible", &mut prompts)
1226
+            .expect("authenticate visible");
1227
+        assert_eq!(outcome, HelperOutcome::Authorized);
1228
+        assert_eq!(prompts.infos, vec!["Enter one-time code"]);
1229
+        assert_eq!(prompts.success_count, 1);
1230
+
1231
+        server.join().expect("server join");
1232
+        let _ = std::fs::remove_file(&socket_path);
1233
+    }
1234
+
1235
+    #[test]
1236
+    fn helper_client_recovers_after_inline_error_message() {
1237
+        let socket_path = temp_socket_path();
1238
+        let listener = UnixListener::bind(&socket_path).expect("bind test socket");
1239
+
1240
+        let server = thread::spawn(move || {
1241
+            let (mut stream, _) = listener.accept().expect("accept");
1242
+            let read_stream = stream.try_clone().expect("clone");
1243
+            let mut reader = BufReader::new(read_stream);
1244
+
1245
+            let mut first_line = String::new();
1246
+            reader.read_line(&mut first_line).expect("read first line");
1247
+            if first_line.trim() == "operator" {
1248
+                let mut cookie = String::new();
1249
+                reader.read_line(&mut cookie).expect("read cookie");
1250
+            }
1251
+
1252
+            stream
1253
+                .write_all(b"PAM_ERROR_MSG Incorrect code, try again\n")
1254
+                .expect("write error");
1255
+            stream
1256
+                .write_all(b"PAM_PROMPT_ECHO_OFF Password:\n")
1257
+                .expect("write prompt");
1258
+            stream.flush().expect("flush prompt");
1259
+
1260
+            let mut secret = String::new();
1261
+            reader.read_line(&mut secret).expect("read secret");
1262
+            assert_eq!(secret.trim(), "correct horse");
1263
+
1264
+            stream.write_all(b"SUCCESS\n").expect("write success");
1265
+            stream.flush().expect("flush success");
1266
+        });
1267
+
1268
+        let client = HelperSocketClient::new(&socket_path);
1269
+        let mut prompts = FakePrompt {
1270
+            secret_response: PromptResponse::Submitted("correct horse".to_string()),
1271
+            ..FakePrompt::default()
1272
+        };
1273
+
1274
+        let outcome = client
1275
+            .authenticate("operator", "cookie-inline-error", &mut prompts)
1276
+            .expect("authenticate recovery");
1277
+        assert_eq!(outcome, HelperOutcome::Authorized);
1278
+        assert_eq!(prompts.errors, vec!["Incorrect code, try again"]);
1279
+        assert_eq!(prompts.success_count, 1);
1280
+
1281
+        server.join().expect("server join");
1282
+        let _ = std::fs::remove_file(&socket_path);
1283
+    }
1284
+
1184
     #[test]
1285
     #[test]
1185
     fn helper_client_reports_timeout_from_prompt_provider() {
1286
     fn helper_client_reports_timeout_from_prompt_provider() {
1186
         let socket_path = temp_socket_path();
1287
         let socket_path = temp_socket_path();