pam_sys/
wrapped.rs

1// Copyright (C) 2015-2017 Florian Wilkens
2//
3// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
4// associated documentation files (the "Software"), to deal in the Software without restriction,
5// including without limitation the rights to use, copy, modify, merge, publish, distribute,
6// sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
7// furnished to do so, subject to the following conditions:
8//
9// The above copyright notice and this permission notice shall be included in all copies or substantial
10// portions of the Software.
11//
12// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
13// NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
14// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
15// OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
16// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
17
18//! Wrapped FFI bindings to Linux-PAM
19//!
20//! This module provides wrapped versions of some of the functions from
21//! the [`raw`](../raw/index.html) module which use the appropriate enums
22//! instead of `c_int`. These wrappers should always be preferred as one
23//! can safely match on their return types and prevent illegal arguments
24//! from beeing passed to the native library.
25//!
26//! Note: These wrappers get added as I need them. Feel free to open an issue
27//! or PR for the ones that you require which haven't been added yet.
28
29use libc::{c_char, c_int, c_void};
30use std::ffi::{CStr, CString};
31use std::ptr::null;
32
33use types::*;
34use raw::*;
35
36/* ------------------------ pam_appl.h -------------------------- */
37#[inline]
38pub fn start(service: &str,
39             user: Option<&str>,
40             conversation: &PamConversation,
41             handle: *mut *mut PamHandle)
42             -> PamReturnCode {
43    if let Ok(service) = CString::new(service) {
44        if let Some(usr) = user {
45            if let Ok(user) = CString::new(usr) {
46                unsafe {
47                    From::from(pam_start(service.as_ptr(),
48                                         user.as_ptr(),
49                                         conversation,
50                                         handle as *mut *const PamHandle))
51                }
52            } else {
53                PamReturnCode::BUF_ERR
54            }
55        } else {
56            unsafe {
57                From::from(pam_start(service.as_ptr(),
58                                     null(),
59                                     conversation,
60                                     handle as *mut *const PamHandle))
61            }
62        }
63    } else {
64        PamReturnCode::SERVICE_ERR
65    }
66}
67
68#[inline]
69pub fn end(handle: &mut PamHandle, status: PamReturnCode) -> PamReturnCode {
70    From::from(unsafe { pam_end(handle, status as c_int) })
71}
72
73#[inline]
74pub fn authenticate(handle: &mut PamHandle, flags: PamFlag) -> PamReturnCode {
75    From::from(unsafe { pam_authenticate(handle, flags as c_int) })
76}
77
78#[inline]
79pub fn setcred(handle: &mut PamHandle, flags: PamFlag) -> PamReturnCode {
80    From::from(unsafe { pam_setcred(handle, flags as c_int) })
81}
82
83#[inline]
84pub fn acct_mgmt(handle: &mut PamHandle, flags: PamFlag) -> PamReturnCode {
85    From::from(unsafe { pam_acct_mgmt(handle, flags as c_int) })
86}
87
88#[inline]
89pub fn open_session(handle: &mut PamHandle, flags: PamFlag) -> PamReturnCode {
90    From::from(unsafe { pam_open_session(handle, flags as c_int) })
91}
92
93#[inline]
94pub fn close_session(handle: &mut PamHandle, flags: PamFlag) -> PamReturnCode {
95    From::from(unsafe { pam_close_session(handle, flags as c_int) })
96}
97
98#[inline]
99pub fn chauthtok(handle: &mut PamHandle, flags: PamFlag) -> PamReturnCode {
100    From::from(unsafe { pam_chauthtok(handle, flags as c_int) })
101}
102/* ------------------------ pam_appl.h -------------------------- */
103
104/* ----------------------- _pam_types.h ------------------------- */
105#[inline]
106pub fn set_item(handle: &mut PamHandle, item_type: PamItemType, item: &c_void) -> PamReturnCode {
107    From::from(unsafe { pam_set_item(handle, item_type as c_int, item) })
108}
109
110#[inline]
111pub fn get_item(handle: &PamHandle,
112                item_type: PamItemType,
113                item: &mut *const c_void)
114                -> PamReturnCode {
115    From::from(unsafe { pam_get_item(handle, item_type as c_int, item) })
116}
117
118#[inline]
119pub fn strerror(handle: &mut PamHandle, errnum: PamReturnCode) -> Option<&str> {
120    unsafe { CStr::from_ptr(pam_strerror(handle, errnum as c_int)) }.to_str().ok()
121}
122
123#[inline]
124pub fn putenv(handle: &mut PamHandle, name_value: &str) -> PamReturnCode {
125    if let Ok(name_value) = CString::new(name_value) {
126        From::from(unsafe { pam_putenv(handle, name_value.as_ptr()) })
127    } else {
128        // Not sure whether this is the correct return value
129        PamReturnCode::BUF_ERR
130    }
131}
132
133#[inline]
134pub fn getenv<'a>(handle: &'a mut PamHandle, name: &str) -> Option<&'a str> {
135    use std::ptr;
136    if let Ok(name) = CString::new(name) {
137        let env = unsafe{pam_getenv(handle, name.as_ptr())};
138        if env != ptr::null(){
139            unsafe { CStr::from_ptr(env) }.to_str().ok()
140        }
141        else{
142            None
143        }
144    } else {
145        None
146    }
147}
148
149#[inline]
150pub fn getenvlist(handle: &mut PamHandle) -> *const *const c_char {
151    //TODO: find a convenient way to handle this with Rust types
152    unsafe { pam_getenvlist(handle) }
153}
154/* ----------------------- _pam_types.h ------------------------- */
155
156/* ----------------------- pam_misc.h --------------------------- */
157#[inline]
158#[cfg(target_os = "linux")]
159pub fn misc_paste_env(handle: &mut PamHandle, user_env: &[&str]) -> PamReturnCode {
160    // Taken from: https://github.com/rust-lang/rust/issues/9564#issuecomment-95354558
161    let user_env: Vec<_> = user_env.iter()
162        .map(|&env| CString::new(env).unwrap())
163        .collect();
164    let env_ptrs: Vec<_> = user_env.iter()
165        .map(|env| env.as_ptr())
166        .chain(Some(null()))
167        .collect();
168    From::from(unsafe { pam_misc_paste_env(handle, env_ptrs.as_ptr()) })
169}
170
171#[inline]
172#[cfg(target_os = "linux")]
173pub fn misc_drop_env(env: &mut *mut c_char) -> PamReturnCode {
174    From::from(unsafe { pam_misc_drop_env(env) })
175}
176
177#[inline]
178#[cfg(target_os = "linux")]
179pub fn misc_setenv(handle: &mut PamHandle,
180                   name: &str,
181                   value: &str,
182                   readonly: bool)
183                   -> PamReturnCode {
184    if let (Ok(name), Ok(value)) = (CString::new(name), CString::new(value)) {
185        From::from(unsafe {
186            pam_misc_setenv(handle,
187                            name.as_ptr(),
188                            value.as_ptr(),
189                            if readonly { 0 } else { 1 })
190        })
191    } else {
192        PamReturnCode::BUF_ERR
193    }
194}
195/* ----------------------- pam_misc.h --------------------------- */
196
197/* ----------------------- pam_modules.h ------------------------ */
198#[inline]
199pub fn set_data(handle: &mut PamHandle,
200                module_data_name: &str,
201                data: &mut c_void,
202                cleanup: Option<extern "C" fn(*mut PamHandle, *mut c_void, c_int)>)
203                -> PamReturnCode {
204    if let Ok(module_data_name) = CString::new(module_data_name) {
205        From::from(unsafe { pam_set_data(handle, module_data_name.as_ptr(), data, cleanup) })
206
207    } else {
208        PamReturnCode::BUF_ERR
209    }
210}
211
212//pub fn get_data(handle: *const PamHandle, module_data_name: *const c_char, data: *const *const c_void);
213
214pub fn get_user(handle: &PamHandle,
215                user: &mut *const c_char,
216                prompt: *const c_char)
217                -> PamReturnCode {
218                
219    From::from(
220        unsafe {
221            pam_get_user(
222                handle,
223                user,
224                prompt
225            )
226        }
227    )
228}
229
230/* ----------------------- pam_modules.h ------------------------ */