├── NEWS.md ├── LICENSE ├── .gitignore ├── tests ├── testthat.R └── testthat │ └── test.R ├── .Rbuildignore ├── NAMESPACE ├── R ├── utils.R ├── RcppExports.R └── keyring.R ├── .travis.yml ├── appveyor.yml ├── DESCRIPTION ├── src ├── keytar.h ├── keytar_win.cc ├── keytar_posix.cc ├── main.cc ├── RcppExports.cpp └── keytar_mac.cc └── README.md /NEWS.md: -------------------------------------------------------------------------------- 1 | 2 | # 1.0.0 3 | 4 | First public release. 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | YEAR: 2016 2 | COPYRIGHT HOLDER: GitHub Inc., Mango Solutions 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .Rproj.user 2 | .Rhistory 3 | .RData 4 | /src/*.o 5 | /src/keyring.so 6 | -------------------------------------------------------------------------------- /tests/testthat.R: -------------------------------------------------------------------------------- 1 | library(testthat) 2 | library(keyring) 3 | 4 | test_check("keyring") 5 | -------------------------------------------------------------------------------- /.Rbuildignore: -------------------------------------------------------------------------------- 1 | ^.*\.Rproj$ 2 | ^\.Rproj\.user$ 3 | ^Makefile$ 4 | ^README.Rmd$ 5 | ^.travis.yml$ 6 | ^appveyor.yml$ 7 | -------------------------------------------------------------------------------- /tests/testthat/test.R: -------------------------------------------------------------------------------- 1 | 2 | context("keyring") 3 | 4 | test_that("keyring works", { 5 | 6 | expect_true(TRUE) 7 | 8 | }) 9 | -------------------------------------------------------------------------------- /NAMESPACE: -------------------------------------------------------------------------------- 1 | # Generated by roxygen2: do not edit by hand 2 | 3 | export(add_password) 4 | export(delete_password) 5 | export(find_password) 6 | export(get_password) 7 | useDynLib(keyring) 8 | -------------------------------------------------------------------------------- /R/utils.R: -------------------------------------------------------------------------------- 1 | 2 | is_string <- function(x) { 3 | is.character(x) && length(x) == 1 && !is.na(x) 4 | } 5 | 6 | is_count <- function(x) { 7 | is.numeric(x) && length(x) == 1 && !is.na(x) && as.integer(x) == x 8 | } 9 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | ## Sample .travis.yml file for use with metacran/r-builder 2 | ## See https://github.com/metacran/r-builder for details. 3 | 4 | language: c 5 | sudo: required 6 | 7 | before_install: 8 | - sudo apt-get update && sudo apt-get -y install libgnome-keyring-dev 9 | - curl -OL https://raw.githubusercontent.com/metacran/r-builder/master/pkg-build.sh 10 | - chmod 755 pkg-build.sh 11 | - ./pkg-build.sh bootstrap 12 | 13 | install: 14 | - ./pkg-build.sh install_deps 15 | 16 | script: 17 | - ./pkg-build.sh run_tests 18 | 19 | after_failure: 20 | - ./pkg-build.sh dump_logs 21 | 22 | notifications: 23 | email: 24 | on_success: change 25 | on_failure: change 26 | 27 | env: 28 | matrix: 29 | - RVERSION=oldrel 30 | - RVERSION=release 31 | - RVERSION=devel 32 | 33 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | # DO NOT CHANGE the "init" and "install" sections below 2 | 3 | # Download script file from GitHub 4 | init: 5 | ps: | 6 | $ErrorActionPreference = "Stop" 7 | Invoke-WebRequest http://raw.github.com/krlmlr/r-appveyor/master/scripts/appveyor-tool.ps1 -OutFile "..\appveyor-tool.ps1" 8 | Import-Module '..\appveyor-tool.ps1' 9 | 10 | install: 11 | ps: Bootstrap 12 | 13 | # Adapt as necessary starting from here 14 | 15 | build_script: 16 | - travis-tool.sh install_deps 17 | 18 | test_script: 19 | - travis-tool.sh run_tests 20 | 21 | on_failure: 22 | - travis-tool.sh dump_logs 23 | 24 | artifacts: 25 | - path: '*.Rcheck\**\*.log' 26 | name: Logs 27 | 28 | - path: '*.Rcheck\**\*.out' 29 | name: Logs 30 | 31 | - path: '*.Rcheck\**\*.fail' 32 | name: Logs 33 | 34 | - path: '*.Rcheck\**\*.Rout' 35 | name: Logs 36 | 37 | - path: '\*_*.tar.gz' 38 | name: Bits 39 | 40 | - path: '\*_*.zip' 41 | name: Bits 42 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: keyring 2 | Title: Access the System Keyring from R 3 | Version: 1.0.0 4 | Author: Gabor Csardi, Kevin Sawicki, Cheng Zhao, Paul Betts, 5 | Johannes Jörg Schmidt, Peter Dave Hello, Robin Mehner, Machisté N. Quintana 6 | Maintainer: Gabor Csardi 7 | Copyright: GitHub Inc., Mango Solutions 8 | Description: Modern OSes store passwords, and other confidential information in 9 | a keyring with a master password. This package allows access to the keyring of 10 | the OS from R. It supports Windows, Mac OS X and Linux systems. The C++ source 11 | code is based on the 'keytar' project: . 12 | License: MIT + file LICENSE 13 | LazyData: true 14 | URL: https://github.com/mangothecat/keyring 15 | BugReports: https://github.com/mangothecat/keyring/issues 16 | LinkingTo: Rcpp 17 | Imports: 18 | Rcpp 19 | Suggests: 20 | testthat 21 | RoxygenNote: 5.0.1 22 | Encoding: UTF-8 23 | SystemRequirements: gnome-keyring library (libgnome-keyring-dev package on Ubunutu) 24 | -------------------------------------------------------------------------------- /src/keytar.h: -------------------------------------------------------------------------------- 1 | #ifndef SRC_KEYTAR_H_ 2 | #define SRC_KEYTAR_H_ 3 | 4 | #include 5 | 6 | namespace keytar { 7 | 8 | bool AddPassword(const std::string& service, 9 | const std::string& account, 10 | const std::string& password); 11 | 12 | bool GetPassword(const std::string& service, 13 | const std::string& account, 14 | std::string* password); 15 | 16 | bool DeletePassword(const std::string& service, 17 | const std::string& account); 18 | 19 | bool FindPassword(const std::string& service, std::string* password); 20 | 21 | bool AddInternetPassword(const std::string& servername, 22 | const std::string& account, 23 | int port, 24 | const std::string& password); 25 | 26 | bool GetInternetPassword(const std::string& servername, 27 | const std::string& account, 28 | int port, 29 | std::string* password); 30 | 31 | bool DeleteInternetPassword(const std::string& servername, 32 | const std::string& account, 33 | int port); 34 | 35 | bool FindInternetPassword(const std::string& servername, 36 | int port, 37 | std::string* password); 38 | 39 | } // namespace keytar 40 | 41 | #endif // SRC_KEYTAR_H_ 42 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # keyring 3 | 4 | [![Project Status: WIP - Initial development is in progress, but there has not yet been a stable, usable release suitable for the public.](http://www.repostatus.org/badges/latest/wip.svg)](http://www.repostatus.org/#wip) 5 | 6 | > Access the System Keyring from R 7 | 8 | [![Linux Build Status](https://travis-ci.org/MangoTheCat/keyring.svg?branch=master)](https://travis-ci.org/MangoTheCat/keyring) 9 | [![Windows Build status](https://ci.appveyor.com/api/projects/status/github/MangoTheCat/keyring?svg=true)](https://ci.appveyor.com/project/gaborcsardi/keyring) 10 | [![](http://www.r-pkg.org/badges/version/keyring)](http://www.r-pkg.org/pkg/keyring) 11 | [![CRAN RStudio mirror downloads](http://cranlogs.r-pkg.org/badges/keyring)](http://www.r-pkg.org/pkg/keyring) 12 | 13 | 14 | Modern OSes store passwords, and other confidential information in a 15 | keyring with a master password. This package allows access to the keyring 16 | of the OS from R. It supports Windows, Mac OS X and Linux systems. 17 | 18 | ## Installation 19 | 20 | ```r 21 | devtools::install_github("mangothecat/keyring") 22 | ``` 23 | 24 | ## Usage 25 | 26 | ```r 27 | library(keyring) 28 | ``` 29 | 30 | ## License 31 | 32 | MIT © [Mango Solutions](https://github.com/mangothecat). 33 | -------------------------------------------------------------------------------- /R/RcppExports.R: -------------------------------------------------------------------------------- 1 | # Generated by using Rcpp::compileAttributes() -> do not edit by hand 2 | # Generator token: 10BE3573-1514-4C36-9D1C-5A225CD40393 3 | 4 | R_AddPassword <- function(service, account, password) { 5 | .Call('keyring_R_AddPassword', PACKAGE = 'keyring', service, account, password) 6 | } 7 | 8 | R_GetPassword <- function(service, account) { 9 | .Call('keyring_R_GetPassword', PACKAGE = 'keyring', service, account) 10 | } 11 | 12 | R_DeletePassword <- function(service, account) { 13 | .Call('keyring_R_DeletePassword', PACKAGE = 'keyring', service, account) 14 | } 15 | 16 | R_FindPassword <- function(service) { 17 | .Call('keyring_R_FindPassword', PACKAGE = 'keyring', service) 18 | } 19 | 20 | R_AddInternetPassword <- function(servername, account, port, password) { 21 | .Call('keyring_R_AddInternetPassword', PACKAGE = 'keyring', servername, account, port, password) 22 | } 23 | 24 | R_GetInternetPassword <- function(servername, account, port) { 25 | .Call('keyring_R_GetInternetPassword', PACKAGE = 'keyring', servername, account, port) 26 | } 27 | 28 | R_DeleteInternetPassword <- function(servername, account, port) { 29 | .Call('keyring_R_DeleteInternetPassword', PACKAGE = 'keyring', servername, account, port) 30 | } 31 | 32 | R_FindInternetPassword <- function(servername, port) { 33 | .Call('keyring_R_FindInternetPassword', PACKAGE = 'keyring', servername, port) 34 | } 35 | 36 | -------------------------------------------------------------------------------- /src/keytar_win.cc: -------------------------------------------------------------------------------- 1 | 2 | #ifdef _WIN32 3 | 4 | #include "keytar.h" 5 | 6 | #include 7 | #include 8 | 9 | namespace keytar { 10 | 11 | bool AddPassword(const std::string& service, 12 | const std::string& account, 13 | const std::string& password) { 14 | std::string target_name = service + '/' + account; 15 | 16 | CREDENTIAL cred = { 0 }; 17 | cred.Type = CRED_TYPE_GENERIC; 18 | cred.TargetName = const_cast(target_name.c_str()); 19 | cred.CredentialBlobSize = password.size(); 20 | cred.CredentialBlob = (LPBYTE)(password.data()); 21 | cred.Persist = CRED_PERSIST_LOCAL_MACHINE; 22 | 23 | return ::CredWrite(&cred, 0) == TRUE; 24 | } 25 | 26 | bool GetPassword(const std::string& service, 27 | const std::string& account, 28 | std::string* password) { 29 | std::string target_name = service + '/' + account; 30 | 31 | CREDENTIAL* cred; 32 | if (::CredRead(target_name.c_str(), CRED_TYPE_GENERIC, 0, &cred) == FALSE) 33 | return false; 34 | 35 | *password = std::string(reinterpret_cast(cred->CredentialBlob), 36 | cred->CredentialBlobSize); 37 | ::CredFree(cred); 38 | return true; 39 | } 40 | 41 | bool DeletePassword(const std::string& service, const std::string& account) { 42 | std::string target_name = service + '/' + account; 43 | 44 | return ::CredDelete(target_name.c_str(), CRED_TYPE_GENERIC, 0) == TRUE; 45 | } 46 | 47 | bool FindPassword(const std::string& service, std::string* password) { 48 | std::string filter = service + "*"; 49 | 50 | DWORD count; 51 | CREDENTIAL** creds; 52 | if (::CredEnumerate(filter.c_str(), 0, &count, &creds) == FALSE) 53 | return false; 54 | 55 | *password = std::string(reinterpret_cast(creds[0]->CredentialBlob), 56 | creds[0]->CredentialBlobSize); 57 | ::CredFree(creds); 58 | return true; 59 | } 60 | 61 | } // namespace keytar 62 | 63 | #endif 64 | -------------------------------------------------------------------------------- /R/keyring.R: -------------------------------------------------------------------------------- 1 | 2 | #' @useDynLib keyring 3 | NULL 4 | 5 | #' @export 6 | 7 | add_password <- function(service, account, password) { 8 | stopifnot( 9 | is_string(service), 10 | is_string(account), 11 | is_string(password) 12 | ) 13 | 14 | R_AddPassword(service, account, password) 15 | } 16 | 17 | #' @export 18 | 19 | get_password <- function(service, account) { 20 | stopifnot( 21 | is_string(service), 22 | is_string(account) 23 | ) 24 | 25 | R_GetPassword(service, account) 26 | } 27 | 28 | #' @export 29 | 30 | delete_password <- function(service, account) { 31 | stopifnot( 32 | is_string(service), 33 | is_string(account) 34 | ) 35 | 36 | R_DeletePassword(service, account) 37 | } 38 | 39 | #' @export 40 | 41 | find_password <- function(service) { 42 | stopifnot( 43 | is_string(service) 44 | ) 45 | 46 | R_FindPassword(service) 47 | } 48 | 49 | ## ------------------------------------------------------------------- 50 | 51 | #' @export 52 | 53 | add_internet_password <- function(servername, account, password, port = 0) { 54 | stopifnot( 55 | is_string(servername), 56 | is_string(account), 57 | is_string(password), 58 | is_count(port) 59 | ) 60 | 61 | R_AddInternetPassword(servername, account, port, password) 62 | } 63 | 64 | #' @export 65 | 66 | get_internet_password <- function(servername, account, port = 0) { 67 | stopifnot( 68 | is_string(servername), 69 | is_string(account), 70 | is_count(port) 71 | ) 72 | 73 | R_GetInternetPassword(servername, account, port) 74 | } 75 | 76 | #' @export 77 | 78 | delete_internet_password <- function(servername, account, port = 0) { 79 | stopifnot( 80 | is_string(servername), 81 | is_string(account), 82 | is_count(port) 83 | ) 84 | 85 | R_DeleteInternetPassword(servername, account, port) 86 | } 87 | 88 | #' @export 89 | 90 | find_internet_password <- function(servername, port = 0) { 91 | stopifnot( 92 | is_string(servername), 93 | is_count(port) 94 | ) 95 | 96 | R_FindInternetPassword(servername, port) 97 | } 98 | -------------------------------------------------------------------------------- /src/keytar_posix.cc: -------------------------------------------------------------------------------- 1 | 2 | #ifdef __linux__ 3 | 4 | #include "keytar.h" 5 | 6 | #include 7 | #include 8 | 9 | namespace keytar { 10 | 11 | namespace { 12 | 13 | const GnomeKeyringPasswordSchema kGnomeSchema = { 14 | GNOME_KEYRING_ITEM_GENERIC_SECRET, { 15 | { "service", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING }, 16 | { "account", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING }, 17 | { NULL } 18 | } 19 | }; 20 | 21 | } // namespace 22 | 23 | bool AddPassword(const std::string& service, 24 | const std::string& account, 25 | const std::string& password) { 26 | GnomeKeyringResult result = gnome_keyring_store_password_sync( 27 | &kGnomeSchema, 28 | NULL, // Default keyring. 29 | (service + "/" + account).c_str(), // Display name. 30 | password.c_str(), 31 | "service", service.c_str(), 32 | "account", account.c_str(), 33 | NULL); 34 | return result == GNOME_KEYRING_RESULT_OK; 35 | } 36 | 37 | bool GetPassword(const std::string& service, 38 | const std::string& account, 39 | std::string* password) { 40 | gchar* raw_passwords; 41 | GnomeKeyringResult result = gnome_keyring_find_password_sync( 42 | &kGnomeSchema, 43 | &raw_passwords, 44 | "service", service.c_str(), 45 | "account", account.c_str(), 46 | NULL); 47 | if (result != GNOME_KEYRING_RESULT_OK) 48 | return false; 49 | 50 | if (raw_passwords != NULL) 51 | *password = raw_passwords; 52 | gnome_keyring_free_password(raw_passwords); 53 | return true; 54 | } 55 | 56 | bool DeletePassword(const std::string& service, const std::string& account) { 57 | return gnome_keyring_delete_password_sync( 58 | &kGnomeSchema, 59 | "service", service.c_str(), 60 | "account", account.c_str(), 61 | NULL) == GNOME_KEYRING_RESULT_OK; 62 | } 63 | 64 | bool FindPassword(const std::string& service, std::string* password) { 65 | gchar* raw_passwords; 66 | GnomeKeyringResult result = gnome_keyring_find_password_sync( 67 | &kGnomeSchema, 68 | &raw_passwords, 69 | "service", service.c_str(), 70 | NULL); 71 | if (result != GNOME_KEYRING_RESULT_OK) 72 | return false; 73 | 74 | if (raw_passwords != NULL) 75 | *password = raw_passwords; 76 | gnome_keyring_free_password(raw_passwords); 77 | return true; 78 | } 79 | 80 | } // namespace keytar 81 | 82 | #endif 83 | -------------------------------------------------------------------------------- /src/main.cc: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | using namespace Rcpp; 4 | 5 | #include "keytar.h" 6 | 7 | // [[Rcpp::export]] 8 | SEXP R_AddPassword(const std::string& service, 9 | const std::string& account, 10 | const std::string& password) { 11 | 12 | return Rcpp::wrap(keytar::AddPassword(service, account, password)); 13 | } 14 | 15 | // [[Rcpp::export]] 16 | SEXP R_GetPassword(const std::string& service, 17 | const std::string& account) { 18 | std::string password; 19 | bool result = keytar::GetPassword(service, account, &password); 20 | if (!result) stop("Cannot find password"); 21 | return Rcpp::wrap(password); 22 | } 23 | 24 | 25 | // [[Rcpp::export]] 26 | SEXP R_DeletePassword(const std::string& service, 27 | const std::string& account) { 28 | 29 | return Rcpp::wrap(keytar::DeletePassword(service, account)); 30 | } 31 | 32 | // [[Rcpp::export]] 33 | SEXP R_FindPassword(const std::string& service) { 34 | 35 | std::string password; 36 | bool result = keytar::FindPassword(service, &password); 37 | if (!result) stop("Cannot find password"); 38 | return Rcpp::wrap(password); 39 | } 40 | 41 | // --------------------------------------------------------------------- 42 | 43 | // [[Rcpp::export]] 44 | SEXP R_AddInternetPassword(const std::string& servername, 45 | const std::string& account, 46 | int port, 47 | const std::string& password) { 48 | 49 | return Rcpp::wrap(keytar::AddInternetPassword(servername, account, port, 50 | password)); 51 | } 52 | 53 | // [[Rcpp::export]] 54 | SEXP R_GetInternetPassword(const std::string& servername, 55 | const std::string& account, 56 | int port) { 57 | 58 | std::string password; 59 | bool result = keytar::GetInternetPassword(servername, account, port, 60 | &password); 61 | if (!result) stop("Cannot find password"); 62 | return Rcpp::wrap(password); 63 | } 64 | 65 | // [[Rcpp::export]] 66 | SEXP R_DeleteInternetPassword(const std::string& servername, 67 | const std::string& account, 68 | int port) { 69 | 70 | return Rcpp::wrap(keytar::DeleteInternetPassword(servername, account, 71 | port)); 72 | } 73 | 74 | // [[Rcpp::export]] 75 | SEXP R_FindInternetPassword(const std::string& servername, 76 | int port) { 77 | 78 | std::string password; 79 | bool result = keytar::FindInternetPassword(servername, port, &password); 80 | if (!result) stop("Cannot find password"); 81 | return Rcpp::wrap(password); 82 | } 83 | -------------------------------------------------------------------------------- /src/RcppExports.cpp: -------------------------------------------------------------------------------- 1 | // Generated by using Rcpp::compileAttributes() -> do not edit by hand 2 | // Generator token: 10BE3573-1514-4C36-9D1C-5A225CD40393 3 | 4 | #include 5 | 6 | using namespace Rcpp; 7 | 8 | // R_AddPassword 9 | SEXP R_AddPassword(const std::string& service, const std::string& account, const std::string& password); 10 | RcppExport SEXP keyring_R_AddPassword(SEXP serviceSEXP, SEXP accountSEXP, SEXP passwordSEXP) { 11 | BEGIN_RCPP 12 | Rcpp::RObject rcpp_result_gen; 13 | Rcpp::RNGScope rcpp_rngScope_gen; 14 | Rcpp::traits::input_parameter< const std::string& >::type service(serviceSEXP); 15 | Rcpp::traits::input_parameter< const std::string& >::type account(accountSEXP); 16 | Rcpp::traits::input_parameter< const std::string& >::type password(passwordSEXP); 17 | rcpp_result_gen = Rcpp::wrap(R_AddPassword(service, account, password)); 18 | return rcpp_result_gen; 19 | END_RCPP 20 | } 21 | // R_GetPassword 22 | SEXP R_GetPassword(const std::string& service, const std::string& account); 23 | RcppExport SEXP keyring_R_GetPassword(SEXP serviceSEXP, SEXP accountSEXP) { 24 | BEGIN_RCPP 25 | Rcpp::RObject rcpp_result_gen; 26 | Rcpp::RNGScope rcpp_rngScope_gen; 27 | Rcpp::traits::input_parameter< const std::string& >::type service(serviceSEXP); 28 | Rcpp::traits::input_parameter< const std::string& >::type account(accountSEXP); 29 | rcpp_result_gen = Rcpp::wrap(R_GetPassword(service, account)); 30 | return rcpp_result_gen; 31 | END_RCPP 32 | } 33 | // R_DeletePassword 34 | SEXP R_DeletePassword(const std::string& service, const std::string& account); 35 | RcppExport SEXP keyring_R_DeletePassword(SEXP serviceSEXP, SEXP accountSEXP) { 36 | BEGIN_RCPP 37 | Rcpp::RObject rcpp_result_gen; 38 | Rcpp::RNGScope rcpp_rngScope_gen; 39 | Rcpp::traits::input_parameter< const std::string& >::type service(serviceSEXP); 40 | Rcpp::traits::input_parameter< const std::string& >::type account(accountSEXP); 41 | rcpp_result_gen = Rcpp::wrap(R_DeletePassword(service, account)); 42 | return rcpp_result_gen; 43 | END_RCPP 44 | } 45 | // R_FindPassword 46 | SEXP R_FindPassword(const std::string& service); 47 | RcppExport SEXP keyring_R_FindPassword(SEXP serviceSEXP) { 48 | BEGIN_RCPP 49 | Rcpp::RObject rcpp_result_gen; 50 | Rcpp::RNGScope rcpp_rngScope_gen; 51 | Rcpp::traits::input_parameter< const std::string& >::type service(serviceSEXP); 52 | rcpp_result_gen = Rcpp::wrap(R_FindPassword(service)); 53 | return rcpp_result_gen; 54 | END_RCPP 55 | } 56 | // R_AddInternetPassword 57 | SEXP R_AddInternetPassword(const std::string& servername, const std::string& account, int port, const std::string& password); 58 | RcppExport SEXP keyring_R_AddInternetPassword(SEXP servernameSEXP, SEXP accountSEXP, SEXP portSEXP, SEXP passwordSEXP) { 59 | BEGIN_RCPP 60 | Rcpp::RObject rcpp_result_gen; 61 | Rcpp::RNGScope rcpp_rngScope_gen; 62 | Rcpp::traits::input_parameter< const std::string& >::type servername(servernameSEXP); 63 | Rcpp::traits::input_parameter< const std::string& >::type account(accountSEXP); 64 | Rcpp::traits::input_parameter< int >::type port(portSEXP); 65 | Rcpp::traits::input_parameter< const std::string& >::type password(passwordSEXP); 66 | rcpp_result_gen = Rcpp::wrap(R_AddInternetPassword(servername, account, port, password)); 67 | return rcpp_result_gen; 68 | END_RCPP 69 | } 70 | // R_GetInternetPassword 71 | SEXP R_GetInternetPassword(const std::string& servername, const std::string& account, int port); 72 | RcppExport SEXP keyring_R_GetInternetPassword(SEXP servernameSEXP, SEXP accountSEXP, SEXP portSEXP) { 73 | BEGIN_RCPP 74 | Rcpp::RObject rcpp_result_gen; 75 | Rcpp::RNGScope rcpp_rngScope_gen; 76 | Rcpp::traits::input_parameter< const std::string& >::type servername(servernameSEXP); 77 | Rcpp::traits::input_parameter< const std::string& >::type account(accountSEXP); 78 | Rcpp::traits::input_parameter< int >::type port(portSEXP); 79 | rcpp_result_gen = Rcpp::wrap(R_GetInternetPassword(servername, account, port)); 80 | return rcpp_result_gen; 81 | END_RCPP 82 | } 83 | // R_DeleteInternetPassword 84 | SEXP R_DeleteInternetPassword(const std::string& servername, const std::string& account, int port); 85 | RcppExport SEXP keyring_R_DeleteInternetPassword(SEXP servernameSEXP, SEXP accountSEXP, SEXP portSEXP) { 86 | BEGIN_RCPP 87 | Rcpp::RObject rcpp_result_gen; 88 | Rcpp::RNGScope rcpp_rngScope_gen; 89 | Rcpp::traits::input_parameter< const std::string& >::type servername(servernameSEXP); 90 | Rcpp::traits::input_parameter< const std::string& >::type account(accountSEXP); 91 | Rcpp::traits::input_parameter< int >::type port(portSEXP); 92 | rcpp_result_gen = Rcpp::wrap(R_DeleteInternetPassword(servername, account, port)); 93 | return rcpp_result_gen; 94 | END_RCPP 95 | } 96 | // R_FindInternetPassword 97 | SEXP R_FindInternetPassword(const std::string& servername, int port); 98 | RcppExport SEXP keyring_R_FindInternetPassword(SEXP servernameSEXP, SEXP portSEXP) { 99 | BEGIN_RCPP 100 | Rcpp::RObject rcpp_result_gen; 101 | Rcpp::RNGScope rcpp_rngScope_gen; 102 | Rcpp::traits::input_parameter< const std::string& >::type servername(servernameSEXP); 103 | Rcpp::traits::input_parameter< int >::type port(portSEXP); 104 | rcpp_result_gen = Rcpp::wrap(R_FindInternetPassword(servername, port)); 105 | return rcpp_result_gen; 106 | END_RCPP 107 | } 108 | -------------------------------------------------------------------------------- /src/keytar_mac.cc: -------------------------------------------------------------------------------- 1 | 2 | #ifdef __APPLE__ 3 | 4 | #include "keytar.h" 5 | 6 | #include 7 | 8 | namespace keytar { 9 | 10 | bool AddPassword(const std::string& service, 11 | const std::string& account, 12 | const std::string& password) { 13 | OSStatus status = SecKeychainAddGenericPassword(NULL, 14 | service.length(), 15 | service.data(), 16 | account.length(), 17 | account.data(), 18 | password.length(), 19 | password.data(), 20 | NULL); 21 | return status == errSecSuccess; 22 | } 23 | 24 | bool GetPassword(const std::string& service, 25 | const std::string& account, 26 | std::string* password) { 27 | void *data; 28 | UInt32 length; 29 | OSStatus status = SecKeychainFindGenericPassword(NULL, 30 | service.length(), 31 | service.data(), 32 | account.length(), 33 | account.data(), 34 | &length, 35 | &data, 36 | NULL); 37 | if (status != errSecSuccess) 38 | return false; 39 | 40 | *password = std::string(reinterpret_cast(data), length); 41 | SecKeychainItemFreeContent(NULL, data); 42 | return true; 43 | } 44 | 45 | bool DeletePassword(const std::string& service, const std::string& account) { 46 | SecKeychainItemRef item; 47 | OSStatus status = SecKeychainFindGenericPassword(NULL, 48 | service.length(), 49 | service.data(), 50 | account.length(), 51 | account.data(), 52 | NULL, 53 | NULL, 54 | &item); 55 | if (status != errSecSuccess) 56 | return false; 57 | 58 | status = SecKeychainItemDelete(item); 59 | CFRelease(item); 60 | return status == errSecSuccess; 61 | } 62 | 63 | bool FindPassword(const std::string& service, std::string* password) { 64 | SecKeychainItemRef item; 65 | void *data; 66 | UInt32 length; 67 | 68 | OSStatus status = SecKeychainFindGenericPassword(NULL, 69 | service.length(), 70 | service.data(), 71 | 0, 72 | NULL, 73 | &length, 74 | &data, 75 | &item); 76 | if (status != errSecSuccess) 77 | return false; 78 | 79 | *password = std::string(reinterpret_cast(data), length); 80 | SecKeychainItemFreeContent(NULL, data); 81 | CFRelease(item); 82 | return true; 83 | } 84 | 85 | // --------------------------------------------------------------------- 86 | // Internet passwords 87 | 88 | bool AddInternetPassword(const std::string& servername, 89 | const std::string& account, 90 | int port, 91 | const std::string& password) { 92 | 93 | OSStatus status = SecKeychainAddInternetPassword 94 | (NULL, // keychain 95 | servername.length(), 96 | servername.data(), 97 | 0, NULL, // securityDomain 98 | account.length(), 99 | account.data(), 100 | 0, NULL, // path 101 | port, 102 | kSecProtocolTypeAny, 103 | kSecAuthenticationTypeAny, 104 | password.length(), 105 | password.data(), 106 | NULL); 107 | 108 | return status == errSecSuccess; 109 | } 110 | 111 | bool GetInternetPassword(const std::string& servername, 112 | const std::string& account, 113 | int port, 114 | std::string* password) { 115 | 116 | void *data; 117 | UInt32 length; 118 | 119 | OSStatus status = SecKeychainFindInternetPassword 120 | (NULL, // keychain 121 | servername.length(), 122 | servername.data(), 123 | 0, NULL, // securityDomain 124 | account.length(), 125 | account.data(), 126 | 0, NULL, // path 127 | port, 128 | kSecProtocolTypeAny, 129 | kSecAuthenticationTypeAny, 130 | &length, 131 | &data, 132 | NULL); 133 | 134 | if (status != errSecSuccess) 135 | return false; 136 | 137 | *password = std::string(reinterpret_cast(data), length); 138 | SecKeychainItemFreeContent(NULL, data); 139 | return true; 140 | } 141 | 142 | bool DeleteInternetPassword(const std::string& servername, 143 | const std::string& account, 144 | int port) { 145 | 146 | SecKeychainItemRef item; 147 | 148 | OSStatus status = SecKeychainFindInternetPassword 149 | (NULL, // keychain 150 | servername.length(), 151 | servername.data(), 152 | 0, NULL, // securityDomain 153 | account.length(), 154 | account.data(), 155 | 0, NULL, // path 156 | port, 157 | kSecProtocolTypeAny, 158 | kSecAuthenticationTypeAny, 159 | NULL, 160 | NULL, 161 | &item); 162 | 163 | if (status != errSecSuccess) 164 | return false; 165 | 166 | status = SecKeychainItemDelete(item); 167 | CFRelease(item); 168 | return status == errSecSuccess; 169 | } 170 | 171 | bool FindInternetPassword(const std::string& servername, 172 | int port, 173 | std::string* password) { 174 | 175 | SecKeychainItemRef item; 176 | void *data; 177 | UInt32 length; 178 | 179 | OSStatus status = SecKeychainFindInternetPassword 180 | (NULL, // keychain 181 | servername.length(), 182 | servername.data(), 183 | 0, NULL, // securityDomain 184 | 0, NULL, // account 185 | 0, NULL, // path 186 | port, 187 | kSecProtocolTypeAny, 188 | kSecAuthenticationTypeAny, 189 | &length, 190 | &data, 191 | &item); 192 | 193 | if (status != errSecSuccess) 194 | return false; 195 | 196 | *password = std::string(reinterpret_cast(data), length); 197 | SecKeychainItemFreeContent(NULL, data); 198 | CFRelease(item); 199 | return true; 200 | } 201 | 202 | } // namespace keytar 203 | 204 | #endif 205 | --------------------------------------------------------------------------------