passphrase_entry.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. #include <stdlib.h>
  2. #include <string.h>
  3. #include "passphrase_entry.h"
  4. #include "readpass.h"
  5. #include "warnp.h"
  6. /**
  7. * passphrase_entry_parse(arg, entry_method_p, entry_arg_p):
  8. * Parse "METHOD:ARG" from ${arg} into an ${*entry_method_p}:${*entry_arg_p}.
  9. */
  10. int
  11. passphrase_entry_parse(const char * arg,
  12. enum passphrase_entry * passphrase_entry_p, const char ** passphrase_arg_p)
  13. {
  14. const char * p;
  15. /* Find the separator in "method:arg", or fail if there isn't one. */
  16. if ((p = strchr(arg, ':')) == NULL)
  17. goto err1;
  18. /* Extract the "arg" part. */
  19. *passphrase_arg_p = &p[1];
  20. /* Parse the "method". */
  21. if (strncmp(arg, "dev:", 4) == 0) {
  22. if (strcmp(*passphrase_arg_p, "tty-stdin") == 0) {
  23. *passphrase_entry_p = PASSPHRASE_TTY_STDIN;
  24. goto success;
  25. }
  26. else if (strcmp(*passphrase_arg_p, "stdin-once") == 0) {
  27. *passphrase_entry_p = PASSPHRASE_STDIN_ONCE;
  28. goto success;
  29. }
  30. else if (strcmp(*passphrase_arg_p, "tty-once") == 0) {
  31. *passphrase_entry_p = PASSPHRASE_TTY_ONCE;
  32. goto success;
  33. }
  34. }
  35. if (strncmp(arg, "env:", 4) == 0) {
  36. *passphrase_entry_p = PASSPHRASE_ENV;
  37. goto success;
  38. }
  39. if (strncmp(arg, "file:", 5) == 0) {
  40. *passphrase_entry_p = PASSPHRASE_FILE;
  41. goto success;
  42. }
  43. err1:
  44. warn0("Invalid option: --passphrase %s", arg);
  45. /* Failure! */
  46. return (-1);
  47. success:
  48. /* Success! */
  49. return (0);
  50. }
  51. /**
  52. * passphrase_entry_readpass(passwd, entry_method, entry_arg, prompt,
  53. * confirmprompt, once):
  54. * Use ${entry_method} to read a passphrase and return it as a malloced
  55. * NUL-terminated string via ${passwd}. If ${entry_method} is
  56. * PASSPHRASE_TTY_STDIN and ${once} is zero, ask for the passphrase twice;
  57. * otherwise ask for it once. If reading from a terminal, use ${prompt} for
  58. * the first prompt, and ${confirmprompt} for the second prompt (if
  59. * applicable); otherwise do not print any prompts.
  60. */
  61. int
  62. passphrase_entry_readpass(char ** passwd,
  63. enum passphrase_entry passphrase_entry, const char * passphrase_arg,
  64. const char * prompt, const char * confirmprompt, int once)
  65. {
  66. const char * passwd_env;
  67. switch (passphrase_entry) {
  68. case PASSPHRASE_TTY_STDIN:
  69. /* Read passphrase, prompting only once if decrypting. */
  70. if (readpass(passwd, prompt, (once) ? NULL : confirmprompt, 1))
  71. goto err0;
  72. break;
  73. case PASSPHRASE_STDIN_ONCE:
  74. /* Read passphrase, prompting only once, from stdin only. */
  75. if (readpass(passwd, prompt, NULL, 0))
  76. goto err0;
  77. break;
  78. case PASSPHRASE_TTY_ONCE:
  79. /* Read passphrase, prompting only once, from tty only. */
  80. if (readpass(passwd, prompt, NULL, 2))
  81. goto err0;
  82. break;
  83. case PASSPHRASE_ENV:
  84. /* We're not allowed to modify the output of getenv(). */
  85. if ((passwd_env = getenv(passphrase_arg)) == NULL) {
  86. warn0("Failed to read from ${%s}", passphrase_arg);
  87. goto err0;
  88. }
  89. /* This allows us to use the same insecure_zero() logic. */
  90. if ((*passwd = strdup(passwd_env)) == NULL) {
  91. warnp("Out of memory");
  92. goto err0;
  93. }
  94. break;
  95. case PASSPHRASE_FILE:
  96. if (readpass_file(passwd, passphrase_arg))
  97. goto err0;
  98. break;
  99. case PASSPHRASE_UNSET:
  100. warn0("Programming error: passphrase_entry is not set");
  101. goto err0;
  102. }
  103. /* Success! */
  104. return (0);
  105. err0:
  106. /* Failure! */
  107. return (-1);
  108. }