From 23e6e7382a21937b0c6bb13b17236745012486d9 Mon Sep 17 00:00:00 2001 From: bySabi Files Date: Tue, 4 Feb 2014 17:29:26 +0100 Subject: [PATCH 01/16] fist compile --- .gitignore | 1 + Makefile | 4 +- Util_win32.cpp | 334 +++++++++++++++++++++++++++++++++++++++++++++++++ crypto.cpp | 6 +- util.cpp | 2 + 5 files changed, 344 insertions(+), 3 deletions(-) create mode 100644 Util_win32.cpp diff --git a/.gitignore b/.gitignore index 81afb4a..55b70cc 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ *.o +*.exe git-crypt diff --git a/Makefile b/Makefile index c5f339b..da97f9e 100644 --- a/Makefile +++ b/Makefile @@ -1,9 +1,9 @@ CXX := c++ CXXFLAGS := -Wall -pedantic -ansi -Wno-long-long -O2 -LDFLAGS := -lcrypto +LDFLAGS := -lcrypto -lwsock32 PREFIX := /usr/local -OBJFILES = git-crypt.o commands.o crypto.o util.o +OBJFILES = git-crypt.o commands.o crypto.o util.o util_win32.o all: git-crypt diff --git a/Util_win32.cpp b/Util_win32.cpp new file mode 100644 index 0000000..3ac74d4 --- /dev/null +++ b/Util_win32.cpp @@ -0,0 +1,334 @@ +#ifdef __WIN32__ +#undef __STRICT_ANSI__ //needed for _fullpath +#include +#include +#include + +#include +#include +#include +#include + + +#define unlink _unlink + + +void LaunchChildProcess(HANDLE hChildStdOut, + HANDLE hChildStdIn, + HANDLE hChildStdErr, + const std::string command); +void ReadAndHandleOutput(HANDLE hPipeRead, std::ostream& output); +void ArgvQuote (const std::string& Argument, + std::string& CommandLine, + bool Force); +int mkstemp(char *name); +void DisplayError(LPCSTR wszPrefix); + +//do nothing on windows +static inline mode_t umask(mode_t mask){ return -1; } + + +int exec_command (const char* command, std::ostream& output) +{ + HANDLE hOutputReadTmp,hOutputRead,hOutputWrite; + HANDLE hErrorWrite; + SECURITY_ATTRIBUTES sa; + + // Set up the security attributes struct. + sa.nLength= sizeof(SECURITY_ATTRIBUTES); + sa.lpSecurityDescriptor = NULL; + sa.bInheritHandle = TRUE; + + // Create the child output pipe. + if (!CreatePipe(&hOutputReadTmp,&hOutputWrite,&sa,0)) + DisplayError("CreatePipe"); + + + // Create a duplicate of the output write handle for the std error + // write handle. This is necessary in case the child application + // closes one of its std output handles. + if (!DuplicateHandle(GetCurrentProcess(),hOutputWrite, + GetCurrentProcess(),&hErrorWrite,0, + TRUE,DUPLICATE_SAME_ACCESS)) + DisplayError("DuplicateHandle"); + + // Create new output read handle. Set + // the Properties to FALSE. Otherwise, the child inherits the + // properties and, as a result, non-closeable handles to the pipes + // are created. + if (!DuplicateHandle(GetCurrentProcess(),hOutputReadTmp, + GetCurrentProcess(), + &hOutputRead, // Address of new handle. + 0,FALSE, // Make it uninheritable. + DUPLICATE_SAME_ACCESS)) + DisplayError("DuplicateHandle"); + + // Close inheritable copies of the handles you do not want to be + // inherited. + if (!CloseHandle(hOutputReadTmp)) DisplayError("CloseHandle"); + + // Prepare command arg + std::string cmd("sh.exe -c "); + ArgvQuote(command, cmd, TRUE); + + // Launch child process with "cmd" + LaunchChildProcess(hOutputWrite ,NULL ,hErrorWrite, cmd); + + // Close pipe handles (do not continue to modify the parent). + // You need to make sure that no handles to the write end of the + // output pipe are maintained in this process or else the pipe will + // not close when the child process exits and the ReadFile will hang. + if (!CloseHandle(hOutputWrite)) DisplayError("CloseHandle"); + if (!CloseHandle(hErrorWrite)) DisplayError("CloseHandle"); + + // Read the child's output. + ReadAndHandleOutput(hOutputRead, output); + + if (!CloseHandle(hOutputRead)) DisplayError("CloseHandle"); + + return 1; +} + +std::string escape_shell_arg(const std::string& str) +{ + std::string escape_str; + ArgvQuote(str, escape_str, TRUE); + return escape_str; +} + +std::string resolve_path (const char* path) +{ + char retname[_MAX_PATH]; + _fullpath(retname, path, _MAX_PATH); + return std::string(retname);; +} + +void open_tempfile (std::fstream& file, std::ios_base::openmode mode) +{ + const char* tmpdir = getenv("TEMP"); + size_t tmpdir_len; + if (tmpdir) { + tmpdir_len = strlen(tmpdir); + } else { + tmpdir = "/tmp"; + tmpdir_len = 4; + } + char* path = new char[tmpdir_len + 18]; + strcpy(path, tmpdir); + strcpy(path + tmpdir_len, "/git-crypt.XXXXXX"); + + int fd = mkstemp(path); + + if (fd == -1) { + perror("mkstemp"); + std::exit(9); + } + + file.open(path, mode); + if (!file.is_open()) { + perror("open"); + unlink(path); + std::exit(9); + } + + // On windows we cannot remove open files. Then git-crypt.XXXXXX temporary files will + // remain on %TEMP% folder for manually remove. It´s not that bad cause 26 different name + // limit on windows mkstemp. + // unlink(path); + close(fd); + delete[] path; +} + +/* + * LaunchChildProcess + * Sets up STARTUPINFO structure, and launches redirected child. + */ +void LaunchChildProcess(HANDLE hChildStdOut, + HANDLE hChildStdIn, + HANDLE hChildStdErr, + const std::string command) +{ + PROCESS_INFORMATION pi; + STARTUPINFO si; + BOOL br = FALSE; + // Set up the start up info struct. + ZeroMemory(&pi, sizeof(PROCESS_INFORMATION)); + ZeroMemory(&si, sizeof(STARTUPINFO)); + si.cb = sizeof(STARTUPINFO); + si.dwFlags = STARTF_USESTDHANDLES; + si.wShowWindow = SW_HIDE; + si.hStdOutput = hChildStdOut; + si.hStdInput = hChildStdIn; + si.hStdError = hChildStdErr; + + br = CreateProcess(NULL, /* module: null means use command line */ + (LPSTR)command.c_str(), /* modified command line */ + NULL, /* thread handle inheritance */ + NULL, /* thread handle inheritance */ + TRUE, /* handles inheritable? */ + CREATE_UNICODE_ENVIRONMENT, + NULL, /* environment: use parent */ + NULL, /* starting directory: use parent */ + &si,&pi); + + if (br) { + WaitForSingleObject(pi.hProcess, INFINITE); + } + else + { + DisplayError("Error launching process"); + } + // Close any unnecessary handles. + if (!CloseHandle(pi.hProcess)) DisplayError("CloseHandle"); + if (!CloseHandle(pi.hThread)) DisplayError("CloseHandle"); +} + + +/* + * ReadAndHandleOutput + * Monitors handle for input. Exits when child exits or pipe breaks. + */ +void ReadAndHandleOutput(HANDLE hPipeRead, std::ostream& output) +{ + UCHAR lpBuffer[256]; + DWORD nBytesRead; + + while(TRUE) + { + memset(lpBuffer, 0, sizeof(lpBuffer)); + if (!ReadFile(hPipeRead,lpBuffer,sizeof(lpBuffer),&nBytesRead,NULL) || !nBytesRead) + { + if (GetLastError() == ERROR_BROKEN_PIPE) + break; // pipe done - normal exit path. + else + DisplayError("ReadFile"); // Something bad happened. + } + + output.write((const char *)lpBuffer, nBytesRead); + } +} + +/* + * ArgvQuote + */ +void ArgvQuote (const std::string& Argument, + std::string& CommandLine, + bool Force) +/*** + * + * Routine Description: + * + * This routine appends the given argument to a command line such + * that CommandLineToArgvW will return the argument string unchanged. + * Arguments in a command line should be separated by spaces; this + * function does not add these spaces. + * + * Arguments: + * + * Argument - Supplies the argument to encode. + * + * CommandLine - Supplies the command line to which we append the encoded argument string. + * + * Force - Supplies an indication of whether we should quote + * the argument even if it does not contain any characters that would + * ordinarily require quoting. + * + * Return Value: + * + * None. + * + * Environment: + * + * Arbitrary. + * + */ + { + // + // Unless we're told otherwise, don't quote unless we actually + // need to do so --- hopefully avoid problems if programs won't + // parse quotes properly + // + if (Force == false && + Argument.empty () == false && + Argument.find_first_of (" \t\n\v\"") == Argument.npos) + { + CommandLine.append (Argument); + } + else { + CommandLine.push_back ('"'); + std::string::const_iterator It; + for (It = Argument.begin () ; ; ++It) { + unsigned NumberBackslashes = 0; + while (It != Argument.end () && *It == '\\') { + ++It; + ++NumberBackslashes; + } + + if (It == Argument.end ()) { + // + // Escape all backslashes, but let the terminating + // double quotation mark we add below be interpreted + // as a metacharacter. + // + CommandLine.append (NumberBackslashes * 2, '\\'); + break; + } + else if (*It == '"') { + // + // Escape all backslashes and the following + // double quotation mark. + // + CommandLine.append (NumberBackslashes * 2 + 1, '\\'); + CommandLine.push_back (*It); + } + else { + // + // Backslashes aren't special here. + // + CommandLine.append (NumberBackslashes, '\\'); + CommandLine.push_back (*It); + } + } + CommandLine.push_back ('"'); + } +} + +int mkstemp(char * filetemplate) +{ + // on windows _mktemp generate only 26 unique filename + char *filename = _mktemp(filetemplate); + if (filename == NULL) { + return -1; + } + return open(filename, _O_RDWR |_O_BINARY | O_CREAT); +} + +/* + * DisplayError + * Displays the error number and corresponding message. + */ +void DisplayError(LPCSTR szPrefix) +{ + LPSTR lpsz = NULL; + DWORD cch = 0; + DWORD dwError = GetLastError(); + + cch = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER + | FORMAT_MESSAGE_FROM_SYSTEM + | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, dwError, LANG_NEUTRAL, + (LPTSTR)&lpsz, 0, NULL); + if (cch < 1) { + cch = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER + | FORMAT_MESSAGE_FROM_STRING + | FORMAT_MESSAGE_ARGUMENT_ARRAY, + "Code 0x%1!08x!", + 0, LANG_NEUTRAL, (LPTSTR)&lpsz, 0, + (va_list*)&dwError); + } + fprintf(stderr, "%s: %s", szPrefix, lpsz); + LocalFree((HLOCAL)lpsz); + ExitProcess(-1); +} + +#endif \ No newline at end of file diff --git a/crypto.cpp b/crypto.cpp index e1a8594..e4ec65c 100644 --- a/crypto.cpp +++ b/crypto.cpp @@ -1,4 +1,4 @@ -/* +/* * Copyright 2012 Andrew Ayer * * This file is part of git-crypt. @@ -38,7 +38,11 @@ #include #include #include +#ifdef __WIN32__ +#include +#else #include +#endif void load_keys (const char* filepath, keys_t* keys) { diff --git a/util.cpp b/util.cpp index 575d616..dbe9aac 100644 --- a/util.cpp +++ b/util.cpp @@ -28,6 +28,7 @@ * as that of the covered work. */ +#ifndef __WIN32__ #include "util.hpp" #include #include @@ -126,3 +127,4 @@ std::string escape_shell_arg (const std::string& str) return new_str; } +#endif \ No newline at end of file From fd4c525a0054c3a5a932034a3bd7753d63e39286 Mon Sep 17 00:00:00 2001 From: bySabi Files Date: Thu, 6 Feb 2014 16:34:13 +0100 Subject: [PATCH 02/16] add win32 support --- INSTALL | 12 +++++ Makefile | 11 +++-- Util_win32.cpp | 131 +++++++++++++++++++++++++++++++++---------------- commands.cpp | 9 +++- crypto.cpp | 5 +- util.cpp | 3 -- util.hpp | 4 ++ 7 files changed, 123 insertions(+), 52 deletions(-) diff --git a/INSTALL b/INSTALL index 0bd4da8..f9c836f 100644 --- a/INSTALL +++ b/INSTALL @@ -20,3 +20,15 @@ The Makefile is tailored for g++, but should work with other compilers. It doesn't matter where you install the git-crypt binary - choose wherever is most convenient for you. + +BUILDING ON WINDOWS + + * Install mingw + * Download OpenSSL for Windows + * Put libeay32.lib on mingw lib folder + * Put openssl header´s folder on mingw include folder + + $ make + +Need "msys" enviroment (sh.exe) to run. + diff --git a/Makefile b/Makefile index da97f9e..a19aabc 100644 --- a/Makefile +++ b/Makefile @@ -1,9 +1,14 @@ CXX := c++ CXXFLAGS := -Wall -pedantic -ansi -Wno-long-long -O2 -LDFLAGS := -lcrypto -lwsock32 +LDFLAGS := -lcrypto PREFIX := /usr/local -OBJFILES = git-crypt.o commands.o crypto.o util.o util_win32.o +OBJFILES = git-crypt.o commands.o crypto.o util.o + +ifeq ($(OS),Windows_NT) + LDFLAGS = -llibeay32 -lwsock32 + OBJFILES = git-crypt.o commands.o crypto.o util_win32.o +endif all: git-crypt @@ -11,7 +16,7 @@ git-crypt: $(OBJFILES) $(CXX) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) clean: - rm -f *.o git-crypt + rm -f *.o git-crypt git-crypt.exe install: install -m 755 git-crypt $(PREFIX)/bin/ diff --git a/Util_win32.cpp b/Util_win32.cpp index 3ac74d4..a6b3b2f 100644 --- a/Util_win32.cpp +++ b/Util_win32.cpp @@ -1,19 +1,48 @@ +/* + * Copyright 2012 Andrew Ayer + * Copyright 2014 bySabi Files + * + * 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 . + * + * 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. + */ + #ifdef __WIN32__ #undef __STRICT_ANSI__ //needed for _fullpath +#include "util.hpp" #include #include #include #include #include -#include #include +#include -#define unlink _unlink - - -void LaunchChildProcess(HANDLE hChildStdOut, +int LaunchChildProcess(HANDLE hChildStdOut, HANDLE hChildStdIn, HANDLE hChildStdErr, const std::string command); @@ -24,9 +53,6 @@ void ArgvQuote (const std::string& Argument, int mkstemp(char *name); void DisplayError(LPCSTR wszPrefix); -//do nothing on windows -static inline mode_t umask(mode_t mask){ return -1; } - int exec_command (const char* command, std::ostream& output) { @@ -43,7 +69,6 @@ int exec_command (const char* command, std::ostream& output) if (!CreatePipe(&hOutputReadTmp,&hOutputWrite,&sa,0)) DisplayError("CreatePipe"); - // Create a duplicate of the output write handle for the std error // write handle. This is necessary in case the child application // closes one of its std output handles. @@ -64,15 +89,15 @@ int exec_command (const char* command, std::ostream& output) DisplayError("DuplicateHandle"); // Close inheritable copies of the handles you do not want to be - // inherited. + // inherited. if (!CloseHandle(hOutputReadTmp)) DisplayError("CloseHandle"); - // Prepare command arg + // Prepare command argv std::string cmd("sh.exe -c "); - ArgvQuote(command, cmd, TRUE); + ArgvQuote(std::string(command), cmd, FALSE); - // Launch child process with "cmd" - LaunchChildProcess(hOutputWrite ,NULL ,hErrorWrite, cmd); + // Launch child process with + int status = LaunchChildProcess(hOutputWrite ,NULL ,hErrorWrite, cmd); // Close pipe handles (do not continue to modify the parent). // You need to make sure that no handles to the write end of the @@ -86,14 +111,21 @@ int exec_command (const char* command, std::ostream& output) if (!CloseHandle(hOutputRead)) DisplayError("CloseHandle"); - return 1; + return status; } -std::string escape_shell_arg(const std::string& str) +std::string escape_shell_arg (const std::string& str) { - std::string escape_str; - ArgvQuote(str, escape_str, TRUE); - return escape_str; + std::string new_str; + new_str.push_back('"'); + for (std::string::const_iterator it(str.begin()); it != str.end(); ++it) { + if (*it == '"' || *it == '\\' || *it == '$' || *it == '`') { + new_str.push_back('\\'); + } + new_str.push_back(*it); + } + new_str.push_back('"'); + return new_str; } std::string resolve_path (const char* path) @@ -130,27 +162,45 @@ void open_tempfile (std::fstream& file, std::ios_base::openmode mode) unlink(path); std::exit(9); } - - // On windows we cannot remove open files. Then git-crypt.XXXXXX temporary files will - // remain on %TEMP% folder for manually remove. It´s not that bad cause 26 different name + + //FIXME + // On windows we cannot remove open files, git-crypt.XXXXXX temporary files will + // remain on %TEMP% folder for manual remove. It´s not that hard cause 26 different name // limit on windows mkstemp. // unlink(path); - close(fd); + // close(fd); delete[] path; } +int win32_system(const char* command) +{ + std::string cmd("sh.exe -c "); + ArgvQuote(std::string(command), cmd, FALSE); + return LaunchChildProcess(NULL ,NULL ,NULL, cmd); +} + +int mkstemp(char * filetemplate) +{ + // on windows _mktemp generate only 26 unique filename + char *filename = _mktemp(filetemplate); + if (filename == NULL) { + return -1; + } + return open(filename, _O_RDWR |_O_BINARY | O_CREAT); +} + /* * LaunchChildProcess * Sets up STARTUPINFO structure, and launches redirected child. */ -void LaunchChildProcess(HANDLE hChildStdOut, +int LaunchChildProcess(HANDLE hChildStdOut, HANDLE hChildStdIn, HANDLE hChildStdErr, const std::string command) { PROCESS_INFORMATION pi; STARTUPINFO si; - BOOL br = FALSE; + DWORD exit_code; // Set up the start up info struct. ZeroMemory(&pi, sizeof(PROCESS_INFORMATION)); ZeroMemory(&si, sizeof(STARTUPINFO)); @@ -161,29 +211,35 @@ void LaunchChildProcess(HANDLE hChildStdOut, si.hStdInput = hChildStdIn; si.hStdError = hChildStdErr; - br = CreateProcess(NULL, /* module: null means use command line */ + if ( CreateProcess(NULL, /* module: null means use command line */ (LPSTR)command.c_str(), /* modified command line */ NULL, /* thread handle inheritance */ NULL, /* thread handle inheritance */ TRUE, /* handles inheritable? */ - CREATE_UNICODE_ENVIRONMENT, + CREATE_NO_WINDOW, NULL, /* environment: use parent */ NULL, /* starting directory: use parent */ - &si,&pi); + &si,&pi) ) - if (br) { + { WaitForSingleObject(pi.hProcess, INFINITE); } else { - DisplayError("Error launching process"); + char error_msg[] = "Error launching process: "; + char buf[_MAX_PATH + sizeof(error_msg)]; + snprintf(buf, sizeof buf, "%s%s%", error_msg, command.c_str()); + DisplayError(buf); } + + GetExitCodeProcess(pi.hProcess, &exit_code); + // Close any unnecessary handles. if (!CloseHandle(pi.hProcess)) DisplayError("CloseHandle"); if (!CloseHandle(pi.hThread)) DisplayError("CloseHandle"); + return exit_code; } - /* * ReadAndHandleOutput * Monitors handle for input. Exits when child exits or pipe breaks. @@ -213,7 +269,7 @@ void ReadAndHandleOutput(HANDLE hPipeRead, std::ostream& output) */ void ArgvQuote (const std::string& Argument, std::string& CommandLine, - bool Force) + bool Force ) /*** * * Routine Description: @@ -263,7 +319,6 @@ void ArgvQuote (const std::string& Argument, ++It; ++NumberBackslashes; } - if (It == Argument.end ()) { // // Escape all backslashes, but let the terminating @@ -293,16 +348,6 @@ void ArgvQuote (const std::string& Argument, } } -int mkstemp(char * filetemplate) -{ - // on windows _mktemp generate only 26 unique filename - char *filename = _mktemp(filetemplate); - if (filename == NULL) { - return -1; - } - return open(filename, _O_RDWR |_O_BINARY | O_CREAT); -} - /* * DisplayError * Displays the error number and corresponding message. diff --git a/commands.cpp b/commands.cpp index b3180c5..ac93d83 100644 --- a/commands.cpp +++ b/commands.cpp @@ -28,6 +28,7 @@ * as that of the covered work. */ + #include "commands.hpp" #include "crypto.hpp" #include "util.hpp" @@ -45,6 +46,12 @@ #include #include + +#ifdef __WIN32__ +#define system(a) win32_system(a) +#endif + + // Encrypt contents of stdin and write to stdout void clean (const char* keyfile) { @@ -234,7 +241,7 @@ void init (const char* argv0, const char* keyfile) // git config filter.git-crypt.smudge "git-crypt smudge /path/to/key" std::string command("git config filter.git-crypt.smudge "); command += escape_shell_arg(escape_shell_arg(git_crypt_path) + " smudge " + escape_shell_arg(keyfile_path)); - + if (system(command.c_str()) != 0) { std::clog << "git config failed\n"; std::exit(1); diff --git a/crypto.cpp b/crypto.cpp index e4ec65c..55faab2 100644 --- a/crypto.cpp +++ b/crypto.cpp @@ -46,15 +46,16 @@ void load_keys (const char* filepath, keys_t* keys) { - std::ifstream file(filepath); + std::ifstream file(filepath, std::ios::binary); if (!file) { perror(filepath); std::exit(1); } char buffer[AES_KEY_BITS/8 + HMAC_KEY_LEN]; file.read(buffer, sizeof(buffer)); + if (file.gcount() != sizeof(buffer)) { - std::clog << filepath << ": Premature end of key file\n"; + std::clog << filepath << ": Prematurrre end of key file\n"; std::exit(1); } diff --git a/util.cpp b/util.cpp index dbe9aac..3849cc8 100644 --- a/util.cpp +++ b/util.cpp @@ -28,7 +28,6 @@ * as that of the covered work. */ -#ifndef __WIN32__ #include "util.hpp" #include #include @@ -126,5 +125,3 @@ std::string escape_shell_arg (const std::string& str) new_str.push_back('"'); return new_str; } - -#endif \ No newline at end of file diff --git a/util.hpp b/util.hpp index aa76982..e165f8d 100644 --- a/util.hpp +++ b/util.hpp @@ -40,5 +40,9 @@ std::string resolve_path (const char* path); void open_tempfile (std::fstream&, std::ios_base::openmode); std::string escape_shell_arg (const std::string&); +#ifdef __WIN32__ +int win32_system (const char* command); +#endif + #endif From 56e3a2fdaac3259c530b4ade5767a758c29dbb92 Mon Sep 17 00:00:00 2001 From: bySabi Files Date: Thu, 6 Feb 2014 16:39:22 +0100 Subject: [PATCH 03/16] add win32 support --- crypto.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crypto.cpp b/crypto.cpp index 55faab2..29da246 100644 --- a/crypto.cpp +++ b/crypto.cpp @@ -55,7 +55,7 @@ void load_keys (const char* filepath, keys_t* keys) file.read(buffer, sizeof(buffer)); if (file.gcount() != sizeof(buffer)) { - std::clog << filepath << ": Prematurrre end of key file\n"; + std::clog << filepath << ": Premature end of key file\n"; std::exit(1); } From 1eff8ac4429a61041dbd8a3fd99e58884e12ed34 Mon Sep 17 00:00:00 2001 From: bySabi Files Date: Thu, 6 Feb 2014 20:56:54 +0100 Subject: [PATCH 04/16] remove sh.exe dependecy --- .gitignore | 1 + Makefile | 5 +- Util_win32.cpp | 148 ++++++++++++++----------------------------------- 3 files changed, 48 insertions(+), 106 deletions(-) diff --git a/.gitignore b/.gitignore index 55b70cc..8cfb6de 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ *.o *.exe git-crypt +SET.bat diff --git a/Makefile b/Makefile index a19aabc..6dadf6e 100644 --- a/Makefile +++ b/Makefile @@ -21,4 +21,7 @@ clean: install: install -m 755 git-crypt $(PREFIX)/bin/ -.PHONY: all clean install +strip: + strip git-crypt.exe + +.PHONY: all clean install strip diff --git a/Util_win32.cpp b/Util_win32.cpp index a6b3b2f..e1894b0 100644 --- a/Util_win32.cpp +++ b/Util_win32.cpp @@ -29,7 +29,6 @@ * as that of the covered work. */ -#ifdef __WIN32__ #undef __STRICT_ANSI__ //needed for _fullpath #include "util.hpp" #include @@ -45,11 +44,8 @@ int LaunchChildProcess(HANDLE hChildStdOut, HANDLE hChildStdIn, HANDLE hChildStdErr, - const std::string command); + const char* command); void ReadAndHandleOutput(HANDLE hPipeRead, std::ostream& output); -void ArgvQuote (const std::string& Argument, - std::string& CommandLine, - bool Force); int mkstemp(char *name); void DisplayError(LPCSTR wszPrefix); @@ -92,12 +88,8 @@ int exec_command (const char* command, std::ostream& output) // inherited. if (!CloseHandle(hOutputReadTmp)) DisplayError("CloseHandle"); - // Prepare command argv - std::string cmd("sh.exe -c "); - ArgvQuote(std::string(command), cmd, FALSE); - - // Launch child process with - int status = LaunchChildProcess(hOutputWrite ,NULL ,hErrorWrite, cmd); + // Launch child process + int status = LaunchChildProcess(hOutputWrite ,NULL ,hErrorWrite, command); // Close pipe handles (do not continue to modify the parent). // You need to make sure that no handles to the write end of the @@ -119,10 +111,14 @@ std::string escape_shell_arg (const std::string& str) std::string new_str; new_str.push_back('"'); for (std::string::const_iterator it(str.begin()); it != str.end(); ++it) { - if (*it == '"' || *it == '\\' || *it == '$' || *it == '`') { + if (*it == '"' || *it == '$' || *it == '`') { new_str.push_back('\\'); } - new_str.push_back(*it); + if (*it == '\\') { + new_str += '/'; + } + else + new_str.push_back(*it); } new_str.push_back('"'); return new_str; @@ -172,11 +168,39 @@ void open_tempfile (std::fstream& file, std::ios_base::openmode mode) delete[] path; } +char* str_replace(const char *string, const char *substr, const char *replacement) +{ + + /* if either substr or replacement is NULL, duplicate string a let caller handle it */ + if ( substr == NULL || replacement == NULL ) return strdup (string); + + char* newstr = strdup (string); + char* head = newstr; + char* tok; + while ( (tok = strstr( head, substr )) ) + { + char* oldstr = newstr; + newstr = (char *)malloc ( strlen ( oldstr ) - strlen ( substr ) + strlen ( replacement ) + 1 ); + /*failed to alloc mem, free old string and return NULL */ + if ( newstr == NULL ){ + free (oldstr); + return NULL; + } + memcpy ( newstr, oldstr, tok - oldstr ); + memcpy ( newstr + (tok - oldstr), replacement, strlen ( replacement ) ); + memcpy ( newstr + (tok - oldstr) + strlen( replacement ), tok + strlen ( substr ), strlen ( oldstr ) - strlen ( substr ) - ( tok - oldstr ) ); + memset ( newstr + strlen ( oldstr ) - strlen ( substr ) + strlen ( replacement ) , 0, 1 ); + /* move back head right after the last replacement */ + head = newstr + (tok - oldstr) + strlen( replacement ); + free (oldstr); + } + return newstr; +} + int win32_system(const char* command) { - std::string cmd("sh.exe -c "); - ArgvQuote(std::string(command), cmd, FALSE); - return LaunchChildProcess(NULL ,NULL ,NULL, cmd); + // >/dev/null TO >nul + return system(str_replace(command, "/dev/null", "nul")); } int mkstemp(char * filetemplate) @@ -196,7 +220,7 @@ int mkstemp(char * filetemplate) int LaunchChildProcess(HANDLE hChildStdOut, HANDLE hChildStdIn, HANDLE hChildStdErr, - const std::string command) + const char* command) { PROCESS_INFORMATION pi; STARTUPINFO si; @@ -212,7 +236,7 @@ int LaunchChildProcess(HANDLE hChildStdOut, si.hStdError = hChildStdErr; if ( CreateProcess(NULL, /* module: null means use command line */ - (LPSTR)command.c_str(), /* modified command line */ + (LPSTR)command, /* modified command line */ NULL, /* thread handle inheritance */ NULL, /* thread handle inheritance */ TRUE, /* handles inheritable? */ @@ -228,7 +252,7 @@ int LaunchChildProcess(HANDLE hChildStdOut, { char error_msg[] = "Error launching process: "; char buf[_MAX_PATH + sizeof(error_msg)]; - snprintf(buf, sizeof buf, "%s%s%", error_msg, command.c_str()); + snprintf(buf, sizeof buf, "%s%s%", error_msg, command); DisplayError(buf); } @@ -264,90 +288,6 @@ void ReadAndHandleOutput(HANDLE hPipeRead, std::ostream& output) } } -/* - * ArgvQuote - */ -void ArgvQuote (const std::string& Argument, - std::string& CommandLine, - bool Force ) -/*** - * - * Routine Description: - * - * This routine appends the given argument to a command line such - * that CommandLineToArgvW will return the argument string unchanged. - * Arguments in a command line should be separated by spaces; this - * function does not add these spaces. - * - * Arguments: - * - * Argument - Supplies the argument to encode. - * - * CommandLine - Supplies the command line to which we append the encoded argument string. - * - * Force - Supplies an indication of whether we should quote - * the argument even if it does not contain any characters that would - * ordinarily require quoting. - * - * Return Value: - * - * None. - * - * Environment: - * - * Arbitrary. - * - */ - { - // - // Unless we're told otherwise, don't quote unless we actually - // need to do so --- hopefully avoid problems if programs won't - // parse quotes properly - // - if (Force == false && - Argument.empty () == false && - Argument.find_first_of (" \t\n\v\"") == Argument.npos) - { - CommandLine.append (Argument); - } - else { - CommandLine.push_back ('"'); - std::string::const_iterator It; - for (It = Argument.begin () ; ; ++It) { - unsigned NumberBackslashes = 0; - while (It != Argument.end () && *It == '\\') { - ++It; - ++NumberBackslashes; - } - if (It == Argument.end ()) { - // - // Escape all backslashes, but let the terminating - // double quotation mark we add below be interpreted - // as a metacharacter. - // - CommandLine.append (NumberBackslashes * 2, '\\'); - break; - } - else if (*It == '"') { - // - // Escape all backslashes and the following - // double quotation mark. - // - CommandLine.append (NumberBackslashes * 2 + 1, '\\'); - CommandLine.push_back (*It); - } - else { - // - // Backslashes aren't special here. - // - CommandLine.append (NumberBackslashes, '\\'); - CommandLine.push_back (*It); - } - } - CommandLine.push_back ('"'); - } -} - /* * DisplayError * Displays the error number and corresponding message. @@ -375,5 +315,3 @@ void DisplayError(LPCSTR szPrefix) LocalFree((HLOCAL)lpsz); ExitProcess(-1); } - -#endif \ No newline at end of file From dfade5f36cbd55af1aaa16037cc9df7f08677c75 Mon Sep 17 00:00:00 2001 From: bySabi Date: Fri, 7 Feb 2014 18:12:32 +0100 Subject: [PATCH 05/16] add test --- .gitignore | 2 +- INSTALL | 2 - Makefile | 8 ++- test.sh | 152 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 159 insertions(+), 5 deletions(-) create mode 100755 test.sh diff --git a/.gitignore b/.gitignore index 8cfb6de..1efbcc4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ *.o *.exe git-crypt -SET.bat +test/ diff --git a/INSTALL b/INSTALL index f9c836f..19399c9 100644 --- a/INSTALL +++ b/INSTALL @@ -30,5 +30,3 @@ BUILDING ON WINDOWS $ make -Need "msys" enviroment (sh.exe) to run. - diff --git a/Makefile b/Makefile index 6dadf6e..5eb16e0 100644 --- a/Makefile +++ b/Makefile @@ -16,12 +16,16 @@ git-crypt: $(OBJFILES) $(CXX) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) clean: - rm -f *.o git-crypt git-crypt.exe + rm -f *.o git-crypt git-crypt.exe \ + rm -fr test install: install -m 755 git-crypt $(PREFIX)/bin/ +test: + ./test.sh + strip: strip git-crypt.exe -.PHONY: all clean install strip +.PHONY: all clean install test strip diff --git a/test.sh b/test.sh new file mode 100755 index 0000000..2371e13 --- /dev/null +++ b/test.sh @@ -0,0 +1,152 @@ +#!/usr/bin/perl +use strict; +use warnings; +use Cwd; +use File::Path; +use Term::ANSIColor; +use Digest::MD5 qw(md5); + +print "\n"."========= GIT-CRYPT TEST ========="."\n"; + + +my $dir=Cwd::cwd()."/test"; + +### Set test folder +if ( -d $dir ) { + rmtree($dir) or die "Cannot remove '$dir' : $!"; +} +mkpath($dir) or die "Cannot create '$dir' : $!"; +chdir($dir); + +### Generate git-crypt key +my $key="test.key"; + +print "\n"; +`git-crypt keygen $key`; !($?) or die; + +### Create git repository + +print "\n"."========= CREATE GIT ORIGIN REPO ========="."\n"; + +my $repo="repo"; +mkpath($repo) or die "Cannot create '$repo' : $!"; +chdir($repo); + +print "\n"; +my $out=`git init`; !($?) or die; +print $out; + +## put some files +my $file1="crypto.hpp"; +my $file2="crypto.tgz"; + +`curl -sS "https://raw.github.com/AGWA/git-crypt/master/crypto.hpp" > $file1`; !($?) or die; +`tar -zcf $file2 $file1`; !($?) or die; + +print "add file: ".$file1."\n"; +print "add file: ".$file2."\n"; + +open (FILE, '>>.gitattributes'); +print FILE "*.hpp filter=git-crypt diff=git-crypt"."\n"; +print FILE "*.tgz filter=git-crypt diff=git-crypt"."\n"; +close (FILE); +print "set .gitattributes filter for: *.hpp *.tgz"."\n"; + +print "Initialized git-crypt repository"."\n"; +`git-crypt init ../$key`; !($?) or die; + +print "git add & commit files"."\n"; +`git add --all`; !($?) or die; +`git commit -m "test git-crypt"`; !($?) or die; + + +### Clone git repository + +chdir($dir); + +print "\n"."======= CLONE GIT ENCRYPTED REPO ======="."\n"; + +my $clonerepo="clonerepo"; + +`git clone --quiet file://'$dir/$repo' $clonerepo`; !($?) or die; +print "\n"."Clone Git repository in "."$dir/$clonerepo/"."\n"; + + +### TEST +chdir("$dir/$clonerepo"); + +### Test#1 +## isencrypted clone repo ? + +print "\n"."======= TEST 1: isencrypted clone repo? ======="."\n"; + +print "\n"; +if ( isencrypted($file1) ) { + print "\"$file1\" encrypted?: ".colored("OK", "green")."\n"; +} else { + print "\"$file1\" encrypted?: ".colored("FAIL", "red")."\n"; +} + +if ( isencrypted($file2) ) { + print "\"$file2\" encrypted?: ".colored("OK", "green")."\n"; +} else { + print "\"$file2\" encrypted?: ".colored("FAIL", "red")."\n"; +} + + +### Test#2 +## decrypt clone repo + +print "\n"."======= TEST 2: decrypt clone repo ======="."\n"; + +`git-crypt init ../$key`; !($?) or die; + +print "\n"; +if ( isdecrypted($file1) ) { + print "\"$file1\" decrypted?: ".colored("OK", "green")."\n"; +} else { + print "\"$file1\" decrypted?: ".colored("FAIL", "red")."\n"; +} + +if ( isdecrypted($file2) ) { + print "\"$file2\" decrypted?: ".colored("OK", "green")."\n"; +} else { + print "\"$file2\" decrypted?: ".colored("FAIL", "red")."\n"; +} +print "\n"; + + + +sub isencrypted { + my $crypthead="\x00GITCRYPT\x00"; + my $file = shift; + open (FILE, $file) or die "Can't open '$file' : $!"; + binmode(FILE) or die "Can't binmode '$file' : $!"; + my $filehead; + read (FILE, $filehead, 10); + close (FILE); + + if ( "$crypthead" eq "$filehead" ) { + return 1; + } + return 0; +} + +sub isdecrypted { + my $file = shift; + if ( getmd5("$dir/$repo/$file") eq getmd5("$dir/$clonerepo/$file") ) { + return 1; + } + return 0; +} + +sub getmd5 { + my $file = shift; + open (FILE, $file) or die "Can't open '$file' : $!"; + binmode(FILE) or die "Can't binmode '$file' : $!"; + my $data = ; + close(FILE); + return md5($data); +} + +exit 0 \ No newline at end of file From df4270802cc0efd7683dc698c556cee07c3b591a Mon Sep 17 00:00:00 2001 From: bySabi Files Date: Tue, 11 Feb 2014 09:10:21 +0100 Subject: [PATCH 06/16] fix error on win32 --- .gitignore | 2 ++ Makefile | 5 ++++- Util_win32.cpp | 2 +- git-crypt.cpp | 18 ++++++++++++++++++ 4 files changed, 25 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 1efbcc4..801d8b0 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,5 @@ *.exe git-crypt test/ +doit.sh + diff --git a/Makefile b/Makefile index 5eb16e0..3919a74 100644 --- a/Makefile +++ b/Makefile @@ -5,9 +5,12 @@ PREFIX := /usr/local OBJFILES = git-crypt.o commands.o crypto.o util.o +INSTALL = install -m 755 git-crypt $(PREFIX)/bin/ + ifeq ($(OS),Windows_NT) LDFLAGS = -llibeay32 -lwsock32 OBJFILES = git-crypt.o commands.o crypto.o util_win32.o + INSTALL = cp git-crypt.exe $(PREFIX)/bin/ endif all: git-crypt @@ -20,7 +23,7 @@ clean: rm -fr test install: - install -m 755 git-crypt $(PREFIX)/bin/ + $(INSTALL) test: ./test.sh diff --git a/Util_win32.cpp b/Util_win32.cpp index e1894b0..ba53c35 100644 --- a/Util_win32.cpp +++ b/Util_win32.cpp @@ -252,7 +252,7 @@ int LaunchChildProcess(HANDLE hChildStdOut, { char error_msg[] = "Error launching process: "; char buf[_MAX_PATH + sizeof(error_msg)]; - snprintf(buf, sizeof buf, "%s%s%", error_msg, command); + snprintf(buf, sizeof buf, "%s%s", error_msg, command); DisplayError(buf); } diff --git a/git-crypt.cpp b/git-crypt.cpp index bd58391..babe636 100644 --- a/git-crypt.cpp +++ b/git-crypt.cpp @@ -34,6 +34,11 @@ #include #include +#ifdef __WIN32__ +#include +#include +#endif + static void print_usage (const char* argv0) { std::clog << "Usage: " << argv0 << " COMMAND [ARGS ...]\n"; @@ -58,6 +63,19 @@ try { std::cin.exceptions(std::ios_base::badbit); std::cout.exceptions(std::ios_base::badbit); +#ifdef __WIN32__ + int result = _setmode( _fileno(stdin), _O_BINARY ); + if( result == -1 ) { + std::cerr <<"Cannot set input mode to binary." < Date: Tue, 11 Feb 2014 10:36:57 +0100 Subject: [PATCH 07/16] fix --- Util_win32.cpp | 317 ------------------------------------------------- 1 file changed, 317 deletions(-) delete mode 100644 Util_win32.cpp diff --git a/Util_win32.cpp b/Util_win32.cpp deleted file mode 100644 index ba53c35..0000000 --- a/Util_win32.cpp +++ /dev/null @@ -1,317 +0,0 @@ -/* - * Copyright 2012 Andrew Ayer - * Copyright 2014 bySabi Files - * - * 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 . - * - * 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. - */ - -#undef __STRICT_ANSI__ //needed for _fullpath -#include "util.hpp" -#include -#include -#include - -#include -#include -#include -#include - - -int LaunchChildProcess(HANDLE hChildStdOut, - HANDLE hChildStdIn, - HANDLE hChildStdErr, - const char* command); -void ReadAndHandleOutput(HANDLE hPipeRead, std::ostream& output); -int mkstemp(char *name); -void DisplayError(LPCSTR wszPrefix); - - -int exec_command (const char* command, std::ostream& output) -{ - HANDLE hOutputReadTmp,hOutputRead,hOutputWrite; - HANDLE hErrorWrite; - SECURITY_ATTRIBUTES sa; - - // Set up the security attributes struct. - sa.nLength= sizeof(SECURITY_ATTRIBUTES); - sa.lpSecurityDescriptor = NULL; - sa.bInheritHandle = TRUE; - - // Create the child output pipe. - if (!CreatePipe(&hOutputReadTmp,&hOutputWrite,&sa,0)) - DisplayError("CreatePipe"); - - // Create a duplicate of the output write handle for the std error - // write handle. This is necessary in case the child application - // closes one of its std output handles. - if (!DuplicateHandle(GetCurrentProcess(),hOutputWrite, - GetCurrentProcess(),&hErrorWrite,0, - TRUE,DUPLICATE_SAME_ACCESS)) - DisplayError("DuplicateHandle"); - - // Create new output read handle. Set - // the Properties to FALSE. Otherwise, the child inherits the - // properties and, as a result, non-closeable handles to the pipes - // are created. - if (!DuplicateHandle(GetCurrentProcess(),hOutputReadTmp, - GetCurrentProcess(), - &hOutputRead, // Address of new handle. - 0,FALSE, // Make it uninheritable. - DUPLICATE_SAME_ACCESS)) - DisplayError("DuplicateHandle"); - - // Close inheritable copies of the handles you do not want to be - // inherited. - if (!CloseHandle(hOutputReadTmp)) DisplayError("CloseHandle"); - - // Launch child process - int status = LaunchChildProcess(hOutputWrite ,NULL ,hErrorWrite, command); - - // Close pipe handles (do not continue to modify the parent). - // You need to make sure that no handles to the write end of the - // output pipe are maintained in this process or else the pipe will - // not close when the child process exits and the ReadFile will hang. - if (!CloseHandle(hOutputWrite)) DisplayError("CloseHandle"); - if (!CloseHandle(hErrorWrite)) DisplayError("CloseHandle"); - - // Read the child's output. - ReadAndHandleOutput(hOutputRead, output); - - if (!CloseHandle(hOutputRead)) DisplayError("CloseHandle"); - - return status; -} - -std::string escape_shell_arg (const std::string& str) -{ - std::string new_str; - new_str.push_back('"'); - for (std::string::const_iterator it(str.begin()); it != str.end(); ++it) { - if (*it == '"' || *it == '$' || *it == '`') { - new_str.push_back('\\'); - } - if (*it == '\\') { - new_str += '/'; - } - else - new_str.push_back(*it); - } - new_str.push_back('"'); - return new_str; -} - -std::string resolve_path (const char* path) -{ - char retname[_MAX_PATH]; - _fullpath(retname, path, _MAX_PATH); - return std::string(retname);; -} - -void open_tempfile (std::fstream& file, std::ios_base::openmode mode) -{ - const char* tmpdir = getenv("TEMP"); - size_t tmpdir_len; - if (tmpdir) { - tmpdir_len = strlen(tmpdir); - } else { - tmpdir = "/tmp"; - tmpdir_len = 4; - } - char* path = new char[tmpdir_len + 18]; - strcpy(path, tmpdir); - strcpy(path + tmpdir_len, "/git-crypt.XXXXXX"); - - int fd = mkstemp(path); - - if (fd == -1) { - perror("mkstemp"); - std::exit(9); - } - - file.open(path, mode); - if (!file.is_open()) { - perror("open"); - unlink(path); - std::exit(9); - } - - //FIXME - // On windows we cannot remove open files, git-crypt.XXXXXX temporary files will - // remain on %TEMP% folder for manual remove. It´s not that hard cause 26 different name - // limit on windows mkstemp. - // unlink(path); - // close(fd); - delete[] path; -} - -char* str_replace(const char *string, const char *substr, const char *replacement) -{ - - /* if either substr or replacement is NULL, duplicate string a let caller handle it */ - if ( substr == NULL || replacement == NULL ) return strdup (string); - - char* newstr = strdup (string); - char* head = newstr; - char* tok; - while ( (tok = strstr( head, substr )) ) - { - char* oldstr = newstr; - newstr = (char *)malloc ( strlen ( oldstr ) - strlen ( substr ) + strlen ( replacement ) + 1 ); - /*failed to alloc mem, free old string and return NULL */ - if ( newstr == NULL ){ - free (oldstr); - return NULL; - } - memcpy ( newstr, oldstr, tok - oldstr ); - memcpy ( newstr + (tok - oldstr), replacement, strlen ( replacement ) ); - memcpy ( newstr + (tok - oldstr) + strlen( replacement ), tok + strlen ( substr ), strlen ( oldstr ) - strlen ( substr ) - ( tok - oldstr ) ); - memset ( newstr + strlen ( oldstr ) - strlen ( substr ) + strlen ( replacement ) , 0, 1 ); - /* move back head right after the last replacement */ - head = newstr + (tok - oldstr) + strlen( replacement ); - free (oldstr); - } - return newstr; -} - -int win32_system(const char* command) -{ - // >/dev/null TO >nul - return system(str_replace(command, "/dev/null", "nul")); -} - -int mkstemp(char * filetemplate) -{ - // on windows _mktemp generate only 26 unique filename - char *filename = _mktemp(filetemplate); - if (filename == NULL) { - return -1; - } - return open(filename, _O_RDWR |_O_BINARY | O_CREAT); -} - -/* - * LaunchChildProcess - * Sets up STARTUPINFO structure, and launches redirected child. - */ -int LaunchChildProcess(HANDLE hChildStdOut, - HANDLE hChildStdIn, - HANDLE hChildStdErr, - const char* command) -{ - PROCESS_INFORMATION pi; - STARTUPINFO si; - DWORD exit_code; - // Set up the start up info struct. - ZeroMemory(&pi, sizeof(PROCESS_INFORMATION)); - ZeroMemory(&si, sizeof(STARTUPINFO)); - si.cb = sizeof(STARTUPINFO); - si.dwFlags = STARTF_USESTDHANDLES; - si.wShowWindow = SW_HIDE; - si.hStdOutput = hChildStdOut; - si.hStdInput = hChildStdIn; - si.hStdError = hChildStdErr; - - if ( CreateProcess(NULL, /* module: null means use command line */ - (LPSTR)command, /* modified command line */ - NULL, /* thread handle inheritance */ - NULL, /* thread handle inheritance */ - TRUE, /* handles inheritable? */ - CREATE_NO_WINDOW, - NULL, /* environment: use parent */ - NULL, /* starting directory: use parent */ - &si,&pi) ) - - { - WaitForSingleObject(pi.hProcess, INFINITE); - } - else - { - char error_msg[] = "Error launching process: "; - char buf[_MAX_PATH + sizeof(error_msg)]; - snprintf(buf, sizeof buf, "%s%s", error_msg, command); - DisplayError(buf); - } - - GetExitCodeProcess(pi.hProcess, &exit_code); - - // Close any unnecessary handles. - if (!CloseHandle(pi.hProcess)) DisplayError("CloseHandle"); - if (!CloseHandle(pi.hThread)) DisplayError("CloseHandle"); - return exit_code; -} - -/* - * ReadAndHandleOutput - * Monitors handle for input. Exits when child exits or pipe breaks. - */ -void ReadAndHandleOutput(HANDLE hPipeRead, std::ostream& output) -{ - UCHAR lpBuffer[256]; - DWORD nBytesRead; - - while(TRUE) - { - memset(lpBuffer, 0, sizeof(lpBuffer)); - if (!ReadFile(hPipeRead,lpBuffer,sizeof(lpBuffer),&nBytesRead,NULL) || !nBytesRead) - { - if (GetLastError() == ERROR_BROKEN_PIPE) - break; // pipe done - normal exit path. - else - DisplayError("ReadFile"); // Something bad happened. - } - - output.write((const char *)lpBuffer, nBytesRead); - } -} - -/* - * DisplayError - * Displays the error number and corresponding message. - */ -void DisplayError(LPCSTR szPrefix) -{ - LPSTR lpsz = NULL; - DWORD cch = 0; - DWORD dwError = GetLastError(); - - cch = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER - | FORMAT_MESSAGE_FROM_SYSTEM - | FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, dwError, LANG_NEUTRAL, - (LPTSTR)&lpsz, 0, NULL); - if (cch < 1) { - cch = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER - | FORMAT_MESSAGE_FROM_STRING - | FORMAT_MESSAGE_ARGUMENT_ARRAY, - "Code 0x%1!08x!", - 0, LANG_NEUTRAL, (LPTSTR)&lpsz, 0, - (va_list*)&dwError); - } - fprintf(stderr, "%s: %s", szPrefix, lpsz); - LocalFree((HLOCAL)lpsz); - ExitProcess(-1); -} From cfd9901124d37ef6f78485817942474d8bd076e6 Mon Sep 17 00:00:00 2001 From: bySabi Files Date: Tue, 11 Feb 2014 10:38:31 +0100 Subject: [PATCH 08/16] fix --- util_win32.cpp | 317 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 317 insertions(+) create mode 100644 util_win32.cpp diff --git a/util_win32.cpp b/util_win32.cpp new file mode 100644 index 0000000..ba53c35 --- /dev/null +++ b/util_win32.cpp @@ -0,0 +1,317 @@ +/* + * Copyright 2012 Andrew Ayer + * Copyright 2014 bySabi Files + * + * 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 . + * + * 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. + */ + +#undef __STRICT_ANSI__ //needed for _fullpath +#include "util.hpp" +#include +#include +#include + +#include +#include +#include +#include + + +int LaunchChildProcess(HANDLE hChildStdOut, + HANDLE hChildStdIn, + HANDLE hChildStdErr, + const char* command); +void ReadAndHandleOutput(HANDLE hPipeRead, std::ostream& output); +int mkstemp(char *name); +void DisplayError(LPCSTR wszPrefix); + + +int exec_command (const char* command, std::ostream& output) +{ + HANDLE hOutputReadTmp,hOutputRead,hOutputWrite; + HANDLE hErrorWrite; + SECURITY_ATTRIBUTES sa; + + // Set up the security attributes struct. + sa.nLength= sizeof(SECURITY_ATTRIBUTES); + sa.lpSecurityDescriptor = NULL; + sa.bInheritHandle = TRUE; + + // Create the child output pipe. + if (!CreatePipe(&hOutputReadTmp,&hOutputWrite,&sa,0)) + DisplayError("CreatePipe"); + + // Create a duplicate of the output write handle for the std error + // write handle. This is necessary in case the child application + // closes one of its std output handles. + if (!DuplicateHandle(GetCurrentProcess(),hOutputWrite, + GetCurrentProcess(),&hErrorWrite,0, + TRUE,DUPLICATE_SAME_ACCESS)) + DisplayError("DuplicateHandle"); + + // Create new output read handle. Set + // the Properties to FALSE. Otherwise, the child inherits the + // properties and, as a result, non-closeable handles to the pipes + // are created. + if (!DuplicateHandle(GetCurrentProcess(),hOutputReadTmp, + GetCurrentProcess(), + &hOutputRead, // Address of new handle. + 0,FALSE, // Make it uninheritable. + DUPLICATE_SAME_ACCESS)) + DisplayError("DuplicateHandle"); + + // Close inheritable copies of the handles you do not want to be + // inherited. + if (!CloseHandle(hOutputReadTmp)) DisplayError("CloseHandle"); + + // Launch child process + int status = LaunchChildProcess(hOutputWrite ,NULL ,hErrorWrite, command); + + // Close pipe handles (do not continue to modify the parent). + // You need to make sure that no handles to the write end of the + // output pipe are maintained in this process or else the pipe will + // not close when the child process exits and the ReadFile will hang. + if (!CloseHandle(hOutputWrite)) DisplayError("CloseHandle"); + if (!CloseHandle(hErrorWrite)) DisplayError("CloseHandle"); + + // Read the child's output. + ReadAndHandleOutput(hOutputRead, output); + + if (!CloseHandle(hOutputRead)) DisplayError("CloseHandle"); + + return status; +} + +std::string escape_shell_arg (const std::string& str) +{ + std::string new_str; + new_str.push_back('"'); + for (std::string::const_iterator it(str.begin()); it != str.end(); ++it) { + if (*it == '"' || *it == '$' || *it == '`') { + new_str.push_back('\\'); + } + if (*it == '\\') { + new_str += '/'; + } + else + new_str.push_back(*it); + } + new_str.push_back('"'); + return new_str; +} + +std::string resolve_path (const char* path) +{ + char retname[_MAX_PATH]; + _fullpath(retname, path, _MAX_PATH); + return std::string(retname);; +} + +void open_tempfile (std::fstream& file, std::ios_base::openmode mode) +{ + const char* tmpdir = getenv("TEMP"); + size_t tmpdir_len; + if (tmpdir) { + tmpdir_len = strlen(tmpdir); + } else { + tmpdir = "/tmp"; + tmpdir_len = 4; + } + char* path = new char[tmpdir_len + 18]; + strcpy(path, tmpdir); + strcpy(path + tmpdir_len, "/git-crypt.XXXXXX"); + + int fd = mkstemp(path); + + if (fd == -1) { + perror("mkstemp"); + std::exit(9); + } + + file.open(path, mode); + if (!file.is_open()) { + perror("open"); + unlink(path); + std::exit(9); + } + + //FIXME + // On windows we cannot remove open files, git-crypt.XXXXXX temporary files will + // remain on %TEMP% folder for manual remove. It´s not that hard cause 26 different name + // limit on windows mkstemp. + // unlink(path); + // close(fd); + delete[] path; +} + +char* str_replace(const char *string, const char *substr, const char *replacement) +{ + + /* if either substr or replacement is NULL, duplicate string a let caller handle it */ + if ( substr == NULL || replacement == NULL ) return strdup (string); + + char* newstr = strdup (string); + char* head = newstr; + char* tok; + while ( (tok = strstr( head, substr )) ) + { + char* oldstr = newstr; + newstr = (char *)malloc ( strlen ( oldstr ) - strlen ( substr ) + strlen ( replacement ) + 1 ); + /*failed to alloc mem, free old string and return NULL */ + if ( newstr == NULL ){ + free (oldstr); + return NULL; + } + memcpy ( newstr, oldstr, tok - oldstr ); + memcpy ( newstr + (tok - oldstr), replacement, strlen ( replacement ) ); + memcpy ( newstr + (tok - oldstr) + strlen( replacement ), tok + strlen ( substr ), strlen ( oldstr ) - strlen ( substr ) - ( tok - oldstr ) ); + memset ( newstr + strlen ( oldstr ) - strlen ( substr ) + strlen ( replacement ) , 0, 1 ); + /* move back head right after the last replacement */ + head = newstr + (tok - oldstr) + strlen( replacement ); + free (oldstr); + } + return newstr; +} + +int win32_system(const char* command) +{ + // >/dev/null TO >nul + return system(str_replace(command, "/dev/null", "nul")); +} + +int mkstemp(char * filetemplate) +{ + // on windows _mktemp generate only 26 unique filename + char *filename = _mktemp(filetemplate); + if (filename == NULL) { + return -1; + } + return open(filename, _O_RDWR |_O_BINARY | O_CREAT); +} + +/* + * LaunchChildProcess + * Sets up STARTUPINFO structure, and launches redirected child. + */ +int LaunchChildProcess(HANDLE hChildStdOut, + HANDLE hChildStdIn, + HANDLE hChildStdErr, + const char* command) +{ + PROCESS_INFORMATION pi; + STARTUPINFO si; + DWORD exit_code; + // Set up the start up info struct. + ZeroMemory(&pi, sizeof(PROCESS_INFORMATION)); + ZeroMemory(&si, sizeof(STARTUPINFO)); + si.cb = sizeof(STARTUPINFO); + si.dwFlags = STARTF_USESTDHANDLES; + si.wShowWindow = SW_HIDE; + si.hStdOutput = hChildStdOut; + si.hStdInput = hChildStdIn; + si.hStdError = hChildStdErr; + + if ( CreateProcess(NULL, /* module: null means use command line */ + (LPSTR)command, /* modified command line */ + NULL, /* thread handle inheritance */ + NULL, /* thread handle inheritance */ + TRUE, /* handles inheritable? */ + CREATE_NO_WINDOW, + NULL, /* environment: use parent */ + NULL, /* starting directory: use parent */ + &si,&pi) ) + + { + WaitForSingleObject(pi.hProcess, INFINITE); + } + else + { + char error_msg[] = "Error launching process: "; + char buf[_MAX_PATH + sizeof(error_msg)]; + snprintf(buf, sizeof buf, "%s%s", error_msg, command); + DisplayError(buf); + } + + GetExitCodeProcess(pi.hProcess, &exit_code); + + // Close any unnecessary handles. + if (!CloseHandle(pi.hProcess)) DisplayError("CloseHandle"); + if (!CloseHandle(pi.hThread)) DisplayError("CloseHandle"); + return exit_code; +} + +/* + * ReadAndHandleOutput + * Monitors handle for input. Exits when child exits or pipe breaks. + */ +void ReadAndHandleOutput(HANDLE hPipeRead, std::ostream& output) +{ + UCHAR lpBuffer[256]; + DWORD nBytesRead; + + while(TRUE) + { + memset(lpBuffer, 0, sizeof(lpBuffer)); + if (!ReadFile(hPipeRead,lpBuffer,sizeof(lpBuffer),&nBytesRead,NULL) || !nBytesRead) + { + if (GetLastError() == ERROR_BROKEN_PIPE) + break; // pipe done - normal exit path. + else + DisplayError("ReadFile"); // Something bad happened. + } + + output.write((const char *)lpBuffer, nBytesRead); + } +} + +/* + * DisplayError + * Displays the error number and corresponding message. + */ +void DisplayError(LPCSTR szPrefix) +{ + LPSTR lpsz = NULL; + DWORD cch = 0; + DWORD dwError = GetLastError(); + + cch = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER + | FORMAT_MESSAGE_FROM_SYSTEM + | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, dwError, LANG_NEUTRAL, + (LPTSTR)&lpsz, 0, NULL); + if (cch < 1) { + cch = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER + | FORMAT_MESSAGE_FROM_STRING + | FORMAT_MESSAGE_ARGUMENT_ARRAY, + "Code 0x%1!08x!", + 0, LANG_NEUTRAL, (LPTSTR)&lpsz, 0, + (va_list*)&dwError); + } + fprintf(stderr, "%s: %s", szPrefix, lpsz); + LocalFree((HLOCAL)lpsz); + ExitProcess(-1); +} From 194fe74758e43c4aedd28997f59b14fd2d91e58f Mon Sep 17 00:00:00 2001 From: bySabi Files Date: Tue, 11 Feb 2014 12:18:27 +0100 Subject: [PATCH 09/16] fixes --- commands.cpp | 2 +- git-crypt.cpp | 16 +--------------- util.hpp | 2 ++ util_win32.cpp | 13 +++++++++++++ 4 files changed, 17 insertions(+), 16 deletions(-) diff --git a/commands.cpp b/commands.cpp index ac93d83..60e8efc 100644 --- a/commands.cpp +++ b/commands.cpp @@ -170,7 +170,7 @@ void diff (const char* keyfile, const char* filename) load_keys(keyfile, &keys); // Open the file - std::ifstream in(filename); + std::ifstream in(filename, std::ios::binary); if (!in) { perror(filename); std::exit(1); diff --git a/git-crypt.cpp b/git-crypt.cpp index babe636..11d88d4 100644 --- a/git-crypt.cpp +++ b/git-crypt.cpp @@ -34,11 +34,6 @@ #include #include -#ifdef __WIN32__ -#include -#include -#endif - static void print_usage (const char* argv0) { std::clog << "Usage: " << argv0 << " COMMAND [ARGS ...]\n"; @@ -64,16 +59,7 @@ try { std::cout.exceptions(std::ios_base::badbit); #ifdef __WIN32__ - int result = _setmode( _fileno(stdin), _O_BINARY ); - if( result == -1 ) { - std::cerr <<"Cannot set input mode to binary." < Date: Tue, 11 Feb 2014 13:53:51 +0100 Subject: [PATCH 10/16] fix dll dependecy --- Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile b/Makefile index 3919a74..5d50ffd 100644 --- a/Makefile +++ b/Makefile @@ -9,6 +9,7 @@ INSTALL = install -m 755 git-crypt $(PREFIX)/bin/ ifeq ($(OS),Windows_NT) LDFLAGS = -llibeay32 -lwsock32 + CXXFLAGS += -static-libgcc -static-libstdc++ OBJFILES = git-crypt.o commands.o crypto.o util_win32.o INSTALL = cp git-crypt.exe $(PREFIX)/bin/ endif From 65dea4eb996666d3ce6e05b299114af3cb7687d1 Mon Sep 17 00:00:00 2001 From: bySabi Files Date: Tue, 11 Feb 2014 16:55:09 +0100 Subject: [PATCH 11/16] Improved test --- .gitignore | 2 - Makefile | 3 +- test.sh | 144 ++++++++++++++++++++++++++++++++++++++--------------- 3 files changed, 107 insertions(+), 42 deletions(-) diff --git a/.gitignore b/.gitignore index 801d8b0..1efbcc4 100644 --- a/.gitignore +++ b/.gitignore @@ -2,5 +2,3 @@ *.exe git-crypt test/ -doit.sh - diff --git a/Makefile b/Makefile index 5d50ffd..01e4fc7 100644 --- a/Makefile +++ b/Makefile @@ -9,7 +9,8 @@ INSTALL = install -m 755 git-crypt $(PREFIX)/bin/ ifeq ($(OS),Windows_NT) LDFLAGS = -llibeay32 -lwsock32 - CXXFLAGS += -static-libgcc -static-libstdc++ + CXXFLAGS += -static-libgcc +# CXXFLAGS += -static-libgcc -static-libstdc++ OBJFILES = git-crypt.o commands.o crypto.o util_win32.o INSTALL = cp git-crypt.exe $(PREFIX)/bin/ endif diff --git a/test.sh b/test.sh index 2371e13..9b87dfa 100755 --- a/test.sh +++ b/test.sh @@ -3,13 +3,14 @@ use strict; use warnings; use Cwd; use File::Path; +use File::Copy; use Term::ANSIColor; use Digest::MD5 qw(md5); print "\n"."========= GIT-CRYPT TEST ========="."\n"; - -my $dir=Cwd::cwd()."/test"; +my $cdir=Cwd::cwd(); +my $dir=$cdir."/test"; ### Set test folder if ( -d $dir ) { @@ -33,93 +34,99 @@ mkpath($repo) or die "Cannot create '$repo' : $!"; chdir($repo); print "\n"; -my $out=`git init`; !($?) or die; +my $out=`git init `; !($?) or die; print $out; ## put some files -my $file1="crypto.hpp"; -my $file2="crypto.tgz"; +my @files_hpp=glob "$cdir/*.hpp"; +my @files_cpp=glob "$cdir/*.cpp"; -`curl -sS "https://raw.github.com/AGWA/git-crypt/master/crypto.hpp" > $file1`; !($?) or die; -`tar -zcf $file2 $file1`; !($?) or die; +foreach my $f (@files_hpp) { copy "$f", "." or die; } +print "add: *.hpp files"."\n"; +foreach my $f (@files_cpp) { copy "$f", "." or die; } +print "add: *.cpp files"."\n"; -print "add file: ".$file1."\n"; -print "add file: ".$file2."\n"; +my $all_hpp = join ' ', @files_hpp; +`tar -zcf "hpp.tgz" $all_hpp 2>&1`; !($?) or die; +print "add: hpp.tgz file"."\n"; +my $all_cpp = join ' ', @files_cpp; +`tar -zcf "cpp.tgz" $all_cpp 2>&1`; !($?) or die; +print "add: cpp.tgz file"."\n"; open (FILE, '>>.gitattributes'); print FILE "*.hpp filter=git-crypt diff=git-crypt"."\n"; +print FILE "*.cpp filter=git-crypt diff=git-crypt"."\n"; print FILE "*.tgz filter=git-crypt diff=git-crypt"."\n"; close (FILE); -print "set .gitattributes filter for: *.hpp *.tgz"."\n"; +print "set .gitattributes filter for: *.hpp *.cpp *.tgz"."\n"; -print "Initialized git-crypt repository"."\n"; -`git-crypt init ../$key`; !($?) or die; +print "Initialized git-crypt repository with key: $dir/$key"."\n"; +`git-crypt init $dir/$key`; !($?) or die; print "git add & commit files"."\n"; `git add --all`; !($?) or die; `git commit -m "test git-crypt"`; !($?) or die; - -### Clone git repository - chdir($dir); + print "\n"."======= CLONE GIT ENCRYPTED REPO ======="."\n"; my $clonerepo="clonerepo"; `git clone --quiet file://'$dir/$repo' $clonerepo`; !($?) or die; -print "\n"."Clone Git repository in "."$dir/$clonerepo/"."\n"; +print "\n"."Clone Encrypted Git repository in "."$dir/$clonerepo/"."\n"; + ### TEST -chdir("$dir/$clonerepo"); ### Test#1 ## isencrypted clone repo ? -print "\n"."======= TEST 1: isencrypted clone repo? ======="."\n"; +chdir("$dir/$clonerepo"); +print "\n"."======= TEST 1: isencrypted clone repo? ======="."\n"; print "\n"; -if ( isencrypted($file1) ) { - print "\"$file1\" encrypted?: ".colored("OK", "green")."\n"; -} else { - print "\"$file1\" encrypted?: ".colored("FAIL", "red")."\n"; -} -if ( isencrypted($file2) ) { - print "\"$file2\" encrypted?: ".colored("OK", "green")."\n"; -} else { - print "\"$file2\" encrypted?: ".colored("FAIL", "red")."\n"; +my @all_files=glob("*.hpp *.cpp *.tgz"); +foreach my $file (@all_files) { + print "\"$file\" encrypted?: "; + if ( isencrypted($file) ){ + print colored("OK", "green")."\n"; + } else{ + print colored("FAIL", "red")."\n"; + } } +print "\n"; + ### Test#2 ## decrypt clone repo print "\n"."======= TEST 2: decrypt clone repo ======="."\n"; +print "\n"; -`git-crypt init ../$key`; !($?) or die; +print "Initialized git-crypt repository with key: $dir/$key"."\n"; +`git-crypt init $dir/$key`; !($?) or die; print "\n"; -if ( isdecrypted($file1) ) { - print "\"$file1\" decrypted?: ".colored("OK", "green")."\n"; -} else { - print "\"$file1\" decrypted?: ".colored("FAIL", "red")."\n"; +foreach my $file (@all_files) { + print "\"$file\" decrypted?: "; + if ( isdecrypted($file) ){ + print colored("OK", "green")."\n"; + } else{ + print colored("FAIL", "red")."\n"; + } } -if ( isdecrypted($file2) ) { - print "\"$file2\" decrypted?: ".colored("OK", "green")."\n"; -} else { - print "\"$file2\" decrypted?: ".colored("FAIL", "red")."\n"; -} print "\n"; - sub isencrypted { my $crypthead="\x00GITCRYPT\x00"; - my $file = shift; + my $file = "$dir/$clonerepo/".shift; open (FILE, $file) or die "Can't open '$file' : $!"; binmode(FILE) or die "Can't binmode '$file' : $!"; my $filehead; @@ -132,6 +139,7 @@ sub isencrypted { return 0; } + sub isdecrypted { my $file = shift; if ( getmd5("$dir/$repo/$file") eq getmd5("$dir/$clonerepo/$file") ) { @@ -149,4 +157,62 @@ sub getmd5 { return md5($data); } + +=begin comment +print "\n"; +if ( isencrypted($file1) ) { + print "\"$file1\" encrypted?: ".colored("OK", "green")."\n"; +} else { + print "\"$file1\" encrypted?: ".colored("FAIL", "red")."\n"; +} + + + + + + + + + + + +### Clone git repository + +chdir($dir); + + + + + +if ( isencrypted($file2) ) { + print "\"$file2\" encrypted?: ".colored("OK", "green")."\n"; +} else { + print "\"$file2\" encrypted?: ".colored("FAIL", "red")."\n"; +} + + + + +print "\n"; +if ( isdecrypted($file1) ) { + print "\"$file1\" decrypted?: ".colored("OK", "green")."\n"; +} else { + print "\"$file1\" decrypted?: ".colored("FAIL", "red")."\n"; +} + +if ( isdecrypted($file2) ) { + print "\"$file2\" decrypted?: ".colored("OK", "green")."\n"; +} else { + print "\"$file2\" decrypted?: ".colored("FAIL", "red")."\n"; +} +print "\n"; + + + + + + +=end comment +=cut + exit 0 \ No newline at end of file From a1ea7b684564d6709f11f949bee7e99b84c1c9ce Mon Sep 17 00:00:00 2001 From: bySabi Files Date: Tue, 11 Feb 2014 17:00:24 +0100 Subject: [PATCH 12/16] Improved test --- test.sh | 59 +-------------------------------------------------------- 1 file changed, 1 insertion(+), 58 deletions(-) diff --git a/test.sh b/test.sh index 9b87dfa..dfd9ca0 100755 --- a/test.sh +++ b/test.sh @@ -158,61 +158,4 @@ sub getmd5 { } -=begin comment -print "\n"; -if ( isencrypted($file1) ) { - print "\"$file1\" encrypted?: ".colored("OK", "green")."\n"; -} else { - print "\"$file1\" encrypted?: ".colored("FAIL", "red")."\n"; -} - - - - - - - - - - - -### Clone git repository - -chdir($dir); - - - - - -if ( isencrypted($file2) ) { - print "\"$file2\" encrypted?: ".colored("OK", "green")."\n"; -} else { - print "\"$file2\" encrypted?: ".colored("FAIL", "red")."\n"; -} - - - - -print "\n"; -if ( isdecrypted($file1) ) { - print "\"$file1\" decrypted?: ".colored("OK", "green")."\n"; -} else { - print "\"$file1\" decrypted?: ".colored("FAIL", "red")."\n"; -} - -if ( isdecrypted($file2) ) { - print "\"$file2\" decrypted?: ".colored("OK", "green")."\n"; -} else { - print "\"$file2\" decrypted?: ".colored("FAIL", "red")."\n"; -} -print "\n"; - - - - - - -=end comment -=cut - -exit 0 \ No newline at end of file +exit 0; From fbbf04eab2d11584afe66f59417c4db00e5fabf1 Mon Sep 17 00:00:00 2001 From: bySabi Files Date: Wed, 12 Feb 2014 08:13:33 +0100 Subject: [PATCH 13/16] fix temp files unlink --- .gitignore | 2 +- commands.cpp | 5 +++-- util.hpp | 17 ++++++++++++++--- util_win32.cpp | 29 ++++++++++++++++++----------- 4 files changed, 36 insertions(+), 17 deletions(-) diff --git a/.gitignore b/.gitignore index 1efbcc4..7e41e79 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ *.o -*.exe git-crypt +git-crypt.exe test/ diff --git a/commands.cpp b/commands.cpp index 60e8efc..790a3ff 100644 --- a/commands.cpp +++ b/commands.cpp @@ -46,9 +46,10 @@ #include #include - #ifdef __WIN32__ #define system(a) win32_system(a) +#else +typedef std::fstream temp_fstream; #endif @@ -63,7 +64,7 @@ void clean (const char* keyfile) hmac_sha1_state hmac(keys.hmac, HMAC_KEY_LEN); // Calculate the file's SHA1 HMAC as we go uint64_t file_size = 0; // Keep track of the length, make sure it doesn't get too big std::string file_contents; // First 8MB or so of the file go here - std::fstream temp_file; // The rest of the file spills into a temporary file on disk + temp_fstream temp_file;// The rest of the file spills into a temporary file on disk temp_file.exceptions(std::fstream::badbit); char buffer[1024]; diff --git a/util.hpp b/util.hpp index 0bf3b05..8d8c4c7 100644 --- a/util.hpp +++ b/util.hpp @@ -34,17 +34,28 @@ #include #include #include +#include -int exec_command (const char* command, std::ostream& output); + +int exec_command (const char* command, std::ostream& output); std::string resolve_path (const char* path); void open_tempfile (std::fstream&, std::ios_base::openmode); std::string escape_shell_arg (const std::string&); #ifdef __WIN32__ -int win32_system (const char* command); -void set_cin_cout_binary_mode(void); +int win32_system (const char* command); +void set_cin_cout_binary_mode(void); + +class temp_fstream : public std::fstream { +public: + void open (const char *fname, std::ios_base::openmode mode); + virtual ~temp_fstream(); +private: + const char *fileName; +}; #endif + #endif diff --git a/util_win32.cpp b/util_win32.cpp index d7b9ff9..3aa1224 100644 --- a/util_win32.cpp +++ b/util_win32.cpp @@ -36,6 +36,7 @@ #include #include +#include #include #include #include @@ -50,6 +51,7 @@ int mkstemp(char *name); void DisplayError(LPCSTR wszPrefix); + int exec_command (const char* command, std::ostream& output) { HANDLE hOutputReadTmp,hOutputRead,hOutputWrite; @@ -144,30 +146,35 @@ void open_tempfile (std::fstream& file, std::ios_base::openmode mode) char* path = new char[tmpdir_len + 18]; strcpy(path, tmpdir); strcpy(path + tmpdir_len, "/git-crypt.XXXXXX"); - int fd = mkstemp(path); - if (fd == -1) { perror("mkstemp"); std::exit(9); } - - file.open(path, mode); + static_cast(file).open(path, mode); if (!file.is_open()) { perror("open"); - unlink(path); + _unlink(path); std::exit(9); } - - //FIXME - // On windows we cannot remove open files, git-crypt.XXXXXX temporary files will - // remain on %TEMP% folder for manual remove. It´s not that hard cause 26 different name - // limit on windows mkstemp. + // On windows we cannot remove open files. // unlink(path); - // close(fd); + close(fd); delete[] path; } +void temp_fstream::open (const char *fname, std::ios_base::openmode mode) +{ + fileName = strdup(fname); + std::fstream::open(fname, mode); +} + +temp_fstream::~temp_fstream() +{ + if (this->is_open()) this->close(); + _unlink(fileName); +} + void set_cin_cout_binary_mode() { int result = _setmode( _fileno(stdin), _O_BINARY ); From 9049f8c26ee7cfcba9f180ab17829c936dda3194 Mon Sep 17 00:00:00 2001 From: bySabi Files Date: Wed, 12 Feb 2014 09:25:23 +0100 Subject: [PATCH 14/16] add fileName NULL check on temp_fstream --- Makefile | 4 ++-- util.hpp | 3 ++- util_win32.cpp | 9 +++++++-- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index 01e4fc7..9aff2dc 100644 --- a/Makefile +++ b/Makefile @@ -9,8 +9,8 @@ INSTALL = install -m 755 git-crypt $(PREFIX)/bin/ ifeq ($(OS),Windows_NT) LDFLAGS = -llibeay32 -lwsock32 - CXXFLAGS += -static-libgcc -# CXXFLAGS += -static-libgcc -static-libstdc++ +# CXXFLAGS += -static-libgcc + CXXFLAGS += -static-libgcc -static-libstdc++ OBJFILES = git-crypt.o commands.o crypto.o util_win32.o INSTALL = cp git-crypt.exe $(PREFIX)/bin/ endif diff --git a/util.hpp b/util.hpp index 8d8c4c7..78d4962 100644 --- a/util.hpp +++ b/util.hpp @@ -49,10 +49,11 @@ void set_cin_cout_binary_mode(void); class temp_fstream : public std::fstream { public: + temp_fstream(); void open (const char *fname, std::ios_base::openmode mode); virtual ~temp_fstream(); private: - const char *fileName; + char *fileName; }; #endif diff --git a/util_win32.cpp b/util_win32.cpp index 3aa1224..d64ea53 100644 --- a/util_win32.cpp +++ b/util_win32.cpp @@ -163,6 +163,9 @@ void open_tempfile (std::fstream& file, std::ios_base::openmode mode) delete[] path; } +temp_fstream::temp_fstream(): std::fstream(), fileName(NULL) +{} + void temp_fstream::open (const char *fname, std::ios_base::openmode mode) { fileName = strdup(fname); @@ -171,8 +174,10 @@ void temp_fstream::open (const char *fname, std::ios_base::openmode mode) temp_fstream::~temp_fstream() { - if (this->is_open()) this->close(); - _unlink(fileName); + if ( this->is_open() ) + this->close(); + if ( fileName != NULL ) + _unlink(fileName); } void set_cin_cout_binary_mode() From 592a76a50b52d8a6033a06f304f731c5253b86b3 Mon Sep 17 00:00:00 2001 From: bySabi Date: Wed, 12 Feb 2014 09:54:24 +0100 Subject: [PATCH 15/16] fix many typos --- commands.cpp | 2 +- util.hpp | 12 ++--- util_win32.cpp | 116 +++++++++++++++++++++++-------------------------- 3 files changed, 61 insertions(+), 69 deletions(-) mode change 100644 => 100755 util.hpp mode change 100644 => 100755 util_win32.cpp diff --git a/commands.cpp b/commands.cpp index 790a3ff..fe6d246 100644 --- a/commands.cpp +++ b/commands.cpp @@ -64,7 +64,7 @@ void clean (const char* keyfile) hmac_sha1_state hmac(keys.hmac, HMAC_KEY_LEN); // Calculate the file's SHA1 HMAC as we go uint64_t file_size = 0; // Keep track of the length, make sure it doesn't get too big std::string file_contents; // First 8MB or so of the file go here - temp_fstream temp_file;// The rest of the file spills into a temporary file on disk + temp_fstream temp_file; // The rest of the file spills into a temporary file on disk temp_file.exceptions(std::fstream::badbit); char buffer[1024]; diff --git a/util.hpp b/util.hpp old mode 100644 new mode 100755 index 78d4962..fb71e94 --- a/util.hpp +++ b/util.hpp @@ -44,16 +44,16 @@ std::string escape_shell_arg (const std::string&); #ifdef __WIN32__ -int win32_system (const char* command); -void set_cin_cout_binary_mode(void); +int win32_system (const char* command); +void set_cin_cout_binary_mode (void); -class temp_fstream : public std::fstream { +class temp_fstream : public std::fstream { public: temp_fstream(); - void open (const char *fname, std::ios_base::openmode mode); - virtual ~temp_fstream(); + void open (const char *fname, std::ios_base::openmode mode); + virtual ~temp_fstream(); private: - char *fileName; + char *fileName; }; #endif diff --git a/util_win32.cpp b/util_win32.cpp old mode 100644 new mode 100755 index d64ea53..3f298aa --- a/util_win32.cpp +++ b/util_win32.cpp @@ -34,7 +34,6 @@ #include #include #include - #include #include #include @@ -42,24 +41,24 @@ #include -int LaunchChildProcess(HANDLE hChildStdOut, +int LaunchChildProcess (HANDLE hChildStdOut, HANDLE hChildStdIn, HANDLE hChildStdErr, const char* command); -void ReadAndHandleOutput(HANDLE hPipeRead, std::ostream& output); -int mkstemp(char *name); -void DisplayError(LPCSTR wszPrefix); +void ReadAndHandleOutput (HANDLE hPipeRead, std::ostream& output); +int mkstemp (char *name); +void DisplayError (LPCSTR wszPrefix); -int exec_command (const char* command, std::ostream& output) +int exec_command (const char* command, std::ostream& output) { - HANDLE hOutputReadTmp,hOutputRead,hOutputWrite; - HANDLE hErrorWrite; - SECURITY_ATTRIBUTES sa; + HANDLE hOutputReadTmp,hOutputRead,hOutputWrite; + HANDLE hErrorWrite; + SECURITY_ATTRIBUTES sa; // Set up the security attributes struct. - sa.nLength= sizeof(SECURITY_ATTRIBUTES); + sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.lpSecurityDescriptor = NULL; sa.bInheritHandle = TRUE; @@ -91,7 +90,7 @@ int exec_command (const char* command, std::ostream& output) if (!CloseHandle(hOutputReadTmp)) DisplayError("CloseHandle"); // Launch child process - int status = LaunchChildProcess(hOutputWrite ,NULL ,hErrorWrite, command); + int status = LaunchChildProcess(hOutputWrite ,NULL ,hErrorWrite, command); // Close pipe handles (do not continue to modify the parent). // You need to make sure that no handles to the write end of the @@ -128,9 +127,9 @@ std::string escape_shell_arg (const std::string& str) std::string resolve_path (const char* path) { - char retname[_MAX_PATH]; + char retname[_MAX_PATH]; _fullpath(retname, path, _MAX_PATH); - return std::string(retname);; + return std::string(retname);; } void open_tempfile (std::fstream& file, std::ios_base::openmode mode) @@ -157,13 +156,13 @@ void open_tempfile (std::fstream& file, std::ios_base::openmode mode) _unlink(path); std::exit(9); } - // On windows we cannot remove open files. + // on windows can´t remove open files. // unlink(path); close(fd); delete[] path; } -temp_fstream::temp_fstream(): std::fstream(), fileName(NULL) +temp_fstream::temp_fstream () : std::fstream(), fileName(NULL) {} void temp_fstream::open (const char *fname, std::ios_base::openmode mode) @@ -172,42 +171,38 @@ void temp_fstream::open (const char *fname, std::ios_base::openmode mode) std::fstream::open(fname, mode); } -temp_fstream::~temp_fstream() +temp_fstream::~temp_fstream () { - if ( this->is_open() ) + if (this->is_open()) this->close(); - if ( fileName != NULL ) + if (fileName != NULL) _unlink(fileName); } -void set_cin_cout_binary_mode() +void set_cin_cout_binary_mode () { - int result = _setmode( _fileno(stdin), _O_BINARY ); - if( result == -1 ){ + int result = _setmode(_fileno(stdin), _O_BINARY ); + if (result == -1) throw std::ios_base::failure("Cannot set input mode to binary."); - } - result = _setmode( _fileno(stdout), _O_BINARY ); - if( result == -1 ){ + result = _setmode(_fileno(stdout), _O_BINARY ); + if ( result == -1) throw std::ios_base::failure("Cannot set output mode to binary."); - } } -char* str_replace(const char *string, const char *substr, const char *replacement) +char* str_replace (const char *string, const char *substr, const char *replacement) { - /* if either substr or replacement is NULL, duplicate string a let caller handle it */ - if ( substr == NULL || replacement == NULL ) return strdup (string); - - char* newstr = strdup (string); - char* head = newstr; - char* tok; + if (substr == NULL || replacement == NULL) return strdup (string); + char* newstr = strdup (string); + char* head = newstr; + char* tok; while ( (tok = strstr( head, substr )) ) { - char* oldstr = newstr; + char* oldstr = newstr; newstr = (char *)malloc ( strlen ( oldstr ) - strlen ( substr ) + strlen ( replacement ) + 1 ); /*failed to alloc mem, free old string and return NULL */ - if ( newstr == NULL ){ + if ( newstr == NULL ) { free (oldstr); return NULL; } @@ -222,16 +217,16 @@ char* str_replace(const char *string, const char *substr, const char *replacemen return newstr; } -int win32_system(const char* command) +int win32_system (const char* command) { // >/dev/null TO >nul return system(str_replace(command, "/dev/null", "nul")); } -int mkstemp(char * filetemplate) +int mkstemp (char * filetemplate) { // on windows _mktemp generate only 26 unique filename - char *filename = _mktemp(filetemplate); + char* filename = _mktemp(filetemplate); if (filename == NULL) { return -1; } @@ -242,14 +237,14 @@ int mkstemp(char * filetemplate) * LaunchChildProcess * Sets up STARTUPINFO structure, and launches redirected child. */ -int LaunchChildProcess(HANDLE hChildStdOut, +int LaunchChildProcess (HANDLE hChildStdOut, HANDLE hChildStdIn, HANDLE hChildStdErr, const char* command) { - PROCESS_INFORMATION pi; - STARTUPINFO si; - DWORD exit_code; + PROCESS_INFORMATION pi; + STARTUPINFO si; + DWORD exit_code; // Set up the start up info struct. ZeroMemory(&pi, sizeof(PROCESS_INFORMATION)); ZeroMemory(&si, sizeof(STARTUPINFO)); @@ -260,29 +255,27 @@ int LaunchChildProcess(HANDLE hChildStdOut, si.hStdInput = hChildStdIn; si.hStdError = hChildStdErr; - if ( CreateProcess(NULL, /* module: null means use command line */ - (LPSTR)command, /* modified command line */ - NULL, /* thread handle inheritance */ - NULL, /* thread handle inheritance */ - TRUE, /* handles inheritable? */ + if (CreateProcess(NULL, /* module: null means use command line */ + (LPSTR)command, /* modified command line */ + NULL, /* thread handle inheritance */ + NULL, /* thread handle inheritance */ + TRUE, /* handles inheritable? */ CREATE_NO_WINDOW, - NULL, /* environment: use parent */ - NULL, /* starting directory: use parent */ - &si,&pi) ) + NULL, /* environment: use parent */ + NULL, /* starting directory: use parent */ + &si,&pi)) { WaitForSingleObject(pi.hProcess, INFINITE); } else { - char error_msg[] = "Error launching process: "; - char buf[_MAX_PATH + sizeof(error_msg)]; + char error_msg[] = "Error launching process: "; + char buf[_MAX_PATH + sizeof(error_msg)]; snprintf(buf, sizeof buf, "%s%s", error_msg, command); DisplayError(buf); } - GetExitCodeProcess(pi.hProcess, &exit_code); - // Close any unnecessary handles. if (!CloseHandle(pi.hProcess)) DisplayError("CloseHandle"); if (!CloseHandle(pi.hThread)) DisplayError("CloseHandle"); @@ -293,12 +286,12 @@ int LaunchChildProcess(HANDLE hChildStdOut, * ReadAndHandleOutput * Monitors handle for input. Exits when child exits or pipe breaks. */ -void ReadAndHandleOutput(HANDLE hPipeRead, std::ostream& output) +void ReadAndHandleOutput (HANDLE hPipeRead, std::ostream& output) { - UCHAR lpBuffer[256]; - DWORD nBytesRead; + UCHAR lpBuffer[256]; + DWORD nBytesRead; - while(TRUE) + while (TRUE) { memset(lpBuffer, 0, sizeof(lpBuffer)); if (!ReadFile(hPipeRead,lpBuffer,sizeof(lpBuffer),&nBytesRead,NULL) || !nBytesRead) @@ -308,7 +301,6 @@ void ReadAndHandleOutput(HANDLE hPipeRead, std::ostream& output) else DisplayError("ReadFile"); // Something bad happened. } - output.write((const char *)lpBuffer, nBytesRead); } } @@ -317,11 +309,11 @@ void ReadAndHandleOutput(HANDLE hPipeRead, std::ostream& output) * DisplayError * Displays the error number and corresponding message. */ -void DisplayError(LPCSTR szPrefix) +void DisplayError (LPCSTR szPrefix) { - LPSTR lpsz = NULL; - DWORD cch = 0; - DWORD dwError = GetLastError(); + LPSTR lpsz = NULL; + DWORD cch = 0; + DWORD dwError = GetLastError(); cch = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM From 1c9c99d09b754443aa1c7a1acab8cec570cbe330 Mon Sep 17 00:00:00 2001 From: bySabi Date: Wed, 12 Feb 2014 11:30:39 +0100 Subject: [PATCH 16/16] chmod files --- util.hpp | 0 util_win32.cpp | 0 2 files changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 util.hpp mode change 100755 => 100644 util_win32.cpp diff --git a/util.hpp b/util.hpp old mode 100755 new mode 100644 diff --git a/util_win32.cpp b/util_win32.cpp old mode 100755 new mode 100644