comparison pam/src/conv.rs @ 34:ec70822cbdef

Overhaul
author Andy Caldwell <andrew.caldwell@metaswitch.com>
date Sun, 24 Apr 2022 03:42:11 +0100
parents 1f4ef4c7e555
children 50371046c61a
comparison
equal deleted inserted replaced
32:ea5f195f035f 34:ec70822cbdef
1 use libc::{c_char, c_int}; 1 use libc::{c_char, c_int};
2 use std::ffi::{CStr, CString}; 2 use std::ffi::{CStr, CString};
3 use std::ptr; 3 use std::ptr;
4 4
5 use constants::PamResultCode; 5 use constants::PamResultCode;
6 use constants::*; 6 use constants::PamMessageStyle;
7 use module::{PamItem, PamResult}; 7 use items::Item;
8 8 use module::PamResult;
9 #[allow(missing_copy_implementations)]
10 pub enum AppDataPtr {}
11 9
12 #[repr(C)] 10 #[repr(C)]
13 struct PamMessage { 11 struct PamMessage {
14 msg_style: PamMessageStyle, 12 msg_style: PamMessageStyle,
15 msg: *const c_char, 13 msg: *const c_char,
16 } 14 }
17 15
18 #[repr(C)] 16 #[repr(C)]
19 struct PamResponse { 17 struct PamResponse {
20 resp: *const c_char, 18 resp: *const c_char,
21 resp_retcode: AlwaysZero, 19 resp_retcode: libc::c_int, // Unused - always zero
22 } 20 }
23 21
24 /// `PamConv` acts as a channel for communicating with user. 22 /// `PamConv` acts as a channel for communicating with user.
25 /// 23 ///
26 /// Communication is mediated by the pam client (the application that invoked 24 /// Communication is mediated by the pam client (the application that invoked
27 /// pam). Messages sent will be relayed to the user by the client, and response 25 /// pam). Messages sent will be relayed to the user by the client, and response
28 /// will be relayed back. 26 /// will be relayed back.
29 #[repr(C)] 27 #[repr(C)]
30 pub struct PamConv { 28 pub struct Inner {
31 conv: extern "C" fn( 29 conv: extern "C" fn(
32 num_msg: c_int, 30 num_msg: c_int,
33 pam_message: &&PamMessage, 31 pam_message: &&PamMessage,
34 pam_response: &mut *const PamResponse, 32 pam_response: &mut *const PamResponse,
35 appdata_ptr: *const AppDataPtr, 33 appdata_ptr: *const libc::c_void,
36 ) -> PamResultCode, 34 ) -> PamResultCode,
37 appdata_ptr: *const AppDataPtr, 35 appdata_ptr: *const libc::c_void,
38 } 36 }
39 37
40 impl PamConv { 38 pub struct Conv<'a>(&'a Inner);
39
40 impl<'a> Conv<'a> {
41 /// Sends a message to the pam client. 41 /// Sends a message to the pam client.
42 /// 42 ///
43 /// This will typically result in the user seeing a message or a prompt. 43 /// This will typically result in the user seeing a message or a prompt.
44 /// There are several message styles available: 44 /// There are several message styles available:
45 /// 45 ///
51 /// - PAM_BINARY_PROMPT 51 /// - PAM_BINARY_PROMPT
52 /// 52 ///
53 /// Note that the user experience will depend on how the client implements 53 /// Note that the user experience will depend on how the client implements
54 /// these message styles - and not all applications implement all message 54 /// these message styles - and not all applications implement all message
55 /// styles. 55 /// styles.
56 pub fn send(&self, style: PamMessageStyle, msg: &str) -> PamResult<Option<String>> { 56 pub fn send(&self, style: PamMessageStyle, msg: &str) -> PamResult<Option<&CStr>> {
57 let mut resp_ptr: *const PamResponse = ptr::null(); 57 let mut resp_ptr: *const PamResponse = ptr::null();
58 let msg_cstr = CString::new(msg).unwrap(); 58 let msg_cstr = CString::new(msg).unwrap();
59 let msg = PamMessage { 59 let msg = PamMessage {
60 msg_style: style, 60 msg_style: style,
61 msg: msg_cstr.as_ptr(), 61 msg: msg_cstr.as_ptr(),
62 }; 62 };
63 63
64 let ret = (self.conv)(1, &&msg, &mut resp_ptr, self.appdata_ptr); 64 let ret = (self.0.conv)(1, &&msg, &mut resp_ptr, self.0.appdata_ptr);
65 65
66 if PamResultCode::PAM_SUCCESS == ret { 66 if PamResultCode::PAM_SUCCESS == ret {
67 // PamResponse.resp is null for styles that don't return user input like PAM_TEXT_INFO 67 // PamResponse.resp is null for styles that don't return user input like PAM_TEXT_INFO
68 let response = unsafe { (*resp_ptr).resp }; 68 let response = unsafe { (*resp_ptr).resp };
69 if response.is_null() { 69 if response.is_null() {
70 Ok(None) 70 Ok(None)
71 } else { 71 } else {
72 let bytes = unsafe { CStr::from_ptr(response).to_bytes() }; 72 Ok(Some(unsafe { CStr::from_ptr(response) }))
73 Ok(String::from_utf8(bytes.to_vec()).ok())
74 } 73 }
75 } else { 74 } else {
76 Err(ret) 75 Err(ret)
77 } 76 }
78 } 77 }
79 } 78 }
80 79
81 impl PamItem for PamConv { 80 impl<'a> Item for Conv<'a> {
82 fn item_type() -> PamItemType { 81 type Raw = Inner;
83 PAM_CONV 82
83 fn type_id() -> crate::items::ItemType {
84 crate::items::ItemType::Conv
85 }
86
87 unsafe fn from_raw(raw: *const Self::Raw) -> Self {
88 Self(&*raw)
89 }
90
91 fn into_raw(self) -> *const Self::Raw {
92 self.0 as _
84 } 93 }
85 } 94 }