Mercurial > crates > nonstick
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); |