19 Commits

Author SHA1 Message Date
Andrew Ayer
546664f152 Prepare 0.6.0 release 2017-11-26 10:24:03 -08:00
Andrew Ayer
37df6fb5ad Update INSTALL file to reflect C++11 requirement 2017-11-26 10:21:23 -08:00
Andrew Ayer
f3dd69e4c7 Update THANKS file 2017-11-26 10:05:42 -08:00
Andrew Ayer
ccdcc76f8e Switch from NULL to nullptr 2017-09-10 12:36:21 -07:00
Andrew Ayer
f03fdc6ad0 Clean up readdir code, add a comment about why we're using readdir 2017-09-10 12:34:36 -07:00
Andrew Ayer
0e4ad51a13 Update a comment regarding unique_ptr 2017-09-10 12:34:36 -07:00
Adrian Cohea
d3bb5aba46 Addresses -Wdeprecated-declarations warnings
changing all references of std::auto_ptr to std::unique_ptr and changing the implementation of get_directory_contents() to use readdir, which is now reentrant, instead of readdir_r.

Signed-off-by: Andrew Ayer <agwa@andrewayer.name>

  Note: old implementations or readdir might not be re-entrant, but that's OK
  because git-crypt is not multi-threaded.
2017-09-10 12:34:05 -07:00
Kevin Borgolte
edfa3dcb5f Allow GPG to fail on some keys
If multiple GPG keys exist that could be used to decrypt the repository
key, but GPG fails on one of them (e.g., the first one because it is
stored on a SmartCard that is not plugged in), then no other keys are
used to try to decrypt it, failing entirely instead of trying the
additional GPG keys.

Modified-by: Andrew Ayer <agwa@andrewayer.name>

  * Make exception variable const
  * Make whitespace conform to project conventions

Signed-off-by: Andrew Ayer <agwa@andrewayer.name>

Closes: #88
2017-09-10 12:25:50 -07:00
Andrew Ayer
2b1076108e Enable C++11 in Makefile 2017-09-10 12:24:52 -07:00
ticktockhouse
00a7887486 Fix tables in install.md
Closes: #119
2017-09-10 12:20:35 -07:00
Andrew Ayer
101b738a8d Read gpg program from git config gpg.program ; ported from fork by alanrossmachinery
Modified-By: Andrew Ayer <agwa@andrewayer.name>

  * Make whitespace conform to project conventions

Closes #89
Closes #65
2017-09-10 12:14:55 -07:00
Andrew Ayer
934914c2c4 Fix typo in README
Closes #83
2017-09-10 12:09:31 -07:00
Andrew Ayer
a6170413eb Sync README changes to README.md 2017-09-10 12:05:13 -07:00
Caleb Maclennan
03ef81e541 Update link to git-remote-gcrypt project
Fixes #96

Signed-off-by: Andrew Ayer <agwa@andrewayer.name>
2017-09-10 12:04:58 -07:00
Wael M. Nasreddine
553c1b0387 crypto: fix for compatibility with openssl 1.1
Closes: #128
2017-09-10 11:33:23 -07:00
Kevin Menard
788a6a99f4 Make the repo state directory location configurable.
Modified-by: Andrew Ayer <agwa@andrewayer.name>

  * Rename a local variable to be more accurate.

Signed-off-by: Andrew Ayer <agwa@andrewayer.name>
2016-06-27 12:08:00 -07:00
Andrew Ayer
b47176e6a8 Don't hard code path to git-crypt in .git/config on Linux
There's a tradeoff.  When the path is hardcoded, it's guaranteed that
git-crypt will be found no matter where you run git or what your $PATH is.
On the other hand, hardcoding means that things break if git-crypt changes
location, which could easily happen if you copy a repository to a different system
(see https://github.com/AGWA/git-crypt/issues/71 for example).

In hindsight, I think this was a bad tradeoff.  Now, if git-crypt is
invoked as a bare filename (no slashes), the bare filename is placed
in .git/config under the assumption that it can be found via $PATH
(this assumption will be true as long as git-crypt wasn't resolved via
a relative path in $PATH).  This logic was already being used on
non-Linux OSes and it seemed to work fine.
2015-12-26 14:30:42 -08:00
Andrew Ayer
c63a727177 Mark .gpg files in .git-crypt as binary
To remove any possibility of Git treating them as text by accident.

Closes #55.
2015-07-29 21:51:11 -07:00
Andrew Ayer
e0b3bd754f Remove gnuism from Makefile
According to POSIX, $< is only valid with inference rules, not normal
target rules.
2015-06-13 10:54:50 -07:00
32 changed files with 321 additions and 413 deletions

14
INSTALL
View File

@@ -2,19 +2,19 @@ DEPENDENCIES
To build git-crypt, you need:
Debian/Ubuntu package RHEL/CentOS package
Debian/Ubuntu package RHEL/CentOS package
-----------------------------------------------------------------------------
Make make make
A C++ compiler (e.g. gcc) g++ gcc-c++
OpenSSL development files libssl-dev openssl-devel
Make make make
A C++11 compiler (e.g. gcc 4.9+) g++ gcc-c++
OpenSSL development files libssl-dev openssl-devel
To use git-crypt, you need:
Debian/Ubuntu package RHEL/CentOS package
Debian/Ubuntu package RHEL/CentOS package
-----------------------------------------------------------------------------
Git 1.7.2 or newer git git
OpenSSL openssl openssl
Git 1.7.2 or newer git git
OpenSSL openssl openssl
Note: Git 1.8.5 or newer is recommended for best performance.

View File

@@ -2,19 +2,19 @@
To build git-crypt, you need:
| Debian/Ubuntu package | RHEL/CentOS package
---------------------------|-----------------------|------------------------
Make | make | make
A C++ compiler (e.g. gcc) | g++ | gcc-c++
OpenSSL development files | libssl-dev | openssl-devel
| Software | Debian/Ubuntu package | RHEL/CentOS package|
|---------------------------------|-----------------------|--------------------|
|Make | make | make |
|A C++11 compiler (e.g. gcc 4.9+) | g++ | gcc-c++ |
|OpenSSL development files | libssl-dev | openssl-devel |
To use git-crypt, you need:
| Debian/Ubuntu package | RHEL/CentOS package
---------------------------|-----------------------|------------------------
Git 1.7.2 or newer | git | git
OpenSSL | openssl | openssl
| Software | Debian/Ubuntu package | RHEL/CentOS package|
|---------------------------------|-----------------------|--------------------|
|Git 1.7.2 or newer | git | git |
|OpenSSL | openssl | openssl |
Note: Git 1.8.5 or newer is recommended for best performance.

View File

@@ -5,6 +5,7 @@
#
CXXFLAGS ?= -Wall -pedantic -Wno-long-long -O2
CXXFLAGS += -std=c++11
PREFIX ?= /usr/local
BINDIR ?= $(PREFIX)/bin
MANDIR ?= $(PREFIX)/share/man
@@ -23,7 +24,7 @@ OBJFILES = \
coprocess.o \
fhstream.o
OBJFILES += crypto-openssl.o
OBJFILES += crypto-openssl-10.o crypto-openssl-11.o
LDFLAGS += -lcrypto
XSLTPROC ?= xsltproc
@@ -54,7 +55,7 @@ coprocess.o: coprocess.cpp coprocess-unix.cpp coprocess-win32.cpp
build-man: man/man1/git-crypt.1
man/man1/git-crypt.1: man/git-crypt.xml
$(XSLTPROC) $(DOCBOOK_FLAGS) $(DOCBOOK_XSL) $<
$(XSLTPROC) $(DOCBOOK_FLAGS) $(DOCBOOK_XSL) man/git-crypt.xml
#
# Clean

13
NEWS
View File

@@ -1,3 +1,16 @@
v0.6.0 (2017-11-26)
* Add support for OpenSSL 1.1 (still works with OpenSSL 1.0).
* Switch to C++11 (gcc 4.9 or higher now required to build).
* Allow GPG to fail on some keys (makes unlock work better if there are
multiple keys that can unlock the repo but only some are available).
* Allow the repo state directory to be configured with the
git-crypt.repoStateDir git config option.
* Respect the gpg.program git config option.
* Don't hard code path to git-crypt in .git/config on Linux (ensures
repo continues to work if git-crypt is moved).
* Ensure git-crypt's gpg files won't be treated as text by Git.
* Minor improvements to build system, documentation.
v0.5.0 (2015-05-30)
* Drastically speed up lock/unlock when used with Git 1.8.5 or newer.
* Add git-crypt(1) man page (pass ENABLE_MAN=yes to make to build).

13
NEWS.md
View File

@@ -1,6 +1,19 @@
News
====
######v0.6.0 (2017-11-26)
* Add support for OpenSSL 1.1 (still works with OpenSSL 1.0).
* Switch to C++11 (gcc 4.9 or higher now required to build).
* Allow GPG to fail on some keys (makes unlock work better if there are
multiple keys that can unlock the repo but only some are available).
* Allow the repo state directory to be configured with the
git-crypt.repoStateDir git config option.
* Respect the gpg.program git config option.
* Don't hard code path to git-crypt in .git/config on Linux (ensures
repo continues to work if git-crypt is moved).
* Ensure git-crypt's gpg files won't be treated as text by Git.
* Minor improvements to build system, documentation.
######v0.5.0 (2015-05-30)
* Drastically speed up lock/unlock when used with Git 1.8.5 or newer.
* Add git-crypt(1) man page (pass `ENABLE_MAN=yes` to make to build).

6
README
View File

@@ -69,7 +69,7 @@ encryption and decryption happen transparently.
CURRENT STATUS
The latest version of git-crypt is 0.5.0, released on 2015-05-30.
The latest version of git-crypt is 0.6.0, released on 2017-11-26.
git-crypt aims to be bug-free and reliable, meaning it shouldn't
crash, malfunction, or expose your confidential data. However,
it has not yet reached maturity, meaning it is not as documented,
@@ -79,7 +79,7 @@ backwards-incompatible changes introduced before version 1.0.
SECURITY
git-crypt is more secure that other transparent git encryption systems.
git-crypt is more secure than other transparent git encryption systems.
git-crypt encrypts files using AES-256 in CTR mode with a synthetic IV
derived from the SHA-1 HMAC of the file. This mode of operation is
provably semantically secure under deterministic chosen-plaintext attack.
@@ -98,7 +98,7 @@ all of the files in a repository. Where git-crypt really shines is where
most of your repository is public, but you have a few files (perhaps
private keys named *.key, or a file with API credentials) which you
need to encrypt. For encrypting an entire repository, consider using a
system like git-remote-gcrypt <https://github.com/joeyh/git-remote-gcrypt>
system like git-remote-gcrypt <https://spwhitton.name/tech/code/git-remote-gcrypt/>
instead. (Note: no endorsement is made of git-remote-gcrypt's security.)
git-crypt does not encrypt file names, commit messages, symlink targets,

View File

@@ -70,8 +70,8 @@ encryption and decryption happen transparently.
Current Status
--------------
The latest version of git-crypt is [0.5.0](NEWS.md), released on
2015-05-30. git-crypt aims to be bug-free and reliable, meaning it
The latest version of git-crypt is [0.6.0](NEWS.md), released on
2017-11-26. git-crypt aims to be bug-free and reliable, meaning it
shouldn't crash, malfunction, or expose your confidential data.
However, it has not yet reached maturity, meaning it is not as
documented, featureful, or easy-to-use as it should be. Additionally,
@@ -81,7 +81,7 @@ there may be backwards-incompatible changes introduced before version
Security
--------
git-crypt is more secure that other transparent git encryption systems.
git-crypt is more secure than other transparent git encryption systems.
git-crypt encrypts files using AES-256 in CTR mode with a synthetic IV
derived from the SHA-1 HMAC of the file. This mode of operation is
provably semantically secure under deterministic chosen-plaintext attack.
@@ -100,7 +100,7 @@ all of the files in a repository. Where git-crypt really shines is where
most of your repository is public, but you have a few files (perhaps
private keys named *.key, or a file with API credentials) which you
need to encrypt. For encrypting an entire repository, consider using a
system like [git-remote-gcrypt](https://github.com/joeyh/git-remote-gcrypt)
system like [git-remote-gcrypt](https://spwhitton.name/tech/code/git-remote-gcrypt/)
instead. (Note: no endorsement is made of git-remote-gcrypt's security.)
git-crypt does not encrypt file names, commit messages, symlink targets,

View File

@@ -12,6 +12,10 @@ For their contributions to git-crypt, I thank:
* Linus G Thiel
* Michael Schout
* Simon Kotlinski
* Kevin Menard
* Wael M. Nasreddine
* Kevin Borgolte
* Adrian Cohea
* And everyone who has tested git-crypt, provided feedback, reported
bugs, and participated in discussions about new features.

View File

@@ -48,6 +48,7 @@
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <exception>
#include <vector>
static std::string attribute_name (const char* key_name)
@@ -254,6 +255,27 @@ static std::string get_internal_key_path (const char* key_name)
return path;
}
std::string get_git_config (const std::string& name)
{
// git config --get
std::vector<std::string> command;
command.push_back("git");
command.push_back("config");
command.push_back("--get");
command.push_back(name);
std::stringstream output;
if (!successful_exit(exec_command(command, output))) {
throw Error("'git config' missing value for key '" + name +"'");
}
std::string value;
std::getline(output, value);
return value;
}
static std::string get_repo_state_path ()
{
// git rev-parse --show-toplevel
@@ -276,7 +298,18 @@ static std::string get_repo_state_path ()
throw Error("Could not determine Git working tree - is this a non-bare repo?");
}
path += "/.git-crypt";
// Check if the repo state dir has been explicitly configured. If so, use that in path construction.
if (git_has_config("git-crypt.repoStateDir")) {
std::string repoStateDir = get_git_config("git-crypt.repoStateDir");
// The repoStateDir value must always be relative to git work tree to ensure the repoStateDir can be committed
// along with the remainder of the repository.
path += '/' + repoStateDir;
} else {
// There is no explicitly configured repo state dir configured, so use the default.
path += "/.git-crypt";
}
return path;
}
@@ -455,7 +488,7 @@ static bool check_if_file_is_encrypted (const std::string& filename)
static bool is_git_file_mode (const std::string& mode)
{
return (std::strtoul(mode.c_str(), NULL, 8) & 0170000) == 0100000;
return (std::strtoul(mode.c_str(), nullptr, 8) & 0170000) == 0100000;
}
static void get_encrypted_files (std::vector<std::string>& files, const char* key_name)
@@ -476,8 +509,8 @@ static void get_encrypted_files (std::vector<std::string>& files, const char* ke
ls_files.spawn(ls_files_command);
Coprocess check_attr;
std::ostream* check_attr_stdin = NULL;
std::istream* check_attr_stdout = NULL;
std::ostream* check_attr_stdin = nullptr;
std::istream* check_attr_stdout = nullptr;
if (git_version() >= make_version(1, 8, 5)) {
// In Git 1.8.5 (released 27 Nov 2013) and higher, we use a single `git check-attr` process
// to get the attributes of all files at once. In prior versions, we have to fork and exec
@@ -557,13 +590,20 @@ static void load_key (Key_file& key_file, const char* key_name, const char* key_
static bool decrypt_repo_key (Key_file& key_file, const char* key_name, uint32_t key_version, const std::vector<std::string>& secret_keys, const std::string& keys_path)
{
std::exception_ptr gpg_error;
for (std::vector<std::string>::const_iterator seckey(secret_keys.begin()); seckey != secret_keys.end(); ++seckey) {
std::ostringstream path_builder;
path_builder << keys_path << '/' << (key_name ? key_name : "default") << '/' << key_version << '/' << *seckey << ".gpg";
std::string path(path_builder.str());
if (access(path.c_str(), F_OK) == 0) {
std::stringstream decrypted_contents;
gpg_decrypt_from_file(path, decrypted_contents);
try {
gpg_decrypt_from_file(path, decrypted_contents);
} catch (const Gpg_error&) {
gpg_error = std::current_exception();
continue;
}
Key_file this_version_key_file;
this_version_key_file.load(decrypted_contents);
const Key_file::Entry* this_version_entry = this_version_key_file.get(key_version);
@@ -578,6 +618,11 @@ static bool decrypt_repo_key (Key_file& key_file, const char* key_name, uint32_t
return true;
}
}
if (gpg_error) {
std::rethrow_exception(gpg_error);
}
return false;
}
@@ -1202,6 +1247,7 @@ int add_gpg_user (int argc, const char** argv)
state_gitattributes_file << "# Do not edit this file. To specify the files to encrypt, create your own\n";
state_gitattributes_file << "# .gitattributes file in the directory where your files are.\n";
state_gitattributes_file << "* !filter !diff\n";
state_gitattributes_file << "*.gpg binary\n";
state_gitattributes_file.close();
if (!state_gitattributes_file) {
std::clog << "Error: unable to write " << state_gitattributes_path << std::endl;

View File

@@ -70,4 +70,7 @@ void help_migrate_key (std::ostream&);
void help_refresh (std::ostream&);
void help_status (std::ostream&);
// other
std::string get_git_config (const std::string& name);
#endif

View File

@@ -41,7 +41,7 @@ static int execvp (const std::string& file, const std::vector<std::string>& args
for (std::vector<std::string>::const_iterator arg(args.begin()); arg != args.end(); ++arg) {
args_c_str.push_back(arg->c_str());
}
args_c_str.push_back(NULL);
args_c_str.push_back(nullptr);
return execvp(file.c_str(), const_cast<char**>(&args_c_str[0]));
}
@@ -50,10 +50,10 @@ Coprocess::Coprocess ()
pid = -1;
stdin_pipe_reader = -1;
stdin_pipe_writer = -1;
stdin_pipe_ostream = NULL;
stdin_pipe_ostream = nullptr;
stdout_pipe_reader = -1;
stdout_pipe_writer = -1;
stdout_pipe_istream = NULL;
stdout_pipe_istream = nullptr;
}
Coprocess::~Coprocess ()
@@ -79,7 +79,7 @@ std::ostream* Coprocess::stdin_pipe ()
void Coprocess::close_stdin ()
{
delete stdin_pipe_ostream;
stdin_pipe_ostream = NULL;
stdin_pipe_ostream = nullptr;
if (stdin_pipe_writer != -1) {
close(stdin_pipe_writer);
stdin_pipe_writer = -1;
@@ -107,7 +107,7 @@ std::istream* Coprocess::stdout_pipe ()
void Coprocess::close_stdout ()
{
delete stdout_pipe_istream;
stdout_pipe_istream = NULL;
stdout_pipe_istream = nullptr;
if (stdout_pipe_writer != -1) {
close(stdout_pipe_writer);
stdout_pipe_writer = -1;

View File

@@ -96,14 +96,14 @@ static HANDLE spawn_command (const std::vector<std::string>& command, HANDLE std
std::string cmdline(format_cmdline(command));
if (!CreateProcessA(NULL, // application name (NULL to use command line)
if (!CreateProcessA(nullptr, // application name (nullptr to use command line)
const_cast<char*>(cmdline.c_str()),
NULL, // process security attributes
NULL, // primary thread security attributes
nullptr, // process security attributes
nullptr, // primary thread security attributes
TRUE, // handles are inherited
0, // creation flags
NULL, // use parent's environment
NULL, // use parent's current directory
nullptr, // use parent's environment
nullptr, // use parent's current directory
&start_info,
&proc_info)) {
throw System_error("CreateProcess", cmdline, GetLastError());
@@ -117,13 +117,13 @@ static HANDLE spawn_command (const std::vector<std::string>& command, HANDLE std
Coprocess::Coprocess ()
{
proc_handle = NULL;
stdin_pipe_reader = NULL;
stdin_pipe_writer = NULL;
stdin_pipe_ostream = NULL;
stdout_pipe_reader = NULL;
stdout_pipe_writer = NULL;
stdout_pipe_istream = NULL;
proc_handle = nullptr;
stdin_pipe_reader = nullptr;
stdin_pipe_writer = nullptr;
stdin_pipe_ostream = nullptr;
stdout_pipe_reader = nullptr;
stdout_pipe_writer = nullptr;
stdout_pipe_istream = nullptr;
}
Coprocess::~Coprocess ()
@@ -143,7 +143,7 @@ std::ostream* Coprocess::stdin_pipe ()
// Set the bInheritHandle flag so pipe handles are inherited.
sec_attr.nLength = sizeof(SECURITY_ATTRIBUTES);
sec_attr.bInheritHandle = TRUE;
sec_attr.lpSecurityDescriptor = NULL;
sec_attr.lpSecurityDescriptor = nullptr;
// Create a pipe for the child process's STDIN.
if (!CreatePipe(&stdin_pipe_reader, &stdin_pipe_writer, &sec_attr, 0)) {
@@ -163,14 +163,14 @@ std::ostream* Coprocess::stdin_pipe ()
void Coprocess::close_stdin ()
{
delete stdin_pipe_ostream;
stdin_pipe_ostream = NULL;
stdin_pipe_ostream = nullptr;
if (stdin_pipe_writer) {
CloseHandle(stdin_pipe_writer);
stdin_pipe_writer = NULL;
stdin_pipe_writer = nullptr;
}
if (stdin_pipe_reader) {
CloseHandle(stdin_pipe_reader);
stdin_pipe_reader = NULL;
stdin_pipe_reader = nullptr;
}
}
@@ -182,7 +182,7 @@ std::istream* Coprocess::stdout_pipe ()
// Set the bInheritHandle flag so pipe handles are inherited.
sec_attr.nLength = sizeof(SECURITY_ATTRIBUTES);
sec_attr.bInheritHandle = TRUE;
sec_attr.lpSecurityDescriptor = NULL;
sec_attr.lpSecurityDescriptor = nullptr;
// Create a pipe for the child process's STDOUT.
if (!CreatePipe(&stdout_pipe_reader, &stdout_pipe_writer, &sec_attr, 0)) {
@@ -202,27 +202,27 @@ std::istream* Coprocess::stdout_pipe ()
void Coprocess::close_stdout ()
{
delete stdout_pipe_istream;
stdout_pipe_istream = NULL;
stdout_pipe_istream = nullptr;
if (stdout_pipe_writer) {
CloseHandle(stdout_pipe_writer);
stdout_pipe_writer = NULL;
stdout_pipe_writer = nullptr;
}
if (stdout_pipe_reader) {
CloseHandle(stdout_pipe_reader);
stdout_pipe_reader = NULL;
stdout_pipe_reader = nullptr;
}
}
void Coprocess::spawn (const std::vector<std::string>& args)
{
proc_handle = spawn_command(args, stdin_pipe_reader, stdout_pipe_writer, NULL);
proc_handle = spawn_command(args, stdin_pipe_reader, stdout_pipe_writer, nullptr);
if (stdin_pipe_reader) {
CloseHandle(stdin_pipe_reader);
stdin_pipe_reader = NULL;
stdin_pipe_reader = nullptr;
}
if (stdout_pipe_writer) {
CloseHandle(stdout_pipe_writer);
stdout_pipe_writer = NULL;
stdout_pipe_writer = nullptr;
}
}
@@ -243,7 +243,7 @@ int Coprocess::wait ()
size_t Coprocess::write_stdin (void* handle, const void* buf, size_t count)
{
DWORD bytes_written;
if (!WriteFile(static_cast<Coprocess*>(handle)->stdin_pipe_writer, buf, count, &bytes_written, NULL)) {
if (!WriteFile(static_cast<Coprocess*>(handle)->stdin_pipe_writer, buf, count, &bytes_written, nullptr)) {
throw System_error("WriteFile", "", GetLastError());
}
return bytes_written;
@@ -257,7 +257,7 @@ size_t Coprocess::read_stdout (void* handle, void* buf, size_t count)
// fails with ERROR_BROKEN_PIPE.
DWORD bytes_read;
do {
if (!ReadFile(static_cast<Coprocess*>(handle)->stdout_pipe_reader, buf, count, &bytes_read, NULL)) {
if (!ReadFile(static_cast<Coprocess*>(handle)->stdout_pipe_reader, buf, count, &bytes_read, nullptr)) {
const DWORD read_error = GetLastError();
if (read_error != ERROR_BROKEN_PIPE) {
throw System_error("ReadFile", "", read_error);

View File

@@ -28,6 +28,10 @@
* as that of the covered work.
*/
#include <openssl/opensslconf.h>
#if !defined(OPENSSL_API_COMPAT)
#include "crypto.hpp"
#include "key.hpp"
#include "util.hpp"
@@ -59,8 +63,8 @@ Aes_ecb_encryptor::Aes_ecb_encryptor (const unsigned char* raw_key)
Aes_ecb_encryptor::~Aes_ecb_encryptor ()
{
// Note: Explicit destructor necessary because class contains an auto_ptr
// which contains an incomplete type when the auto_ptr is declared.
// Note: Explicit destructor necessary because class contains an unique_ptr
// which contains an incomplete type when the unique_ptr is declared.
explicit_memset(&impl->key, '\0', sizeof(impl->key));
}
@@ -82,8 +86,8 @@ Hmac_sha1_state::Hmac_sha1_state (const unsigned char* key, size_t key_len)
Hmac_sha1_state::~Hmac_sha1_state ()
{
// Note: Explicit destructor necessary because class contains an auto_ptr
// which contains an incomplete type when the auto_ptr is declared.
// Note: Explicit destructor necessary because class contains an unique_ptr
// which contains an incomplete type when the unique_ptr is declared.
HMAC_cleanup(&(impl->ctx));
}
@@ -113,3 +117,4 @@ void random_bytes (unsigned char* buffer, size_t len)
}
}
#endif

119
crypto-openssl-11.cpp Normal file
View File

@@ -0,0 +1,119 @@
/*
* Copyright 2012, 2014 Andrew Ayer
*
* This file is part of git-crypt.
*
* git-crypt is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* git-crypt is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with git-crypt. If not, see <http://www.gnu.org/licenses/>.
*
* Additional permission under GNU GPL version 3 section 7:
*
* If you modify the Program, or any covered work, by linking or
* combining it with the OpenSSL project's OpenSSL library (or a
* modified version of that library), containing parts covered by the
* terms of the OpenSSL or SSLeay licenses, the licensors of the Program
* grant you additional permission to convey the resulting work.
* Corresponding Source for a non-source form of such a combination
* shall include the source code for the parts of OpenSSL used as well
* as that of the covered work.
*/
#include <openssl/opensslconf.h>
#if defined(OPENSSL_API_COMPAT)
#include "crypto.hpp"
#include "key.hpp"
#include "util.hpp"
#include <openssl/aes.h>
#include <openssl/sha.h>
#include <openssl/hmac.h>
#include <openssl/evp.h>
#include <openssl/rand.h>
#include <openssl/err.h>
#include <sstream>
#include <cstring>
void init_crypto ()
{
ERR_load_crypto_strings();
}
struct Aes_ecb_encryptor::Aes_impl {
AES_KEY key;
};
Aes_ecb_encryptor::Aes_ecb_encryptor (const unsigned char* raw_key)
: impl(new Aes_impl)
{
if (AES_set_encrypt_key(raw_key, KEY_LEN * 8, &(impl->key)) != 0) {
throw Crypto_error("Aes_ctr_encryptor::Aes_ctr_encryptor", "AES_set_encrypt_key failed");
}
}
Aes_ecb_encryptor::~Aes_ecb_encryptor ()
{
// Note: Explicit destructor necessary because class contains an unique_ptr
// which contains an incomplete type when the unique_ptr is declared.
explicit_memset(&impl->key, '\0', sizeof(impl->key));
}
void Aes_ecb_encryptor::encrypt(const unsigned char* plain, unsigned char* cipher)
{
AES_encrypt(plain, cipher, &(impl->key));
}
struct Hmac_sha1_state::Hmac_impl {
HMAC_CTX *ctx;
};
Hmac_sha1_state::Hmac_sha1_state (const unsigned char* key, size_t key_len)
: impl(new Hmac_impl)
{
impl->ctx = HMAC_CTX_new();
HMAC_Init_ex(impl->ctx, key, key_len, EVP_sha1(), nullptr);
}
Hmac_sha1_state::~Hmac_sha1_state ()
{
HMAC_CTX_free(impl->ctx);
}
void Hmac_sha1_state::add (const unsigned char* buffer, size_t buffer_len)
{
HMAC_Update(impl->ctx, buffer, buffer_len);
}
void Hmac_sha1_state::get (unsigned char* digest)
{
unsigned int len;
HMAC_Final(impl->ctx, digest, &len);
}
void random_bytes (unsigned char* buffer, size_t len)
{
if (RAND_bytes(buffer, len) != 1) {
std::ostringstream message;
while (unsigned long code = ERR_get_error()) {
char error_string[120];
ERR_error_string_n(code, error_string, sizeof(error_string));
message << "OpenSSL Error: " << error_string << "; ";
}
throw Crypto_error("random_bytes", message.str());
}
}
#endif

View File

@@ -57,7 +57,7 @@ public:
private:
struct Aes_impl;
std::auto_ptr<Aes_impl> impl;
std::unique_ptr<Aes_impl> impl;
public:
Aes_ecb_encryptor (const unsigned char* key);
@@ -102,7 +102,7 @@ public:
private:
struct Hmac_impl;
std::auto_ptr<Hmac_impl> impl;
std::unique_ptr<Hmac_impl> impl;
public:
Hmac_sha1_state (const unsigned char* key, size_t key_len);

12
debian/changelog vendored
View File

@@ -1,12 +0,0 @@
git-crypt (0.5.0-2) unstable; urgency=medium
* Build against OpenSSL 1.0.x. (Closes: #828312)
* Bump standards version (no changes needed).
-- Andrew Ayer <agwa@andrewayer.name> Wed, 23 Nov 2016 12:51:51 -0800
git-crypt (0.5.0-1) unstable; urgency=medium
* Initial release. (Closes: #785346)
-- Andrew Ayer <agwa@andrewayer.name> Sat, 30 May 2015 20:22:22 -0700

1
debian/compat vendored
View File

@@ -1 +0,0 @@
9

24
debian/control vendored
View File

@@ -1,24 +0,0 @@
Source: git-crypt
Maintainer: Andrew Ayer <agwa@andrewayer.name>
Section: vcs
Priority: optional
Standards-Version: 3.9.8
Build-Depends: debhelper (>= 9), libssl1.0-dev | libssl-dev (<< 1.1.0~), xsltproc, docbook-xml, docbook-xsl
Vcs-Git: https://www.agwa.name/git/git-crypt.git -b debian
Homepage: https://www.agwa.name/projects/git-crypt
Package: git-crypt
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}, git (>= 1.7.2)
Recommends: gnupg
Enhances: git
Description: Transparent file encryption in git
git-crypt enables transparent encryption and decryption of files in a
git repository. Files which you choose to protect are encrypted when
committed, and decrypted when checked out. git-crypt lets you freely
share a repository containing a mix of public and private content.
git-crypt gracefully degrades, so developers without the secret key
can still clone and commit to a repository with encrypted files.
This lets you store your secret material (such as keys or passwords)
in the same repository as your code, without requiring you to lock down
your entire repository.

64
debian/copyright vendored
View File

@@ -1,64 +0,0 @@
Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: git-crypt
Source: https://www.agwa.name/projects/git-crypt
Files: *
Copyright: Copyright 2012-2015 Andrew Ayer
License: GPL-3+ with OpenSSL exception
Files: fhstream.cpp fhstream.hpp parse_options.cpp parse_options.hpp
Copyright: Copyright 2012, 2014, 2015 Andrew Ayer
License: X11
License: GPL-3+ with OpenSSL exception
git-crypt is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
.
git-crypt is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
.
You should have received a copy of the GNU General Public License
along with git-crypt. If not, see <http://www.gnu.org/licenses/>.
.
On Debian systems, the full text of the GNU General Public
License version 3 can be found in the file
`/usr/share/common-licenses/GPL-3'.
.
Additional permission under GNU GPL version 3 section 7:
.
If you modify the Program, or any covered work, by linking or
combining it with the OpenSSL project's OpenSSL library (or a
modified version of that library), containing parts covered by the
terms of the OpenSSL or SSLeay licenses, the licensors of the Program
grant you additional permission to convey the resulting work.
Corresponding Source for a non-source form of such a combination
shall include the source code for the parts of OpenSSL used as well
as that of the covered work.
License: X11
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
.
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
.
Except as contained in this notice, the name(s) of the above copyright
holders shall not be used in advertising or otherwise to promote the
sale, use or other dealings in this Software without prior written
authorization.

5
debian/gbp.conf vendored
View File

@@ -1,5 +0,0 @@
[DEFAULT]
pristine-tar = True
pristine-tar-commit = True
debian-branch = debian
upstream-tag = %(version)s

View File

@@ -1,8 +0,0 @@
CONTRIBUTING.md
NEWS
NEWS.md
README
README.md
RELEASE_NOTES-0.4.1.md
RELEASE_NOTES-0.4.md
THANKS.md

7
debian/rules vendored
View File

@@ -1,7 +0,0 @@
#!/usr/bin/make -f
export PREFIX=/usr
export ENABLE_MAN=yes
%:
dh $@

View File

@@ -1 +0,0 @@
3.0 (quilt)

View File

@@ -1 +0,0 @@
single-debian-patch

View File

@@ -1,17 +0,0 @@
Subject: Collected Debian patches for git-crypt
Author: Andrew Ayer <agwa@andrewayer.name>
Since I am also upstream for this package, there will normally not be
any patches to apply to the upstream source. However, occasionally
I'll pull up specific upstream commits prior to making an upstream
release. When this happens, this patch will collect all of those
modifications.
I use Git to maintain both the upstream source and the Debian
packages, and generating individual patches rather than using git
cherry-pick takes extra work for no gain. Since I'm also upstream,
there's no need to separate the patches for later upstream submission.
Hence, I take this approach with a unified patch when it's necessary.
For full commit history and separated commits, see the upstream Git
repository.

View File

@@ -1,135 +0,0 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
mQINBFNTDEsBEACiZ+AWNaj80CvSIV9T+mlPClETM+pxEHuB+vldasG+BWsyyb2d
AH390MSjXzs4RaiDGAXgZKnP9bhlWV/6BYcF0edz+G+Ux89L+D/c6miWFqwywQ7G
FRBh10WDriNbSF6UoD6TJX9Kc2KIgeDQ7LFL1PsiFjsO/cUBfDmSvMWd/zzIV4Ug
QdqFjjHdPSTr5w9D5YDS5FY2UOmcrxyNU66PoGkIp0Cqjgaieszxx3/CkGtktn0T
M/dwP+yafgH5uUDRfgFR5McTvu4E53CAimsiv05wodXmnoELojVDrEYciJIrfGRx
fCj+tiWsz0IcJCJ/ND1UExlI5so5tx0YaYMapx3PCb7+ZrZEUrRa3xK6m+ZU2Qfk
XQJmUSnKuIsKP4Uo8ysMPxDuWrCap4nxw2uNsGgPXXnExJgVoWfyR0qMr16+BUSu
Yrtfng19npv/Y381Y6hB8uRWRNRbaG8MEAHrgdPkb6853cbXT6A+k3KbZJVcEZsv
XCS2lFuWaZTQGA1G4mj7TbudjvHLuDV8VbPsyxotgAHITSh6pekBuJFPOVhAZN41
HyPNMZnE7eoW6DmShrdC+TjIVpzliqiLytDfGabIMNbnQDWdHxhzqq/Vn07ObOVp
0MGn7PaGeyF+rmi0h1ttab3Dioku49dljjuz+uNhBcu1CB/CegIdtRVyDwARAQAB
tCJBbmRyZXcgQXllciA8YWd3YUBhbmRyZXdheWVyLm5hbWU+iQI6BBMBCAAkAhsB
BQsJCAcDBRUKCQgLBRYDAgEAAh4BAheABQJTUwz6AhkBAAoJEBA3jvwggAgM0BwQ
AI8tAYxpeHyN+6StVAiu+wY2n2SNuunsORVmqyiICDOruxPTr4ulsP8vKM7Y4L9H
lpJqfW/g65cByuZ48dFciQmI97RfZjjZgAxejM1dq/Y0RJGpZ6I7pNNbWIxvDm7o
8mMeEQYT5S4vZKmreYZpzjLLZin+3gpBfljapGRikZNC1dzQu5JA0iCkWqIWmgto
O/kEmGKID9ShLB0H/f26K+jKfKuQ2unqlPgUPlQfd65yBN0m0SaESozs5hnCjMxS
oJSDnI0Kst0W/E/c0RZp5WJ3PECqnV0ru7xazMPLP3yNMrJVv3s6rKdiwzkQYUDj
10KxCDOChc9UfVRZfiVc4OlnK77L5EM3AWLrNOwx8ntcs67hJXrppoDVin87PyMG
SJE+DNKZk40oHLIrWCE43zS8p0k4OSGpJhiVev/o2FJImIiZXdYrm0gA3rA5OOM2
nDSyPlB0kOzMN03z7pzT319OMhf5KZgYRuoAU59IqdW+Iz2q1vfusuh0UU5GfP+U
XOuiiv9O9VqPTxpDOzmk5qnw8p3NNdwnqzop64wcBsNebyWGM52Hetd8bIwdFniI
XsBhzRxnMVmNdXwQ7zhPKwpgGA9vWkyZ15EuhDK0Wc3XQf51NWVjY9Pt/NgpwKli
CEqnd+sUszM78jXhvZjsWEkophudU6O615zYEEpTe+b/tB5BbmRyZXcgQXllciA8
YW5kcmV3QGFnd2EubmFtZT6JAjcEEwEIACEFAlNTDM8CGwEFCwkIBwMFFQoJCAsF
FgMCAQACHgECF4AACgkQEDeO/CCACAxWoA/+NYvxCoJ4V/TGZnYQJxT95qK+8uGS
sQmlAYlIbYAAr0zxe1+U0HxMVMh0pj211B8Nd6Qq46X2ZYmWSyAPA6tiiSg+Y5C9
2IGyCZ11oG98Op99nnPOEnKAPVgTtGgpMeomTPo768ucj0kvvbibGg3yMs1JBH2p
wBULHZLCswlKzDOgg4YZfa5eicXRJOjl1EVbdhPyMZrnJB5bFnkno8rSIJ1h3QkV
kWAJ0bPggHxsWiYOEJUjEkzr4zXjcCJKIyPWY9rZcgJNvo1Bwqx/E7Cs+XABuPtU
0OPIysXROANzsUMVt0NpcSJsAPJxt5L5EoCVRhTDjaK6kXglEcxqOqSzTsu61cKj
MAAyZY+qfTA2ILzPYgxiy+h4ReUxAHx0Bzd7w6L+tn1aPlc9nqDm1nzk9U8rzA5j
XDJJJOuC5yCzhQ2tpsAp/RRE+1sgiGV8D+LSXf2ZYBQbV9V6icFdhHUrqKzQsw7m
5C4n2Fk1wk54JTFO1j4rWarHiVeKuKWiBrQhhUJqFtJ/lpr6tIVsI5KuoWczHpQ0
RhCnUNFPj1JaMM09pLEkg9u/RRrVo6eSHy0vHKCqYZYUAldTGpE18kRlpTDgrN8T
jhBaiFrk8PBKPiE4Pt+5BgDZr8jP+CWA9Bc06E6EtV+fDdTexAj2Uw0JE0zZdhQc
1J1NNIMHc4WpS6+0JEFuZHJldyBBeWVyIDxhbmRyZXdAYW5kcmV3YXllci5uYW1l
PokCNwQTAQgAIQUCU1MMjQIbAQULCQgHAwUVCgkICwUWAwIBAAIeAQIXgAAKCRAQ
N478IIAIDDg1EACQ+stApB16L54LnS7YMFUHeUgaG3Hfu+WmIrvRn5UcT4hxRNsY
/c7nDumrwAmg8HiOXwe7V8MJMFUEEoQylWpYLFzOTlwDmVGUMczQScgi7RvK9zwJ
0475Wlpr/7wUrG0LyinLVf7GoKPtIkefzlydTzMu4xSr52t1sSGQqcWXDVJ2bCGf
KuvmDpv1gOORdp4g2lI0wOPWgPzm4ctqhzT58jFR5vQpzpr+H0qB35prcKa9TAIG
sbtF1bdSaOBkXev/IFhY07Fq35aqEuv27+aMJkYjhzIVSnm+/9Io/1L0RTpHZpgc
px08yfllq7Vf0buCiC8uEvdFVL4sHOlp9gVU21boLj4JJnZvlJ1m+gfIMAfhtt4R
2QNxKxC+jO2bBvj4j9dHBz0MQvAoJl121cjOAxZGMHye3eV0sHtE7UntxA5pQQv0
U2hx7A70yAlN2Np76xVDO9cae4aVUV7lCdY14L9e5Ww4mAknFMeIgbkoxWT2lMA+
1pfn541c6XUuuNfr1D9flYHbDFEYTUOFZ6ypAgOxkK+/wPYlz4d6MTBJ4fcoEhSF
qX0JVFW8Jrnqs4GsDmej9dibfYdk2a0qG69oSRF8Bujxdh41R+/C03LSnRBXhjHJ
SG/xSYoCcOL6y3aiJb2gK2lbrLxmeysCn7goGPp16VikSxHNFJkigRUqDbQhQW5k
cmV3IEF5ZXIgPGFnd2FAYW5kcmV3YXllci5jb20+iQI3BBMBCAAhBQJTUwyrAhsB
BQsJCAcDBRUKCQgLBRYDAgEAAh4BAheAAAoJEBA3jvwggAgMfWsP/2F+Ds4lIn7p
rdgEeK2kT4Sxn4ldATU8ZKjVe/RnTxWx+jqEHdsXkUAVEHNuUPYwtvETub2mMFBr
lguL1WWW09J1ihYEk4ErDT81kNP+8cGGDjLkv8FWjlLPUGrcZRMj52JP0saW7AIJ
2/OxvpC00xkpb5goy5yXUKVgzBhVUAcSx1a3vY92y+RnmcwhnQmlhAy+xpyO0Ju+
dEhNfBny+gc/YdWfha6sWed6fL0VWut2l1euEU9WIH/Mcd8NWGs10ez9iqVhRWi3
zpTWxkVBY0+PaPaHkqh6N3cCDEdFXXmVtP3nPvC+4k6vIUK+frIIffjDlOXhXaPB
bGZ2SyJcYJdsh6Lb3cnQ2ISHrlKy2CgVkExdgz8JeSF296OInQJmS/U9XFH2iN/w
Yivi93pUV9xvPaJTXOSUMA+szKXapPTH8zUNQ99tm7KiwV0aMXWKG0iNxjg7C0kO
vVuKGBKEpFdyNLL7uAE/bzs7WVZ8ztebZJTlScIU7KZUr931kR++VAzIFr7yYlaC
4c2TjiinStFsHgfRqaVoJfQIWQzxrli46LkaIVur3rzBJERNSpDcPlpF1wngXkFo
Jqt+c7MTVBeoaaAv5TAK0a/D027fUNtAyxtCPmkoHs6BWh38NDGO7VNBRNog0Vnm
ItcFmFtM0rcQV6DbUjUZdTYygPGq0MAWtCNBbmRyZXcgQXllciA8YW5kcmV3QGFu
ZHJld2F5ZXIuY29tPokCNwQTAQgAIQUCU1MMwgIbAQULCQgHAwUVCgkICwUWAwIB
AAIeAQIXgAAKCRAQN478IIAIDDN4D/0eINLgeE2mHs68kM6fXRf0jfDdyVYMvxnK
ZO0jq1sjurEYgw+tHQRHo5bsu52E1yneoam5pzucu6TXUVc2X7dGKfuqvsU55+Qo
IlqE0ai0tXlmc7orVzZFgLCTGrZgL2NL208h3EvlSeqy//6yA/rirMIRiD/vSb3A
u0EBXSav+x/o092W904jPzeLGGL9c9G6HxmAzGxRO0q5FfB7u1sI9bpgljC3mBVb
jUhD/ynIwkIZfTgQFRlBHtzy0HpcnlzxzcY7b/SB+8was1aEDetzuEeXOdTDXxd6
gVBFDZMyKtZU5jsprZDU6/nleka6/ji6ZMNIJvMgcJbgwV3i/ipKH3FfItcnTt+F
gx2q3j/pVYPyKo05tp2dBCgdyEKsTgc+QTqo0EOk5to8Gz7ebkyPGIELqIfBtPjp
hoB9oTpgmnAsgSnSGDfz4yD+8uU3FBOjrMNe5tucq+N8VVYZhCQFs8fAbrghh568
ahBcLDu4n9OvjZz5hHnpARtSOw2WmLdQ43JAnFa6F8rN98ymlP6X8CT3lTnPwkRL
+9l008KXP64nZStISozKwDb4zMfRn7iHbqs6reIlvgIOevkiMmPTyhhQ0zz6aLwy
ZNcQPK7wdXtynPydzAPfKbxfQkVpkQb/mgBgr2blZSu4Z5W491tDOTI/MF0gMTfA
eqavC9PhRrkCDQRTUw1OARAAyr3w+DujjQ+oiLrlnGu+DArnxK5lf8DzeVokFlSX
TJXSgCl4niJeQhodn3EtnDRdKimdvMxgW+iVU4MKhK/2xbf0rNSQDJv4iIub0wHH
Y8kkqsBU3vDjoTYraoFMjKWIvZEr9FJTiDgX4VruJAhwydjknrSWdK7As9PzqU0l
C7ReHRJIJLu20EeVCVoGuyVmRfendTXDbflvZhUhTitcgJbNek272u521lYbk3g1
knMWhwmdsy95ZqNbjk4iMJ6eq4l2MA/yka4V4zA7P9L0WBjuFyImVix4WyaF+TIN
/t8eX+zF6VfImoKlMer8qpMmGaFBKxOdGdAH+YpoP8sysSrFDV0iSbA/WwbNa4e7
F8eras4B/sFWIldXlSd0yLqdNe8ZB0vPDS44tNcmDYz3cWIH1mDF1AbHDBbOxwa+
FkcHDPjYrnIQbFI3Z+rzOqc8vOeiNPHggPSDRjM6duah4aOLp6RYEYc/2ouO1yMD
UlWQ+eGDvqAvIt3HH2y78fbkl3K2VVA+gd5w9oxDKxXKZxp/y5RVVYCZUAv1lllT
87dRMXignTVEIsF8VdESrHhRYUQW+2wP40hKZIPEaWS5BSH/d/qGgDSBsVPbDlas
4n3FJ+SVil6xm0hJ+29Xw/GDMc+uQfs8TkPxbM0cjn59oZb6I3Zhxy+KWSxdCN2g
8nMAEQEAAYkERAQYAQgADwIbAgUCU1MO8wUJB4TPXQIpwV0gBBkBCAAGBQJTUw1O
AAoJEJ0V9ORH5MgyJTQP/0cSeXYZ+G7EKEjM+xHfjUyNavahVZ+rfiLzZpU+os4s
SGwd4annJ4Z56UMA+1U5Qm34+rH+E72qTJAEhg512CQJnFejVKqBuVzBsxaO5aLK
nSafGk3Ixev4JraspFtDmSflVHrQFVKeu3oF+tjE2elHHhhV8I1N8eA2HTiwlTpD
9RgQ1nFw9KM4+ncBm56dK3lVQbgT7XPz6noIPhXpAKH1THthvIyjUDyTqeRUrgHL
eeFtKXWnsiUMi5z3dz1lK0QacGaykl+VtLXlUIffh7IpLp3MoiaboXV2UdocIrZ3
vg00wBrZ01w7L10LB0Jl1NEH5ccbezAVCaW3/2MT6C7BnQZqpjQiKncrnx2YoupJ
+OWJT2QOQoLOKwL4ShHB8Dae4RD0aTcmTTVBEteSvH32hhcsXChMi1Dzsf6cvNmV
pl54VkfWmZqyfTl7LjqpQsOcUtDshFPQMziKF8pSyhSYiuImvLFwypTe4KtDqA/U
d1v9XB40mniAUTC5dWO+80MhOB4NpXNNSXP22DzpDZvfhdTxSCwc70bpWJIRVpuT
gVvVjqOiCVanNXqwh14Nn+/SaRDx19BglXhniBWNEXN8f2dhI3YkZ2ovS/t6mfxn
aymghsKL1yvu8zdTFZsmAhYdpTBIB9zMjoNs3TNb8I+X26oPUjSKZ1/+oAacGTtJ
CRAQN478IIAIDBXvD/sG09+tMC30Tcq6DuycebKiuHfIioBdWTNLTz3Pahi0C/4e
WDcd0H8hcxUz9cdBnUs5uvUwdo07bqVb+zJ0PidDdCpCSDwNH9Zn98Duy7QVPtAU
psPApSe2Y23zh4tr37c31dlUIsRCiGfjIjjoCFg3NZMxmw4y3UhUMPNemDt+rB+t
XmstUc03xdaUrrssAxZf/qhNy9tPucHGl1Uuq1c8ANhdgmosMacfxb9i/kcCErTl
Kz3DwZPVdE4Q/KcaiTOBxBthlvpZM27h//BeT/Yo2Hy/X7nzhhyscPqaDj/HOCbt
O/wyH/kv4z++bzy7FSERMJTQvAaYEbhWE71l+sSBJT1ZJnafDXX+b9ZlSE7Im5C8
mjGc1XX9Mw1eXzLh7wiC+BEEr4S9qOkyKtSKcQ/m+UjOARXrqA1qhDp1mmhSVNsW
UnhWabsO9TwxcRdSX98ql+rNYBjN7tsqzq3G3R3oFeaGevAqPqJFbAFhGhB33UP1
yolOPxGP6u2NdNFmGQ2vVlzJNzY5QAk2cekIZWJLd8YEcXeijPo1BX4eTg4V6d61
EWIKoSHBeKVwhuCg9l6ZFrNzUoHGP4yKDXJood71KBulDSSUkzIM05ngfcajz1RS
R9szqJlNAuLHpQHOZEI1k38sQrnPoqwzyshgU7S/vLAT6hr666bJ2i9l82X077kC
DQRTUw4RARAA30ouhOBeAX4ORzDmeyP9MjuDZWArkJv22PI5ijISIyRjUdYogvqY
XAm2z0RTzD4waW9lSabumDqVGd5MzTm0GTaIw/E+7rx08vnBVRlHLpAOZMUogNEG
p+3uXhgHmar0uhVhYar1v6SUqscray+wtnkRnXQkitkD0zzTWGx17LnWPOguNDsU
uYjWoAYgEiS9g3UYLfexQRVxae7n6YTDedNfjuMKAmmc+ixWDHQ9Dcjc4oJacV5z
iz78NYdXoPA3101lKPzUGqRye/Rvm0/GXzht5nhsIMB/X/FIk6qlbCAP/VpVRpYD
KE7N3juJY7jwoCze9d3TZx6jU8IR/rD1uuDW/gjyPVAHAcE1fRwjErtR1TsFcXdY
wtTJx+Rzq6gaS1mfeV90/V2RY0i+nqGhmY+o+lLt1uozX3iTO2X9cF/REp9i6Rly
TOUMAPW7mOryN9Yv/WAkG4S/WgtnZRCA0M88jFSgX8go+Y2Z6yAUynEXDREH9VMI
rw0kNhvOzfWSAyBOuNfNrehShR6RMtAKs/JC+VEwhvDD+avFNHywpn7fGMa2WqFw
x337Yz6wARJ5g9vBCMJBWMhWT62cMQK62TLVkW5lbULSVwUAsbNyZMaQks7kfas3
9w3gr66Bc/2v4PaQMUQ3I79yO/f6zsxu9vZ1yxPtKOGwGHQvnCdRMlMAEQEAAYkC
JQQYAQgADwIbDAUCU1MPDQUJB4TO+QAKCRAQN478IIAIDFQcEACFi6e4/++dhkPT
e1dnaifmSINXthSFkOAp8OR0mK2/0Ged6UmbyxPd7gKQJUXFV5Mz5Sj8G6N4YCLl
+55k67gwZwzZ62EYB41FnjkXKILBgP+mt2c0SCuwwwz9g8Jx351l2Cfatz6SoviE
XjQURDHPxsqK1mfKMmoMWo4Ii68hzKrBg0mcdxeJeYj/t8l0ug2JQApnJsaE+5QC
3U9txBYm1Rpsaz/IFvlGJS9CkZyQA7ci/eMmoKn+/R8Gk48avkM0vFmUz9T8saIr
g0F5T7ThjC8575PNtInpDZRp9V3PdeKtiA9Fky11fNi0VS7luurKQ3I0UJfdyxe1
Sb/kvwSu++zEDEG5/li4GfMBqiZTV6oZJ9fzZnrGjEyiRSLN7GA4T1KC795zm/63
MrTaTf/3G6iRLNcvEdcWTiSHlFSkpx+qQHoijs0KU6uzdvHwtKKX/UBrk837SOFL
AEqn8ebsOKYiO4gA0ismpAt9NQwqsKq0rhyZAIDl9hSjwGBqX24NA7qnkoZNZySC
YBn0ZZRr3VGyeNWgtZg/KIiyKX7xmEUgBswt/U42x5wG3SdhAiSn6If/y8dTpfzT
kXF2+jp/tbGpm1qHi6qrkdMqCHCf67beh9SmlKa8nYyb1fpEcNBBElA8AAFgaYKh
zZq3C24mS3JwlqDwjT/Ut1/tChr3wQ==
=ZMwd
-----END PGP PUBLIC KEY BLOCK-----

2
debian/watch vendored
View File

@@ -1,2 +0,0 @@
version=3
opts=pgpsigurlmangle=s/$/.asc/ https://www.agwa.name/projects/git-crypt/ .*/git-crypt-(\d.*)\.(?:zip|tgz|tbz|txz|(?:tar\.(?:gz|bz2|xz)))

View File

@@ -31,7 +31,7 @@
#ifndef GIT_CRYPT_GIT_CRYPT_HPP
#define GIT_CRYPT_GIT_CRYPT_HPP
#define VERSION "0.5.0"
#define VERSION "0.6.0"
extern const char* argv0; // initialized in main() to argv[0]

20
gpg.cpp
View File

@@ -30,8 +30,18 @@
#include "gpg.hpp"
#include "util.hpp"
#include "commands.hpp"
#include <sstream>
static std::string gpg_get_executable()
{
std::string gpgbin = "gpg";
try {
gpgbin = get_git_config("gpg.program");
} catch (...) {
}
return gpgbin;
}
static std::string gpg_nth_column (const std::string& line, unsigned int col)
{
std::string::size_type pos = 0;
@@ -62,7 +72,7 @@ std::string gpg_get_uid (const std::string& fingerprint)
{
// gpg --batch --with-colons --fixed-list-mode --list-keys 0x7A399B2DB06D039020CD1CE1D0F3702D61489532
std::vector<std::string> command;
command.push_back("gpg");
command.push_back(gpg_get_executable());
command.push_back("--batch");
command.push_back("--with-colons");
command.push_back("--fixed-list-mode");
@@ -94,7 +104,7 @@ std::vector<std::string> gpg_lookup_key (const std::string& query)
// gpg --batch --with-colons --fingerprint --list-keys jsmith@example.com
std::vector<std::string> command;
command.push_back("gpg");
command.push_back(gpg_get_executable());
command.push_back("--batch");
command.push_back("--with-colons");
command.push_back("--fingerprint");
@@ -125,7 +135,7 @@ std::vector<std::string> gpg_list_secret_keys ()
{
// gpg --batch --with-colons --list-secret-keys --fingerprint
std::vector<std::string> command;
command.push_back("gpg");
command.push_back(gpg_get_executable());
command.push_back("--batch");
command.push_back("--with-colons");
command.push_back("--list-secret-keys");
@@ -154,7 +164,7 @@ void gpg_encrypt_to_file (const std::string& filename, const std::string& recipi
{
// gpg --batch -o FILENAME -r RECIPIENT -e
std::vector<std::string> command;
command.push_back("gpg");
command.push_back(gpg_get_executable());
command.push_back("--batch");
if (key_is_trusted) {
command.push_back("--trust-model");
@@ -174,7 +184,7 @@ void gpg_decrypt_from_file (const std::string& filename, std::ostream& output)
{
// gpg -q -d FILENAME
std::vector<std::string> command;
command.push_back("gpg");
command.push_back(gpg_get_executable());
command.push_back("-q");
command.push_back("-d");
command.push_back(filename);

View File

@@ -7,8 +7,8 @@
-->
<refentryinfo>
<title>git-crypt</title>
<date>2015-05-30</date>
<productname>git-crypt 0.5.0</productname>
<date>2017-11-26</date>
<productname>git-crypt 0.6.0</productname>
<author>
<othername>Andrew Ayer</othername>

View File

@@ -125,40 +125,20 @@ void mkdir_parent (const std::string& path)
}
}
static std::string readlink (const char* pathname)
{
std::vector<char> buffer(64);
ssize_t len;
while ((len = ::readlink(pathname, &buffer[0], buffer.size())) == static_cast<ssize_t>(buffer.size())) {
// buffer may have been truncated - grow and try again
buffer.resize(buffer.size() * 2);
}
if (len == -1) {
throw System_error("readlink", pathname, errno);
}
return std::string(buffer.begin(), buffer.begin() + len);
}
std::string our_exe_path ()
{
try {
return readlink("/proc/self/exe");
} catch (const System_error&) {
if (argv0[0] == '/') {
// argv[0] starts with / => it's an absolute path
return argv0;
} else if (std::strchr(argv0, '/')) {
// argv[0] contains / => it a relative path that should be resolved
char* resolved_path_p = realpath(argv0, NULL);
std::string resolved_path(resolved_path_p);
free(resolved_path_p);
return resolved_path;
} else {
// argv[0] is just a bare filename => not much we can do
return argv0;
}
if (argv0[0] == '/') {
// argv[0] starts with / => it's an absolute path
return argv0;
} else if (std::strchr(argv0, '/')) {
// argv[0] contains / => it a relative path that should be resolved
char* resolved_path_p = realpath(argv0, nullptr);
std::string resolved_path(resolved_path_p);
free(resolved_path_p);
return resolved_path;
} else {
// argv[0] is just a bare filename => not much we can do
return argv0;
}
}
@@ -169,7 +149,7 @@ int exit_status (int wait_status)
void touch_file (const std::string& filename)
{
if (utimes(filename.c_str(), NULL) == -1 && errno != ENOENT) {
if (utimes(filename.c_str(), nullptr) == -1 && errno != ENOENT) {
throw System_error("utimes", filename, errno);
}
}
@@ -199,19 +179,6 @@ int util_rename (const char* from, const char* to)
return rename(from, to);
}
static size_t sizeof_dirent_for (DIR* p)
{
long name_max = fpathconf(dirfd(p), _PC_NAME_MAX);
if (name_max == -1) {
#ifdef NAME_MAX
name_max = NAME_MAX;
#else
name_max = 255;
#endif
}
return offsetof(struct dirent, d_name) + name_max + 1; // final +1 is for d_name's null terminator
}
std::vector<std::string> get_directory_contents (const char* path)
{
std::vector<std::string> contents;
@@ -221,19 +188,23 @@ std::vector<std::string> get_directory_contents (const char* path)
throw System_error("opendir", path, errno);
}
try {
std::vector<unsigned char> buffer(sizeof_dirent_for(dir));
struct dirent* dirent_buffer = reinterpret_cast<struct dirent*>(&buffer[0]);
struct dirent* ent = NULL;
int err = 0;
while ((err = readdir_r(dir, dirent_buffer, &ent)) == 0 && ent != NULL) {
if (std::strcmp(ent->d_name, ".") == 0 || std::strcmp(ent->d_name, "..") == 0) {
continue;
errno = 0;
// Note: readdir is reentrant in new implementations. In old implementations,
// it might not be, but git-crypt isn't multi-threaded so that's OK.
// We don't use readdir_r because it's buggy and deprecated:
// https://womble.decadent.org.uk/readdir_r-advisory.html
// http://austingroupbugs.net/view.php?id=696
// http://man7.org/linux/man-pages/man3/readdir_r.3.html
while (struct dirent* ent = readdir(dir)) {
if (!(std::strcmp(ent->d_name, ".") == 0 || std::strcmp(ent->d_name, "..") == 0)) {
contents.push_back(ent->d_name);
}
contents.push_back(ent->d_name);
}
if (err != 0) {
throw System_error("readdir_r", path, errno);
if (errno) {
throw System_error("readdir", path, errno);
}
} catch (...) {
closedir(dir);
throw;

View File

@@ -46,12 +46,12 @@ std::string System_error::message () const
LPTSTR error_message;
FormatMessageA(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
nullptr,
error,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
reinterpret_cast<LPTSTR>(&error_message),
0,
NULL);
nullptr);
mesg += error_message;
LocalFree(error_message);
}
@@ -100,7 +100,7 @@ void mkdir_parent (const std::string& path)
std::string prefix(path.substr(0, slash));
if (GetFileAttributes(prefix.c_str()) == INVALID_FILE_ATTRIBUTES) {
// prefix does not exist, so try to create it
if (!CreateDirectory(prefix.c_str(), NULL)) {
if (!CreateDirectory(prefix.c_str(), nullptr)) {
throw System_error("CreateDirectory", prefix, GetLastError());
}
}
@@ -114,7 +114,7 @@ std::string our_exe_path ()
std::vector<char> buffer(128);
size_t len;
while ((len = GetModuleFileNameA(NULL, &buffer[0], buffer.size())) == buffer.size()) {
while ((len = GetModuleFileNameA(nullptr, &buffer[0], buffer.size())) == buffer.size()) {
// buffer may have been truncated - grow and try again
buffer.resize(buffer.size() * 2);
}
@@ -132,7 +132,7 @@ int exit_status (int status)
void touch_file (const std::string& filename)
{
HANDLE fh = CreateFileA(filename.c_str(), FILE_WRITE_ATTRIBUTES, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
HANDLE fh = CreateFileA(filename.c_str(), FILE_WRITE_ATTRIBUTES, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr);
if (fh == INVALID_HANDLE_VALUE) {
DWORD error = GetLastError();
if (error == ERROR_FILE_NOT_FOUND) {
@@ -146,7 +146,7 @@ void touch_file (const std::string& filename)
FILETIME file_time;
SystemTimeToFileTime(&system_time, &file_time);
if (!SetFileTime(fh, NULL, NULL, &file_time)) {
if (!SetFileTime(fh, nullptr, nullptr, &file_time)) {
DWORD error = GetLastError();
CloseHandle(fh);
throw System_error("SetFileTime", filename, error);