askpass/0000755000176200001440000000000013416631773011732 5ustar liggesusersaskpass/inst/0000755000176200001440000000000013374566731012713 5ustar liggesusersaskpass/inst/mac-askpass0000755000176200001440000000145513374006143015033 0ustar liggesusers#!/usr/bin/env osascript # This only works on MacOS! # Adapted from: https://github.com/theseal/ssh-askpass on run argv set args to argv as text set frontmost_application to name of (info for (path to frontmost application)) tell application frontmost_application if args ends with ": " or args ends with ":" then if args contains "pass" or args contains "pin" then display dialog args with icon note default button "OK" default answer "" with hidden answer else display dialog args with icon note default button "OK" default answer "" end if return result's text returned else display dialog args with icon note default button "Cancel" return end if end tell end run askpass/inst/mac-simplepass0000755000176200001440000000054113374031337015544 0ustar liggesusers#!/usr/bin/env osascript # This only works on MacOS! on run argv set args to argv as text set frontmost_application to name of (info for (path to frontmost application)) tell application frontmost_application display dialog args with icon note default button "OK" default answer "" with hidden answer return result's text returned end tell end run askpass/inst/WORDLIST0000644000176200001440000000002513374044635014074 0ustar liggesusersCMD IDEs MacOS tcltk askpass/tests/0000755000176200001440000000000013374043317013066 5ustar liggesusersaskpass/tests/testthat.R0000644000176200001440000000007213374017351015047 0ustar liggesuserslibrary(testthat) library(askpass) test_check("askpass") askpass/tests/testthat/0000755000176200001440000000000013416631773014734 5ustar liggesusersaskpass/tests/testthat/test-option.R0000644000176200001440000000043513374021521017331 0ustar liggesuserscontext("test-option") test_that("program exists", { if(is_windows() || is_macos()){ expect_true(file.exists(ssh_askpass())) } }) test_that("option askpass is respected", { options(askpass = function(...){ 'supersecret' }) expect_equal(askpass(), 'supersecret') }) askpass/src/0000755000176200001440000000000013413122702012501 5ustar liggesusersaskpass/src/askpass.c0000644000176200001440000000116013416625061014321 0ustar liggesusers#include #include #include #include /* We don't use this anymore */ SEXP pw_entry_dialog(SEXP prompt){ #ifndef _WIN32 const char *text = CHAR(STRING_ELT(prompt, 0)); const char *pass = getpass(text); if(pass != NULL) return Rf_mkString(pass); #endif return R_NilValue; } static const R_CallMethodDef CallEntries[] = { {"pw_entry_dialog", (DL_FUNC) &pw_entry_dialog, 1}, {NULL, NULL, 0} }; void R_init_askpass(DllInfo *dll){ R_registerRoutines(dll, NULL, CallEntries, NULL, NULL); R_useDynamicSymbols(dll, FALSE); R_forceSymbols(dll, TRUE); } askpass/src/win32/0000755000176200001440000000000013374367657013475 5ustar liggesusersaskpass/src/win32/win-askpass.c0000644000176200001440000000351413416625061016063 0ustar liggesusers#include #include #include static const char *formatError(DWORD res){ static char buf[1000], *p; FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, res, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), buf, 1000, NULL); p = buf+strlen(buf) -1; if(*p == '\n') *p = '\0'; p = buf+strlen(buf) -1; if(*p == '\r') *p = '\0'; p = buf+strlen(buf) -1; if(*p == '.') *p = '\0'; return buf; } int main( int argc, const char* argv[] ){ const char *prompt = argc > 1 ? argv[1] : "Please enter password"; const char *user = argc > 2 ? argv[2] : "NA"; CREDUI_INFO cui; TCHAR pszPwd[CREDUI_MAX_PASSWORD_LENGTH+1]; BOOL fSave; DWORD dwErr; cui.cbSize = sizeof(CREDUI_INFO); cui.hwndParent = GetActiveWindow(); cui.pszMessageText = TEXT(prompt); cui.pszCaptionText = TEXT("Password Entry"); cui.hbmBanner = NULL; fSave = FALSE; SecureZeroMemory(pszPwd, sizeof(pszPwd)); dwErr = CredUIPromptForCredentials( &cui, // CREDUI_INFO structure TEXT("TheServer"), // Target for credentials NULL, // Reserved 0, // Reason (char*) user, // User name 0, // Max number of char for user name pszPwd, // Password CREDUI_MAX_PASSWORD_LENGTH+1, // Max number of char for password &fSave, // State of save check box CREDUI_FLAGS_GENERIC_CREDENTIALS | // flags CREDUI_FLAGS_KEEP_USERNAME | CREDUI_FLAGS_PASSWORD_ONLY_OK | CREDUI_FLAGS_ALWAYS_SHOW_UI | CREDUI_FLAGS_DO_NOT_PERSIST); if(!dwErr) { fprintf( stdout, "%s\n", pszPwd); return 0; } else { fprintf( stderr, "%s\n", formatError(GetLastError())); return 1; } } askpass/src/Makevars.win0000644000176200001440000000032513416625061015002 0ustar liggesusersASKPASS=../inst/win-askpass$(WIN).exe ASKPASSOBJ=win32/win-askpass.o all: clean $(ASKPASS) clean: rm -f $(ASKPASS) $(ASKPASSOBJ) $(ASKPASS): $(ASKPASSOBJ) $(CC) $(CFLAGS) -o $(ASKPASS) $(ASKPASSOBJ) -lcredui askpass/NAMESPACE0000644000176200001440000000012213377474226013150 0ustar liggesusers# Generated by roxygen2: do not edit by hand export(askpass) export(ssh_askpass) askpass/NEWS0000644000176200001440000000014213416623477012430 0ustar liggesusers1.1 - Fix build on R 3.3 and older - Fix compiler warning on Solaris 1.0 - Initial release askpass/R/0000755000176200001440000000000013374566625012141 5ustar liggesusersaskpass/R/onload.R0000644000176200001440000000237313374372173013536 0ustar liggesusers.onLoad <- function(libname, pkgname){ setup_askpass_vars() } setup_askpass_vars <- function(){ if(var_exists('RSTUDIO')){ fix_rstudio_path() } else { # This is mostly for RGui and R.app (tty could mean MacOS server) if(is_windows() || (is_macos() && !isatty(stdin()))){ askpass_bin = ssh_askpass() if(!var_exists('GIT_ASKPASS')){ Sys.setenv("GIT_ASKPASS" = askpass_bin) } if(!var_exists('SSH_ASKPASS')){ Sys.setenv("SSH_ASKPASS" = askpass_bin) } } } } # Try to put 'rpostback-askpass' on the path in RStudio if needed # See: https://github.com/rstudio/rstudio/issues/3805 fix_rstudio_path <- function(){ rs_path <- Sys.getenv('RS_RPOSTBACK_PATH') git_askpass <- Sys.getenv('GIT_ASKPASS') if(nchar(rs_path) && !cmd_exists(git_askpass)){ PATH <- Sys.getenv("PATH") if(!grepl(normalizePath(rs_path, mustWork = FALSE), PATH, fixed = TRUE)){ rs_path <- unique(c(rs_path, sub("rpostback", 'postback', rs_path))) Sys.setenv(PATH = paste(c(PATH, normalizePath(rs_path, mustWork = FALSE)), collapse = .Platform$path.sep)) } } } var_exists <- function(var){ nchar(Sys.getenv(var)) > 0 } cmd_exists <- function(cmd){ nchar(Sys.which(cmd)) > 0 } askpass/R/ssh.R0000644000176200001440000000103113374566625013054 0ustar liggesusers#' ASKPASS CMD TOOL #' #' This returns the path to the native askpass executable which can be used #' by git-credential or ssh-agent. Most users don't have worry about this. #' #' On Windows and MacOS the package automatically sets the `SSH_ASKPASS` and #' `GIT_ASKPASS` variables on load (if not already set). If these are set #' you should be able to run e.g. `sys::exec_wait("ssh-add")` and you should #' be prompted for a passphrase if your key is protected. #' #' @export ssh_askpass <- function(){ askpass_path(simple = FALSE) } askpass/R/askpass.R0000644000176200001440000000427313377474220013727 0ustar liggesusers#' Password Prompt Utility #' #' Prompt the user for a password to authenticate or read a protected key. #' By default, this function automatically uses the most appropriate method #' based on the user platform and front-end. Users or IDEs can override this #' and set a custom password entry function via the `askpass` option. #' #' @export #' @param prompt the string printed when prompting the user for input. #' @examples \donttest{ #' # Prompt user for passwd #' pw <- askpass("Please enter your password") #' } askpass <- function(prompt = "Please enter your password: "){ FUN <- getOption("askpass", ask_password_default) FUN(prompt) } ask_password_default <- function(prompt){ if(!interactive()) return(NULL) if(is_windows()){ askpass_windows(prompt) } else if(is_macos() && !isatty(stdin())){ askpass_mac(prompt) } else { readline_silent(prompt) } } askpass_path <- function(simple = TRUE){ if(is_windows()){ arch <- .Machine$sizeof.pointer * 8; system.file(sprintf('win-askpass%d.exe', arch), package = 'askpass', mustWork = TRUE) } else if(is_macos()){ prog <- ifelse(isTRUE(simple), 'mac-simplepass', 'mac-askpass') system.file(prog, package = 'askpass', mustWork = TRUE) } } askpass_windows <- function(prompt, user = names(prompt)){ tryCatch({ res <- sys::exec_internal(askpass_path(), c(prompt, user), timeout = 120) out_without_eol(res$stdout) }, error = function(e){ message(e$message) }) } askpass_mac <- function(prompt){ tryCatch({ res <- sys::exec_internal(askpass_path(), prompt, timeout = 120) out_without_eol(res$stdout) }, error = function(e){ message(e$message) }) } readline_silent <- function(prompt, icon = "\U0001f511 "){ if(is_unix() && isatty(stdin())){ if(system('stty -echo') == 0){ on.exit(system('stty echo')) } } cat(prompt, "\n") out <- base::readline(icon) cat(" OK\n") out } is_windows <- function(){ .Platform$OS.type == 'windows' } is_unix <- function(){ .Platform$OS.type == "unix" } is_macos <- function(){ identical(tolower(Sys.info()[['sysname']]), "darwin") } out_without_eol <- function(x){ sub("\r?\n$", "", rawToChar(x)) } askpass/MD50000644000176200001440000000147613416631773012252 0ustar liggesuserseb6f4d0b9cc61dfa08b3804779591d5f *DESCRIPTION 98c71b5eae0ac8dabb055bd8883b8398 *LICENSE ad7ca63fdfe698661be582601697c491 *NAMESPACE 53a778139c44afbdf7a33ef6f5df8705 *NEWS 35412ba699bd625370487aa6a3e462c4 *R/askpass.R 97259f0bad2d259cc87ad38a01dbf02e *R/onload.R a1624267f9c82ed814f980de8c5fbc66 *R/ssh.R 1f9f6a06b0543cf62931f42ad291db6b *inst/WORDLIST a34602417af1b0c9ad06fc93df828c71 *inst/mac-askpass e0651808479eb9c747ffbd785441912b *inst/mac-simplepass 0eb1bcf4a9936ace5ae19d962a2a56a7 *man/askpass.Rd 20d01a60d6cef576ee14420f207d90d1 *man/ssh_askpass.Rd dce2a57c7c4f360319f3beaec3245444 *src/Makevars.win ff322a40812325235977b54323b67c91 *src/askpass.c b0e65f1a2fd9237f0cb01f9e2e6f64a4 *src/win32/win-askpass.c 203e4bb2a5fd4caccb9a07d14bf48a90 *tests/testthat.R 631ab61b3bc4600779d0eee8aaf6cb32 *tests/testthat/test-option.R askpass/DESCRIPTION0000644000176200001440000000244713416631773013447 0ustar liggesusersPackage: askpass Type: Package Title: Safe Password Entry for R, Git, and SSH Version: 1.1 Authors@R: person("Jeroen", "Ooms", role = c("aut", "cre"), email = "jeroen@berkeley.edu", comment = c(ORCID = "0000-0002-4035-0289")) Description: Cross-platform utilities for prompting the user for credentials or a passphrase, for example to authenticate with a server or read a protected key. Includes native programs for MacOS and Windows, hence no 'tcltk' is required. Password entry can be invoked in two different ways: directly from R via the askpass() function, or indirectly as password-entry back-end for 'ssh-agent' or 'git-credential' via the SSH_ASKPASS and GIT_ASKPASS environment variables. Thereby the user can be prompted for credentials or a passphrase if needed when R calls out to git or ssh. License: MIT + file LICENSE URL: https://github.com/jeroen/askpass#readme BugReports: https://github.com/jeroen/askpass/issues Encoding: UTF-8 LazyData: true Imports: sys (>= 2.1) RoxygenNote: 6.1.1 Suggests: testthat Language: en-US NeedsCompilation: yes Packaged: 2019-01-13 12:08:17 UTC; jeroen Author: Jeroen Ooms [aut, cre] () Maintainer: Jeroen Ooms Repository: CRAN Date/Publication: 2019-01-13 12:50:03 UTC askpass/man/0000755000176200001440000000000013374566625012513 5ustar liggesusersaskpass/man/ssh_askpass.Rd0000644000176200001440000000117213374566625015325 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/ssh.R \name{ssh_askpass} \alias{ssh_askpass} \title{ASKPASS CMD TOOL} \usage{ ssh_askpass() } \description{ This returns the path to the native askpass executable which can be used by git-credential or ssh-agent. Most users don't have worry about this. } \details{ On Windows and MacOS the package automatically sets the \code{SSH_ASKPASS} and \code{GIT_ASKPASS} variables on load (if not already set). If these are set you should be able to run e.g. \code{sys::exec_wait("ssh-add")} and you should be prompted for a passphrase if your key is protected. } askpass/man/askpass.Rd0000644000176200001440000000126713377474226014453 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/askpass.R \name{askpass} \alias{askpass} \title{Password Prompt Utility} \usage{ askpass(prompt = "Please enter your password: ") } \arguments{ \item{prompt}{the string printed when prompting the user for input.} } \description{ Prompt the user for a password to authenticate or read a protected key. By default, this function automatically uses the most appropriate method based on the user platform and front-end. Users or IDEs can override this and set a custom password entry function via the \code{askpass} option. } \examples{ \donttest{ # Prompt user for passwd pw <- askpass("Please enter your password") } } askpass/LICENSE0000644000176200001440000000005113374005027012721 0ustar liggesusersYEAR: 2018 COPYRIGHT HOLDER: Jeroen Ooms