|
1 | 1 | //! Implementation of the libsecret credential helper.
|
2 | 2 |
|
| 3 | +use anyhow::Context; |
3 | 4 | use cargo_credential::{
|
4 | 5 | read_token, Action, CacheControl, Credential, CredentialResponse, Error, RegistryInfo, Secret,
|
5 | 6 | };
|
| 7 | +use libloading::{Library, Symbol}; |
6 | 8 | use std::ffi::{CStr, CString};
|
7 | 9 | use std::os::raw::{c_char, c_int};
|
8 | 10 | use std::ptr::{null, null_mut};
|
@@ -52,29 +54,27 @@ enum SecretSchemaAttributeType {
|
52 | 54 | String = 0,
|
53 | 55 | }
|
54 | 56 |
|
55 |
| -extern "C" { |
56 |
| - fn secret_password_store_sync( |
57 |
| - schema: *const SecretSchema, |
58 |
| - collection: *const gchar, |
59 |
| - label: *const gchar, |
60 |
| - password: *const gchar, |
61 |
| - cancellable: *mut GCancellable, |
62 |
| - error: *mut *mut GError, |
63 |
| - ... |
64 |
| - ) -> gboolean; |
65 |
| - fn secret_password_clear_sync( |
66 |
| - schema: *const SecretSchema, |
67 |
| - cancellable: *mut GCancellable, |
68 |
| - error: *mut *mut GError, |
69 |
| - ... |
70 |
| - ) -> gboolean; |
71 |
| - fn secret_password_lookup_sync( |
72 |
| - schema: *const SecretSchema, |
73 |
| - cancellable: *mut GCancellable, |
74 |
| - error: *mut *mut GError, |
75 |
| - ... |
76 |
| - ) -> *mut gchar; |
77 |
| -} |
| 57 | +type SecretPasswordStoreSync = extern "C" fn( |
| 58 | + schema: *const SecretSchema, |
| 59 | + collection: *const gchar, |
| 60 | + label: *const gchar, |
| 61 | + password: *const gchar, |
| 62 | + cancellable: *mut GCancellable, |
| 63 | + error: *mut *mut GError, |
| 64 | + ... |
| 65 | +) -> gboolean; |
| 66 | +type SecretPasswordClearSync = extern "C" fn( |
| 67 | + schema: *const SecretSchema, |
| 68 | + cancellable: *mut GCancellable, |
| 69 | + error: *mut *mut GError, |
| 70 | + ... |
| 71 | +) -> gboolean; |
| 72 | +type SecretPasswordLookupSync = extern "C" fn( |
| 73 | + schema: *const SecretSchema, |
| 74 | + cancellable: *mut GCancellable, |
| 75 | + error: *mut *mut GError, |
| 76 | + ... |
| 77 | +) -> *mut gchar; |
78 | 78 |
|
79 | 79 | pub struct GnomeSecret;
|
80 | 80 |
|
@@ -105,6 +105,26 @@ impl Credential for GnomeSecret {
|
105 | 105 | action: &Action,
|
106 | 106 | _args: &[&str],
|
107 | 107 | ) -> Result<CredentialResponse, Error> {
|
| 108 | + // Dynamically load libsecret to avoid users needing to install |
| 109 | + // additional -dev packages when building this provider. |
| 110 | + let lib; |
| 111 | + let secret_password_lookup_sync: Symbol<SecretPasswordLookupSync>; |
| 112 | + let secret_password_store_sync: Symbol<SecretPasswordStoreSync>; |
| 113 | + let secret_password_clear_sync: Symbol<SecretPasswordClearSync>; |
| 114 | + unsafe { |
| 115 | + lib = Library::new("libsecret-1.so").context( |
| 116 | + "failed to load libsecret: try installing the `libsecret` \ |
| 117 | + or `libsecret-1-0` package with the system package manager", |
| 118 | + )?; |
| 119 | + secret_password_lookup_sync = lib |
| 120 | + .get(b"secret_password_lookup_sync\0") |
| 121 | + .map_err(Box::new)?; |
| 122 | + secret_password_store_sync = |
| 123 | + lib.get(b"secret_password_store_sync\0").map_err(Box::new)?; |
| 124 | + secret_password_clear_sync = |
| 125 | + lib.get(b"secret_password_clear_sync\0").map_err(Box::new)?; |
| 126 | + } |
| 127 | + |
108 | 128 | let index_url_c = CString::new(registry.index_url).unwrap();
|
109 | 129 | match action {
|
110 | 130 | cargo_credential::Action::Get(_) => {
|
|
0 commit comments