Don't use libc getpass() for asking the password anymore. It is deprecated and doesn't play nice with tools that want to pass in the password on stdin. Now we just use stdin.

This commit is contained in:
Sebastian Messmer 2016-02-12 23:18:13 +01:00
parent aad7570222
commit ff62ef1b88
4 changed files with 59 additions and 12 deletions

View File

@ -0,0 +1 @@
#include "DontEchoStdinToStdoutRAII.h"

View File

@ -0,0 +1,39 @@
#pragma once
#ifndef MESSMER_CPPUTILS_IO_DONTECHOSTDINTOSTDOUTRAII_H
#define MESSMER_CPPUTILS_IO_DONTECHOSTDINTOSTDOUTRAII_H
#include <iostream>
#include <string>
#include <termios.h>
#include <unistd.h>
#include "../macros.h"
namespace cpputils {
/**
* If you create an instance of this class in your scope, then any user input from stdin
* won't be echoed back to stdout until the instance leaves the scope.
* This can be very handy for password inputs where you don't want the password to be visible on screen.
*/
class DontEchoStdinToStdoutRAII final {
public:
DontEchoStdinToStdoutRAII() {
tcgetattr(STDIN_FILENO, &_old_state);
termios new_state = _old_state;
new_state.c_lflag &= ~ECHO;
tcsetattr(STDIN_FILENO, TCSANOW, &new_state);
}
~DontEchoStdinToStdoutRAII() {
tcsetattr(STDIN_FILENO, TCSANOW, &_old_state);
}
private:
termios _old_state;
DISALLOW_COPY_AND_ASSIGN(DontEchoStdinToStdoutRAII);
};
}
#endif

View File

@ -11,6 +11,7 @@
#include <fspp/fuse/Fuse.h>
#include <fspp/impl/FilesystemImpl.h>
#include <cpp-utils/process/subprocess.h>
#include <cpp-utils/io/DontEchoStdinToStdoutRAII.h>
#include "../filesystem/CryDevice.h"
#include "../config/CryConfigLoader.h"
#include "program_options/Parser.h"
@ -20,14 +21,6 @@
#include "VersionChecker.h"
#include <pwd.h>
//<limits.h> needed for libc to define PASS_MAX
#include <limits.h>
#ifdef PASS_MAX
#error The used libc implementation has a maximal password size for getpass(). We cannot use it to ask for passwords.
#endif
//TODO Fails with gpg-homedir in filesystem: gpg --homedir gpg-homedir --gen-key
//TODO Many functions accessing the ProgramOptions object. Factor out into class that stores it as a member.
//TODO Factor out class handling askPassword
@ -49,6 +42,8 @@ using cpputils::unique_ref;
using cpputils::SCryptSettings;
using cpputils::Console;
using cpputils::HttpClient;
using cpputils::DontEchoStdinToStdoutRAII;
using std::cin;
using std::cout;
using std::string;
using std::endl;
@ -131,9 +126,9 @@ namespace cryfs {
}
string Cli::_askPasswordForExistingFilesystem() {
string password = getpass("Password: ");
string password = _askPasswordFromStdin("Password: ");
while (!_checkPassword(password)) {
password = getpass("Password: ");
password = _askPasswordFromStdin("Password: ");
}
return password;
};
@ -142,7 +137,7 @@ namespace cryfs {
string password;
bool again = false;
do {
password = getpass("Password: ");
password = _askPasswordFromStdin("Password: ");
if (!_checkPassword(password)) {
again = true;
continue;
@ -157,7 +152,7 @@ namespace cryfs {
}
bool Cli::_confirmPassword(const string &password) {
string confirmPassword = getpass("Confirm Password: ");
string confirmPassword = _askPasswordFromStdin("Confirm Password: ");
if (password != confirmPassword) {
std::cout << "Passwords don't match" << std::endl;
return false;
@ -165,6 +160,17 @@ namespace cryfs {
return true;
}
string Cli::_askPasswordFromStdin(const string &prompt) {
DontEchoStdinToStdoutRAII _stdin_input_is_hidden_as_long_as_this_is_in_scope;
std::cout << prompt << std::flush;
string result;
std::getline(cin, result);
std::cout << std::endl;
return result;
}
bf::path Cli::_determineConfigFile(const ProgramOptions &options) {
auto configFile = options.configFile();
if (configFile == none) {

View File

@ -24,6 +24,7 @@ namespace cryfs {
std::string _getPassword(const program_options::ProgramOptions &options, std::function<std::string()> askPassword);
static std::string _askPasswordForExistingFilesystem();
static std::string _askPasswordForNewFilesystem();
static std::string _askPasswordFromStdin(const std::string &prompt);
static bool _confirmPassword(const std::string &password);
static bool _checkPassword(const std::string &password);
void _showVersion();