comparison src/conv.rs @ 1:b195a14058bb

initial commit
author Jesse Hallett <jesse@galois.com>
date Thu, 05 Mar 2015 16:25:10 -0800
parents
children 2ec97116d72c
comparison
equal deleted inserted replaced
0:8ed8b2cfd909 1:b195a14058bb
1 use libc::{c_char, c_int};
2 use std::{ptr};
3 use std::ffi::{CStr, CString};
4
5 use constants;
6 use constants::*;
7 use module::{PamItem, PamResult};
8
9 #[allow(missing_copy_implementations)]
10 pub enum AppDataPtr {}
11
12 #[repr(C)]
13 struct PamMessage {
14 msg_style: PamMessageStyle,
15 msg: *const c_char,
16 }
17
18 #[repr(C)]
19 struct PamResponse {
20 resp: *const c_char,
21 resp_retcode: AlwaysZero,
22 }
23
24 /// `PamConv` acts as a channel for communicating with user.
25 ///
26 /// 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
28 /// will be relayed back.
29 #[repr(C)]
30 pub struct PamConv {
31 conv: extern fn(num_msg: c_int,
32 pam_message: &&PamMessage,
33 pam_response: &*mut PamResponse,
34 appdata_ptr: *const AppDataPtr
35 ) -> PamResultCode,
36 appdata_ptr: *const AppDataPtr,
37 }
38
39 impl PamConv {
40 /// Sends a message to the pam client.
41 ///
42 /// This will typically result in the user seeing a message or a prompt.
43 /// There are several message styles available:
44 ///
45 /// - PAM_PROMPT_ECHO_OFF
46 /// - PAM_PROMPT_ECHO_ON
47 /// - PAM_ERROR_MSG
48 /// - PAM_TEXT_INFO
49 /// - PAM_RADIO_TYPE
50 /// - PAM_BINARY_PROMPT
51 ///
52 /// Note that the user experience will depend on how the client implements
53 /// these message styles - and not all applications implement all message
54 /// styles.
55 pub fn send(&self, style: PamMessageStyle, msg: &str) -> PamResult<Option<String>> {
56 let resp_ptr: *mut PamResponse = ptr::null_mut();
57 let msg = PamMessage {
58 msg_style: style,
59 msg: CString::new(msg).unwrap().as_ptr(),
60 };
61
62 let ret = (self.conv)(1, &&msg, &resp_ptr, self.appdata_ptr);
63
64 if constants::PAM_SUCCESS == ret {
65 let s = unsafe { resp_ptr.as_ref() }
66 .and_then(|r| {
67 if r.resp.is_null() {
68 None
69 }
70 else {
71 let bytes = unsafe { CStr::from_ptr(r.resp).to_bytes() };
72 String::from_utf8(bytes.to_vec()).ok()
73 }
74 });
75 Ok(s)
76 } else {
77 Err(ret)
78 }
79 }
80 }
81
82 impl PamItem for PamConv {
83 fn item_type(_: Option<Self>) -> PamItemType { PAM_CONV }
84 }