diff --git a/src/constants.rs b/src/constants.rs index d160387..4ca67ef 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -2,5 +2,5 @@ pub const BUSY_WAIT_TIME: std::time::Duration = std::time::Duration::from_secs(5); // The location of the keys DB relative to the user's home directory. -pub const KEYS_DB: &[ &str ] = &[ ".pEp", "keys.db" ]; +pub const KEYS_DB: &[ &str ] = &[ "keys.db" ]; diff --git a/src/keystore.rs b/src/keystore.rs index e826f69..90d4f3f 100644 --- a/src/keystore.rs +++ b/src/keystore.rs @@ -1,5 +1,6 @@ use std::cmp; use std::env; +use std::path::Path; use std::path::PathBuf; use rusqlite::{ @@ -157,8 +158,10 @@ impl Keystore { /// Initializes the key store. /// /// This opens the keys.db and initializes it, if necessary. - pub fn init() -> Result { - Self::init_(false) + pub fn init

(dir: P) -> Result + where P: AsRef + { + Self::init_(Some(dir.as_ref())) } /// Initializes an in-memory key store. @@ -166,45 +169,22 @@ impl Keystore { /// This is used for the unit tests. #[cfg(test)] pub(crate) fn init_in_memory() -> Result { - Self::init_(true) + Self::init_(None) } - fn init_(in_memory: bool) -> Result { - let keys_db = PathBuf::new(); + fn init_(home: Option<&Path>) -> Result { + let mut keys_db = PathBuf::new(); - let conn = if in_memory { - wrap_err!( - Connection::open_in_memory(), - InitCannotOpenDB, - "Creating in-memory keys DB")? - } else { - let mut home: Option = None; + let conn = if let Some(home) = home { + keys_db.push(home); - // Create the home directory. #[cfg(not(windows))] - { - if cfg!(debug_assertions) { - home = env::var("PEP_HOME").ok().map(|s| PathBuf::from(s)); - } - #[allow(deprecated)] - if home.is_none() { - home = env::home_dir(); + if cfg!(debug_assertions) { + if let Ok(pep_home) = env::var("PEP_HOME") { + keys_db = PathBuf::from(pep_home); } } - #[cfg(windows)] - { - // Get the home directory on Windows. - unimplemented!(); - } - - let home = match home { - None => return Err(Error::InitCryptoLibInitFailed( - "HOME environment variable unset".into()).into()), - Some(home) => home, - }; - - let mut keys_db = home; for n in KEYS_DB { keys_db.push(n); } @@ -218,6 +198,12 @@ impl Keystore { | OpenFlags::SQLITE_OPEN_PRIVATE_CACHE), InitCannotOpenDB, format!("Opening keys DB ('{}')", keys_db.display()))? + } else { + // Create an in-memory DB. + wrap_err!( + Connection::open_in_memory(), + InitCannotOpenDB, + "Creating in-memory keys DB")? }; wrap_err!( diff --git a/src/lib.rs b/src/lib.rs index cc1afa9..ba8043e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,12 +1,16 @@ use std::cmp; use std::convert::TryInto; use std::env; -use std::ffi::CStr; +use std::ffi::{ + CStr, + OsStr, +}; use std::io::{ Read, Write, }; use std::mem; +use std::path::Path; use std::ptr; use std::slice; use std::time::{ @@ -197,6 +201,7 @@ fn _pgp_get_decrypted_key_iter<'a, I>(iter: I, pass: Option<&Password>) // PEP_STATUS pgp_init(PEP_SESSION session, bool in_first) ffi!(fn pgp_init_(session: *mut Session, _in_first: bool, + per_user_directory: *const c_char, session_size: c_uint, session_cookie_offset: c_uint, session_curr_passphrase_offset: c_uint, @@ -241,7 +246,27 @@ ffi!(fn pgp_init_(session: *mut Session, _in_first: bool, let session = Session::as_mut(session); - let ks = keystore::Keystore::init()?; + if per_user_directory.is_null() { + return Err(Error::IllegalValue( + "per_user_directory may not be NULL".into())); + } + let per_user_directory = unsafe { CStr::from_ptr(per_user_directory) }; + + #[cfg(not(windows))] + let per_user_directory = { + use std::os::unix::ffi::OsStrExt; + OsStr::from_bytes(per_user_directory.to_bytes()) + }; + #[cfg(windows)] + let per_user_directory = { + use std::ffi::OsString; + use std::os::windows::prelude::*; + + let os_string = OsString::from_wide(per_user_directory.as_bytes()); + os_string.as_os_str() + }; + + let ks = keystore::Keystore::init(Path::new(per_user_directory))?; session.set_keystore(ks); Ok(())