askpass/0000755000176200001440000000000014677713443011737 5ustar liggesusersaskpass/tests/0000755000176200001440000000000014677335647013107 5ustar liggesusersaskpass/tests/testthat/0000755000176200001440000000000014677713443014741 5ustar liggesusersaskpass/tests/testthat/test-option.R0000644000176200001440000000043514677335647017361 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/tests/testthat.R0000644000176200001440000000007214677335647015071 0ustar liggesuserslibrary(testthat) library(askpass) test_check("askpass") askpass/MD50000644000176200001440000000156014677713443012251 0ustar liggesusers65338b9776c7cb5ae5932e66267e3159 *DESCRIPTION 98c71b5eae0ac8dabb055bd8883b8398 *LICENSE ad7ca63fdfe698661be582601697c491 *NAMESPACE 2281326fb2937aaffb03822ae70f4c7a *NEWS 00d594b6178fe8ea2e56ac8f8c188284 *R/askpass.R e0e98bb6ad99cc66b8d117e7e68916cc *R/interactive.R 97259f0bad2d259cc87ad38a01dbf02e *R/onload.R a1624267f9c82ed814f980de8c5fbc66 *R/ssh.R 1f9f6a06b0543cf62931f42ad291db6b *inst/WORDLIST a34602417af1b0c9ad06fc93df828c71 *inst/mac-askpass e0651808479eb9c747ffbd785441912b *inst/mac-simplepass a0f97770d4be15c46a6ce502e4d274db *man/askpass.Rd 20d01a60d6cef576ee14420f207d90d1 *man/ssh_askpass.Rd 2adeae71bea50e397971f3243e7c61e6 *src/Makevars.win ff322a40812325235977b54323b67c91 *src/askpass.c b0e65f1a2fd9237f0cb01f9e2e6f64a4 *src/win32/win-askpass.c 203e4bb2a5fd4caccb9a07d14bf48a90 *tests/testthat.R 631ab61b3bc4600779d0eee8aaf6cb32 *tests/testthat/test-option.R askpass/R/0000755000176200001440000000000014677335647012146 5ustar liggesusersaskpass/R/askpass.R0000644000176200001440000000477714677335647013755 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. #' #' By default `askpass()` returns `NULL` in non-interactive sessions. #' (These include knitr runs and testthat tests.) #' If you want to force a password prompt in non-interactive sessions, #' set the `rlib_interactive` option to `TRUE`: #' ```r #' options(rlib_interactive = TRUE) #' ``` #' #' @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(!is_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 <- ifelse(identical(.Machine$sizeof.pointer, 4L), "32", "") system.file(sprintf('win-askpass%s.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/R/onload.R0000644000176200001440000000237314677335647013552 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.R0000644000176200001440000000103114677335647013061 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/interactive.R0000644000176200001440000000052114677335647014604 0ustar liggesusers is_interactive <- function() { opt <- getOption("rlib_interactive") if (isTRUE(opt)) { TRUE } else if (identical(opt, FALSE)) { FALSE } else if (tolower(getOption("knitr.in.progress", "false")) == "true") { FALSE } else if (identical(Sys.getenv("TESTTHAT"), "true")) { FALSE } else { interactive() } } askpass/NEWS0000644000176200001440000000022514677335647012443 0ustar liggesusers1.2.0 - Fix package for experimental arm builds 1.1 - Fix build on R 3.3 and older - Fix compiler warning on Solaris 1.0 - Initial release askpass/src/0000755000176200001440000000000014677335647012534 5ustar liggesusersaskpass/src/Makevars.win0000644000176200001440000000034214677335647015023 0ustar liggesusersASKPASS=../inst/win-askpass$(subst 64,,$(WIN)).exe ASKPASSOBJ=win32/win-askpass.o all: clean $(ASKPASS) clean: rm -f $(ASKPASS) $(ASKPASSOBJ) $(ASKPASS): $(ASKPASSOBJ) $(CC) $(CFLAGS) -o $(ASKPASS) $(ASKPASSOBJ) -lcredui askpass/src/win32/0000755000176200001440000000000014677335647013476 5ustar liggesusersaskpass/src/win32/win-askpass.c0000644000176200001440000000351414677335647016105 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/askpass.c0000644000176200001440000000116014677335647014343 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/NAMESPACE0000644000176200001440000000012214677335647013157 0ustar liggesusers# Generated by roxygen2: do not edit by hand export(askpass) export(ssh_askpass) askpass/LICENSE0000644000176200001440000000005114677335647012746 0ustar liggesusersYEAR: 2018 COPYRIGHT HOLDER: Jeroen Ooms askpass/inst/0000755000176200001440000000000014677335647012722 5ustar liggesusersaskpass/inst/mac-askpass0000755000176200001440000000145514677335647015060 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-simplepass0000755000176200001440000000054114677335647015566 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/WORDLIST0000644000176200001440000000002514677335647014111 0ustar liggesusersCMD IDEs MacOS tcltk askpass/man/0000755000176200001440000000000014677335647012520 5ustar liggesusersaskpass/man/askpass.Rd0000644000176200001440000000205614677335647014457 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. } \details{ By default \code{askpass()} returns \code{NULL} in non-interactive sessions. (These include knitr runs and testthat tests.) If you want to force a password prompt in non-interactive sessions, set the \code{rlib_interactive} option to \code{TRUE}: \if{html}{\out{
}}\preformatted{options(rlib_interactive = TRUE) }\if{html}{\out{
}} } \examples{ \donttest{ # Prompt user for passwd pw <- askpass("Please enter your password") } } askpass/man/ssh_askpass.Rd0000644000176200001440000000117214677335647015332 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/DESCRIPTION0000644000176200001440000000243414677713443013450 0ustar liggesusersPackage: askpass Type: Package Title: Password Entry Utilities for R, Git, and SSH Version: 1.2.1 Authors@R: person("Jeroen", "Ooms", role = c("aut", "cre"), email = "jeroenooms@gmail.com", 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://r-lib.r-universe.dev/askpass BugReports: https://github.com/r-lib/askpass/issues Encoding: UTF-8 Imports: sys (>= 2.1) RoxygenNote: 7.2.3 Suggests: testthat Language: en-US NeedsCompilation: yes Packaged: 2024-10-03 14:12:09 UTC; jeroen Author: Jeroen Ooms [aut, cre] () Maintainer: Jeroen Ooms Repository: CRAN Date/Publication: 2024-10-04 07:20:03 UTC