comparison testharness/src/lib.rs @ 166:2f5913131295

Separate flag/action flags into flags and action. This also individualizes the type of flag for each PAM function, so that you can only call a function with the right flags and values.
author Paul Fisher <paul@pfish.zone>
date Tue, 15 Jul 2025 00:32:24 -0400
parents a75a66cb4181
children 0cabe7b94a4f
comparison
equal deleted inserted replaced
165:c4b1e280463c 166:2f5913131295
3 use crate::nonstick::items::ItemsMut; 3 use crate::nonstick::items::ItemsMut;
4 use std::cell::Cell; 4 use std::cell::Cell;
5 extern crate nonstick; 5 extern crate nonstick;
6 6
7 use nonstick::conv::{ErrorMsg, InfoMsg, MaskedQAndA, QAndA}; 7 use nonstick::conv::{ErrorMsg, InfoMsg, MaskedQAndA, QAndA};
8 use nonstick::{error, info, pam_hooks, ErrorCode, Flags, ModuleClient, PamModule}; 8 use nonstick::{
9 error, info, pam_hooks, AuthnFlags, AuthtokAction, AuthtokFlags, ErrorCode, ModuleClient,
10 PamModule,
11 };
9 use std::ffi::{CStr, OsString}; 12 use std::ffi::{CStr, OsString};
10 use std::os::unix::ffi::OsStrExt; 13 use std::os::unix::ffi::OsStrExt;
11 14
12 struct TestHarness; 15 struct TestHarness;
13 16
14 impl<M: ModuleClient> PamModule<M> for TestHarness { 17 impl<M: ModuleClient> PamModule<M> for TestHarness {
15 fn authenticate(handle: &mut M, args: Vec<&CStr>, _: Flags) -> nonstick::Result<()> { 18 fn authenticate(handle: &mut M, args: Vec<&CStr>, _: AuthnFlags) -> nonstick::Result<()> {
16 let strings: Vec<_> = args.iter().map(|&a| Vec::from(a.to_bytes())).collect(); 19 let strings: Vec<_> = args.iter().map(|&a| Vec::from(a.to_bytes())).collect();
17 if strings != vec![Vec::from(b"param"), Vec::from(b"param2")] { 20 if strings != vec![Vec::from(b"param"), Vec::from(b"param2")] {
18 return Err(ErrorCode::SystemError); 21 return Err(ErrorCode::SystemError);
19 } 22 }
20 let username = handle.username(None)?; 23 let username = handle.username(None)?;
49 } else { 52 } else {
50 Err(ErrorCode::Abort) 53 Err(ErrorCode::Abort)
51 } 54 }
52 } 55 }
53 56
54 fn account_management(handle: &mut M, _: Vec<&CStr>, _: Flags) -> nonstick::Result<()> { 57 fn account_management(handle: &mut M, _: Vec<&CStr>, _: AuthnFlags) -> nonstick::Result<()> {
55 let value: &Cell<i32> = match handle.username(None)?.as_bytes() { 58 let value: &Cell<i32> = match handle.username(None)?.as_bytes() {
56 b"initial" => return Err(ErrorCode::AccountExpired), 59 b"initial" => return Err(ErrorCode::AccountExpired),
57 b"updated-in-process" => handle.get_module_data("florgus"), 60 b"updated-in-process" => handle.get_module_data("florgus"),
58 _ => return Err(ErrorCode::UserUnknown), 61 _ => return Err(ErrorCode::UserUnknown),
59 } 62 }
75 } else { 78 } else {
76 Ok(()) 79 Ok(())
77 } 80 }
78 } 81 }
79 82
80 fn change_authtok(handle: &mut M, _: Vec<&CStr>, flags: Flags) -> nonstick::Result<()> { 83 fn change_authtok(
81 if flags.contains(Flags::PRELIMINARY_CHECK) { 84 handle: &mut M,
82 let password = handle.authtok(None)?; 85 _: Vec<&CStr>,
83 if password.as_bytes() != b"acceptable" { 86 action: AuthtokAction,
84 return Err(ErrorCode::PermissionDenied); 87 _flags: AuthtokFlags,
88 ) -> nonstick::Result<()> {
89 match action {
90 AuthtokAction::PreliminaryCheck => {
91 let password = handle.authtok(None)?;
92 if password.as_bytes() != b"acceptable" {
93 return Err(ErrorCode::PermissionDenied);
94 }
95 handle.set_module_data("checked_pass", password)
85 } 96 }
86 handle.set_module_data("checked_pass", password) 97 AuthtokAction::Update => {
87 } else if flags.contains(Flags::UPDATE_AUTHTOK) { 98 let password = handle.authtok(None)?;
88 let password = handle.authtok(None)?; 99 let checked: &OsString = handle
89 let checked: &OsString = handle 100 .get_module_data("checked_pass")
90 .get_module_data("checked_pass") 101 .ok_or(ErrorCode::SystemError)?;
91 .ok_or(ErrorCode::SystemError)?; 102 if password != *checked {
92 if password != *checked { 103 error!(handle, "password mismatch? {password:?} {checked:?}");
93 error!(handle, "password mismatch? {password:?} {checked:?}"); 104 return Err(ErrorCode::AuthenticationError);
94 return Err(ErrorCode::AuthenticationError); 105 }
106 Ok(())
95 } 107 }
96 Ok(())
97 } else {
98 error!(handle, "invalid flag state: {flags:?}");
99 Err(ErrorCode::SystemError)
100 } 108 }
101 } 109 }
102 } 110 }
103 111
104 pam_hooks!(TestHarness); 112 pam_hooks!(TestHarness);