pam: Take dyn Converse instead of PasswordConv

This commit is contained in:
Kenny Levinsen
2020-01-09 20:09:00 +01:00
parent 9e1cad0c25
commit b6a7181f59
3 changed files with 21 additions and 17 deletions

View File

@@ -6,14 +6,18 @@ use pam_sys::{PamConversation, PamMessage, PamMessageStyle, PamResponse, PamRetu
use super::converse::Converse; use super::converse::Converse;
pub fn make_conversation<C: Converse>(user_converse: &mut C) -> PamConversation { pub struct PamConvHandlerWrapper {
pub handler: Box<dyn Converse>,
}
pub fn make_conversation(conv: &mut PamConvHandlerWrapper) -> PamConversation {
PamConversation { PamConversation {
conv: Some(converse::<C>), conv: Some(converse),
data_ptr: user_converse as *mut C as *mut c_void, data_ptr: conv as *mut PamConvHandlerWrapper as *mut c_void,
} }
} }
pub extern "C" fn converse<C: Converse>( pub extern "C" fn converse(
num_msg: c_int, num_msg: c_int,
msg: *mut *mut PamMessage, msg: *mut *mut PamMessage,
out_resp: *mut *mut PamResponse, out_resp: *mut *mut PamResponse,
@@ -27,7 +31,7 @@ pub extern "C" fn converse<C: Converse>(
return PamReturnCode::BUF_ERR as c_int; return PamReturnCode::BUF_ERR as c_int;
} }
let handler = unsafe { &mut *(appdata_ptr as *mut C) }; let wrapper = unsafe { &mut *(appdata_ptr as *mut PamConvHandlerWrapper) };
let mut result: PamReturnCode = PamReturnCode::SUCCESS; let mut result: PamReturnCode = PamReturnCode::SUCCESS;
for i in 0..num_msg as isize { for i in 0..num_msg as isize {
@@ -38,21 +42,21 @@ pub extern "C" fn converse<C: Converse>(
// match on msg_style // match on msg_style
match PamMessageStyle::from(m.msg_style) { match PamMessageStyle::from(m.msg_style) {
PamMessageStyle::PROMPT_ECHO_ON => { PamMessageStyle::PROMPT_ECHO_ON => {
if let Ok(handler_response) = handler.prompt_echo(msg) { if let Ok(handler_response) = wrapper.handler.prompt_echo(msg) {
r.resp = unsafe { strdup(handler_response.as_ptr()) }; r.resp = unsafe { strdup(handler_response.as_ptr()) };
} else { } else {
result = PamReturnCode::CONV_ERR; result = PamReturnCode::CONV_ERR;
} }
} }
PamMessageStyle::PROMPT_ECHO_OFF => { PamMessageStyle::PROMPT_ECHO_OFF => {
if let Ok(handler_response) = handler.prompt_blind(msg) { if let Ok(handler_response) = wrapper.handler.prompt_blind(msg) {
r.resp = unsafe { strdup(handler_response.as_ptr()) }; r.resp = unsafe { strdup(handler_response.as_ptr()) };
} else { } else {
result = PamReturnCode::CONV_ERR; result = PamReturnCode::CONV_ERR;
} }
} }
PamMessageStyle::ERROR_MSG => handler.error(msg), PamMessageStyle::ERROR_MSG => wrapper.handler.error(msg),
PamMessageStyle::TEXT_INFO => handler.info(msg), PamMessageStyle::TEXT_INFO => wrapper.handler.info(msg),
} }
if result != PamReturnCode::SUCCESS { if result != PamReturnCode::SUCCESS {
break; break;
@@ -61,7 +65,6 @@ pub extern "C" fn converse<C: Converse>(
// free allocated memory if an error occured // free allocated memory if an error occured
if result != PamReturnCode::SUCCESS { if result != PamReturnCode::SUCCESS {
// Free any strdup'd response strings // Free any strdup'd response strings
for i in 0..num_msg as isize { for i in 0..num_msg as isize {
let r: &mut PamResponse = unsafe { &mut *(resp.offset(i)) }; let r: &mut PamResponse = unsafe { &mut *(resp.offset(i)) };

View File

@@ -6,25 +6,26 @@ use std::ptr;
use libc::c_void; use libc::c_void;
use pam_sys::{PamFlag, PamHandle, PamItemType, PamReturnCode}; use pam_sys::{PamFlag, PamHandle, PamItemType, PamReturnCode};
use super::converse::PasswordConv; use super::converse::Converse;
use super::env::{get_pam_env, PamEnvList}; use super::env::{get_pam_env, PamEnvList};
use super::ffi::make_conversation; use super::ffi::{make_conversation, PamConvHandlerWrapper};
pub struct PamSession<'a> { pub struct PamSession<'a> {
handle: &'a mut PamHandle, handle: &'a mut PamHandle,
pub converse: Box<PasswordConv>, pub converse: Box<PamConvHandlerWrapper>,
last_code: PamReturnCode, last_code: PamReturnCode,
} }
impl<'a> PamSession<'a> { impl<'a> PamSession<'a> {
pub fn start(service: &str, mut pam_conv: Box<PasswordConv>) -> Result<PamSession, Box<dyn Error>> { pub fn start(service: &str, pam_conv: Box<dyn Converse>) -> Result<PamSession, Box<dyn Error>> {
let conv = make_conversation(&mut *pam_conv); let mut pch = Box::new(PamConvHandlerWrapper { handler: pam_conv });
let conv = make_conversation(&mut *pch);
let mut pam_handle: *mut PamHandle = ptr::null_mut(); let mut pam_handle: *mut PamHandle = ptr::null_mut();
match pam_sys::start(service, None, &conv, &mut pam_handle) { match pam_sys::start(service, None, &conv, &mut pam_handle) {
PamReturnCode::SUCCESS => Ok(PamSession { PamReturnCode::SUCCESS => Ok(PamSession {
handle: unsafe { &mut *pam_handle }, handle: unsafe { &mut *pam_handle },
converse: pam_conv, converse: pch,
last_code: PamReturnCode::SUCCESS, last_code: PamReturnCode::SUCCESS,
}), }),
_ => Err(io::Error::new(io::ErrorKind::Other, "unable to start pam session").into()), _ => Err(io::Error::new(io::ErrorKind::Other, "unable to start pam session").into()),

View File

@@ -20,8 +20,8 @@ use pam_sys::{PamFlag, PamItemType};
use users::os::unix::UserExt; use users::os::unix::UserExt;
use users::User; use users::User;
use crate::pam::session::PamSession;
use crate::pam::converse::PasswordConv; use crate::pam::converse::PasswordConv;
use crate::pam::session::PamSession;
use crate::pollable::signals::blocked_sigset; use crate::pollable::signals::blocked_sigset;
use crate::terminal; use crate::terminal;