Skip to content

Commit

Permalink
Auto merge of #12518 - arlosi:cred-dlopen, r=epage
Browse files Browse the repository at this point in the history
cargo-credential-gnome-secret: dynamically load libsecret

Building `cargo-credential-gnome-secret` currently requires the `libsecret` development libraries to be installed and findable via `pkg-config`. This is often an extra step for users and complicates CI builds.

This loads the required functions from `libsecret` dynamically using `libloading` which uses `dlopen` internally.

Closes #12503

Testing this requires manually installing the credential provider on a system with libsecret set up. I tested it on Arch Linux.
  • Loading branch information
bors committed Aug 17, 2023
2 parents 9a35c0b + 627936b commit 937b930
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 36 deletions.
15 changes: 13 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ lazy_static = "1.4.0"
lazycell = "1.3.0"
libc = "0.2.147"
libgit2-sys = "0.15.2"
libloading = "0.8.0"
memchr = "2.5.0"
miow = "0.6.0"
opener = "0.6.1"
Expand Down
6 changes: 3 additions & 3 deletions credential/cargo-credential-gnome-secret/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
[package]
name = "cargo-credential-gnome-secret"
version = "0.3.0"
version = "0.3.1"
edition.workspace = true
license.workspace = true
repository = "https://github.com/rust-lang/cargo"
description = "A Cargo credential process that stores tokens with GNOME libsecret."

[dependencies]
anyhow.workspace = true
cargo-credential.workspace = true
libloading.workspace = true

[build-dependencies]
pkg-config.workspace = true
8 changes: 0 additions & 8 deletions credential/cargo-credential-gnome-secret/build.rs

This file was deleted.

66 changes: 43 additions & 23 deletions credential/cargo-credential-gnome-secret/src/libsecret.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
//! Implementation of the libsecret credential helper.
use anyhow::Context;
use cargo_credential::{
read_token, Action, CacheControl, Credential, CredentialResponse, Error, RegistryInfo, Secret,
};
use libloading::{Library, Symbol};
use std::ffi::{CStr, CString};
use std::os::raw::{c_char, c_int};
use std::ptr::{null, null_mut};
Expand Down Expand Up @@ -52,29 +54,27 @@ enum SecretSchemaAttributeType {
String = 0,
}

extern "C" {
fn secret_password_store_sync(
schema: *const SecretSchema,
collection: *const gchar,
label: *const gchar,
password: *const gchar,
cancellable: *mut GCancellable,
error: *mut *mut GError,
...
) -> gboolean;
fn secret_password_clear_sync(
schema: *const SecretSchema,
cancellable: *mut GCancellable,
error: *mut *mut GError,
...
) -> gboolean;
fn secret_password_lookup_sync(
schema: *const SecretSchema,
cancellable: *mut GCancellable,
error: *mut *mut GError,
...
) -> *mut gchar;
}
type SecretPasswordStoreSync = extern "C" fn(
schema: *const SecretSchema,
collection: *const gchar,
label: *const gchar,
password: *const gchar,
cancellable: *mut GCancellable,
error: *mut *mut GError,
...
) -> gboolean;
type SecretPasswordClearSync = extern "C" fn(
schema: *const SecretSchema,
cancellable: *mut GCancellable,
error: *mut *mut GError,
...
) -> gboolean;
type SecretPasswordLookupSync = extern "C" fn(
schema: *const SecretSchema,
cancellable: *mut GCancellable,
error: *mut *mut GError,
...
) -> *mut gchar;

pub struct GnomeSecret;

Expand Down Expand Up @@ -105,6 +105,26 @@ impl Credential for GnomeSecret {
action: &Action,
_args: &[&str],
) -> Result<CredentialResponse, Error> {
// Dynamically load libsecret to avoid users needing to install
// additional -dev packages when building this provider.
let lib;
let secret_password_lookup_sync: Symbol<SecretPasswordLookupSync>;
let secret_password_store_sync: Symbol<SecretPasswordStoreSync>;
let secret_password_clear_sync: Symbol<SecretPasswordClearSync>;
unsafe {
lib = Library::new("libsecret-1.so").context(
"failed to load libsecret: try installing the `libsecret` \
or `libsecret-1-0` package with the system package manager",
)?;
secret_password_lookup_sync = lib
.get(b"secret_password_lookup_sync\0")
.map_err(Box::new)?;
secret_password_store_sync =
lib.get(b"secret_password_store_sync\0").map_err(Box::new)?;
secret_password_clear_sync =
lib.get(b"secret_password_clear_sync\0").map_err(Box::new)?;
}

let index_url_c = CString::new(registry.index_url).unwrap();
match action {
cargo_credential::Action::Get(_) => {
Expand Down

0 comments on commit 937b930

Please sign in to comment.