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