Skip to main content

security/keychain/
mod.rs

1use crate::bridge;
2use crate::error::Result;
3
4#[derive(Debug, Clone, PartialEq, Eq, Hash)]
5pub struct KeychainEntry {
6    account: String,
7    service: String,
8}
9
10impl KeychainEntry {
11    pub fn new(account: impl Into<String>, service: impl Into<String>) -> Self {
12        Self {
13            account: account.into(),
14            service: service.into(),
15        }
16    }
17
18    pub fn account(&self) -> &str {
19        &self.account
20    }
21
22    pub fn service(&self) -> &str {
23        &self.service
24    }
25
26    pub fn set(&self, password: &str) -> Result<()> {
27        Keychain::set(&self.account, &self.service, password)
28    }
29
30    pub fn get(&self) -> Result<String> {
31        Keychain::get(&self.account, &self.service)
32    }
33
34    pub fn delete(&self) -> Result<()> {
35        Keychain::delete(&self.account, &self.service)
36    }
37}
38
39pub struct Keychain;
40
41impl Keychain {
42    pub fn entry(account: impl Into<String>, service: impl Into<String>) -> KeychainEntry {
43        KeychainEntry::new(account, service)
44    }
45
46    pub fn set(account: &str, service: &str, password: &str) -> Result<()> {
47        let account = bridge::cstring(account)?;
48        let service = bridge::cstring(service)?;
49        let password = bridge::cstring(password)?;
50        let mut error = std::ptr::null_mut();
51        let status = unsafe {
52            bridge::security_keychain_set_password(
53                account.as_ptr(),
54                service.as_ptr(),
55                password.as_ptr(),
56                &mut error,
57            )
58        };
59        bridge::status_result("security_keychain_set_password", status, error)
60    }
61
62    pub fn get(account: &str, service: &str) -> Result<String> {
63        let account = bridge::cstring(account)?;
64        let service = bridge::cstring(service)?;
65        let mut status = 0;
66        let mut error = std::ptr::null_mut();
67        let raw = unsafe {
68            bridge::security_keychain_get_password(
69                account.as_ptr(),
70                service.as_ptr(),
71                &mut status,
72                &mut error,
73            )
74        };
75        bridge::required_string("security_keychain_get_password", raw, status, error)
76    }
77
78    pub fn delete(account: &str, service: &str) -> Result<()> {
79        let account = bridge::cstring(account)?;
80        let service = bridge::cstring(service)?;
81        let mut error = std::ptr::null_mut();
82        let status = unsafe {
83            bridge::security_keychain_delete_password(account.as_ptr(), service.as_ptr(), &mut error)
84        };
85        bridge::status_result("security_keychain_delete_password", status, error)
86    }
87
88    pub fn list_accounts(service: &str) -> Result<Vec<String>> {
89        let service = bridge::cstring(service)?;
90        let mut status = 0;
91        let mut error = std::ptr::null_mut();
92        let raw = unsafe {
93            bridge::security_keychain_list_accounts(service.as_ptr(), &mut status, &mut error)
94        };
95        bridge::required_json("security_keychain_list_accounts", raw, status, error)
96    }
97}