2005-04-11 01:10:52 +02:00
|
|
|
|
/* symcryptrun.c - Tool to call simple symmetric encryption tools.
|
2007-05-19 00:58:59 +02:00
|
|
|
|
* Copyright (C) 2005, 2007 Free Software Foundation, Inc.
|
2005-04-11 01:10:52 +02:00
|
|
|
|
*
|
|
|
|
|
* This file is part of GnuPG.
|
|
|
|
|
*
|
|
|
|
|
* GnuPG is free software; you can redistribute it and/or modify
|
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
2007-07-04 21:49:40 +02:00
|
|
|
|
* the Free Software Foundation; either version 3 of the License, or
|
2005-04-11 01:10:52 +02:00
|
|
|
|
* (at your option) any later version.
|
|
|
|
|
*
|
|
|
|
|
* GnuPG 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
|
2016-11-05 12:02:19 +01:00
|
|
|
|
* along with this program; if not, see <https://www.gnu.org/licenses/>.
|
2005-04-11 01:10:52 +02:00
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Sometimes simple encryption tools are already in use for a long
|
|
|
|
|
time and there is a desire to integrate them into the GnuPG
|
|
|
|
|
framework. The protocols and encryption methods might be
|
|
|
|
|
non-standard or not even properly documented, so that a
|
|
|
|
|
full-fledged encryption tool with an interface like gpg is not
|
|
|
|
|
doable. This simple wrapper program provides a solution: It
|
|
|
|
|
operates by calling the encryption/decryption module and providing
|
|
|
|
|
the passphrase for a key (or even the key directly) using the
|
|
|
|
|
standard pinentry mechanism through gpg-agent. */
|
|
|
|
|
|
|
|
|
|
/* This program is invoked in the following way:
|
|
|
|
|
|
|
|
|
|
symcryptrun --class CLASS --program PROGRAM --keyfile KEYFILE \
|
|
|
|
|
[--decrypt | --encrypt]
|
|
|
|
|
|
|
|
|
|
For encryption, the plain text must be provided on STDIN, and the
|
|
|
|
|
ciphertext will be output to STDOUT. For decryption vice versa.
|
|
|
|
|
|
|
|
|
|
CLASS can currently only be "confucius".
|
|
|
|
|
|
|
|
|
|
PROGRAM must be the path to the crypto engine.
|
|
|
|
|
|
|
|
|
|
KEYFILE must contain the secret key, which may be protected by a
|
|
|
|
|
passphrase. The passphrase is retrieved via the pinentry program.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
The GPG Agent _must_ be running before starting symcryptrun.
|
|
|
|
|
|
|
|
|
|
The possible exit status codes:
|
|
|
|
|
|
|
|
|
|
0 Success
|
2015-11-16 12:41:46 +01:00
|
|
|
|
1 Some error occurred
|
2005-04-11 01:10:52 +02:00
|
|
|
|
2 No valid passphrase was provided
|
|
|
|
|
3 The operation was canceled by the user
|
|
|
|
|
|
|
|
|
|
Other classes may be added in the future. */
|
|
|
|
|
|
2005-07-04 06:58:04 +02:00
|
|
|
|
#define SYMC_BAD_PASSPHRASE 2
|
|
|
|
|
#define SYMC_CANCELED 3
|
|
|
|
|
|
2005-04-11 01:10:52 +02:00
|
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
|
|
|
|
|
#include <unistd.h>
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <errno.h>
|
|
|
|
|
#include <assert.h>
|
2006-11-05 16:08:58 +01:00
|
|
|
|
#include <signal.h>
|
2005-04-11 01:10:52 +02:00
|
|
|
|
#include <sys/stat.h>
|
|
|
|
|
#include <sys/types.h>
|
|
|
|
|
#include <sys/wait.h>
|
2017-03-07 02:29:37 +01:00
|
|
|
|
|
2006-11-05 16:08:58 +01:00
|
|
|
|
#ifdef HAVE_PTY_H
|
2005-04-11 01:10:52 +02:00
|
|
|
|
#include <pty.h>
|
2017-03-07 02:29:37 +01:00
|
|
|
|
#else
|
|
|
|
|
#ifdef HAVE_TERMIOS_H
|
|
|
|
|
#include <termios.h>
|
|
|
|
|
#endif
|
|
|
|
|
#ifdef HAVE_UTIL_H
|
|
|
|
|
#include <util.h>
|
|
|
|
|
#endif
|
|
|
|
|
#ifdef HAVE_LIBUTIL_H
|
|
|
|
|
#include <libutil.h>
|
2006-11-05 16:08:58 +01:00
|
|
|
|
#endif
|
2017-03-07 02:29:37 +01:00
|
|
|
|
#endif
|
|
|
|
|
|
2011-03-08 12:23:59 +01:00
|
|
|
|
#ifdef HAVE_UTMP_H
|
|
|
|
|
#include <utmp.h>
|
|
|
|
|
#endif
|
2005-04-11 01:10:52 +02:00
|
|
|
|
#include <ctype.h>
|
|
|
|
|
#ifdef HAVE_LOCALE_H
|
|
|
|
|
#include <locale.h>
|
|
|
|
|
#endif
|
|
|
|
|
#ifdef HAVE_LANGINFO_CODESET
|
|
|
|
|
#include <langinfo.h>
|
|
|
|
|
#endif
|
|
|
|
|
#include <gpg-error.h>
|
|
|
|
|
|
2017-03-07 12:32:09 +01:00
|
|
|
|
#include "../common/i18n.h"
|
2005-04-11 01:10:52 +02:00
|
|
|
|
#include "../common/util.h"
|
2012-02-06 20:50:47 +01:00
|
|
|
|
#include "../common/init.h"
|
2014-11-11 15:14:31 +01:00
|
|
|
|
#include "../common/sysutils.h"
|
2005-04-11 01:10:52 +02:00
|
|
|
|
|
|
|
|
|
/* FIXME: Bah. For spwq_secure_free. */
|
|
|
|
|
#define SIMPLE_PWQUERY_IMPLEMENTATION 1
|
|
|
|
|
#include "../common/simple-pwquery.h"
|
|
|
|
|
|
2005-07-04 06:58:04 +02:00
|
|
|
|
|
|
|
|
|
/* From simple-gettext.c. */
|
|
|
|
|
|
2012-06-05 19:29:22 +02:00
|
|
|
|
/* We assume to have 'unsigned long int' value with at least 32 bits. */
|
2005-07-04 06:58:04 +02:00
|
|
|
|
#define HASHWORDBITS 32
|
|
|
|
|
|
2012-06-05 19:29:22 +02:00
|
|
|
|
/* The so called 'hashpjw' function by P.J. Weinberger
|
2005-07-04 06:58:04 +02:00
|
|
|
|
[see Aho/Sethi/Ullman, COMPILERS: Principles, Techniques and Tools,
|
|
|
|
|
1986, 1987 Bell Telephone Laboratories, Inc.] */
|
|
|
|
|
|
|
|
|
|
static __inline__ ulong
|
|
|
|
|
hash_string( const char *str_param )
|
|
|
|
|
{
|
|
|
|
|
unsigned long int hval, g;
|
|
|
|
|
const char *str = str_param;
|
|
|
|
|
|
|
|
|
|
hval = 0;
|
|
|
|
|
while (*str != '\0')
|
|
|
|
|
{
|
|
|
|
|
hval <<= 4;
|
|
|
|
|
hval += (unsigned long int) *str++;
|
|
|
|
|
g = hval & ((unsigned long int) 0xf << (HASHWORDBITS - 4));
|
|
|
|
|
if (g != 0)
|
|
|
|
|
{
|
|
|
|
|
hval ^= g >> (HASHWORDBITS - 8);
|
|
|
|
|
hval ^= g;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return hval;
|
|
|
|
|
}
|
|
|
|
|
|
2005-04-11 01:10:52 +02:00
|
|
|
|
|
|
|
|
|
/* Constants to identify the commands and options. */
|
|
|
|
|
enum cmd_and_opt_values
|
|
|
|
|
{
|
|
|
|
|
aNull = 0,
|
|
|
|
|
oQuiet = 'q',
|
|
|
|
|
oVerbose = 'v',
|
|
|
|
|
|
|
|
|
|
oNoVerbose = 500,
|
2005-04-11 01:54:39 +02:00
|
|
|
|
oOptions,
|
|
|
|
|
oNoOptions,
|
2005-04-11 01:10:52 +02:00
|
|
|
|
oLogFile,
|
|
|
|
|
oHomedir,
|
|
|
|
|
oClass,
|
|
|
|
|
oProgram,
|
|
|
|
|
oKeyfile,
|
|
|
|
|
oDecrypt,
|
|
|
|
|
oEncrypt,
|
2005-04-21 11:33:07 +02:00
|
|
|
|
oInput
|
2005-04-11 01:10:52 +02:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* The list of commands and options. */
|
2020-07-17 08:17:43 +02:00
|
|
|
|
static gpgrt_opt_t opts[] = {
|
2005-04-11 01:10:52 +02:00
|
|
|
|
|
2020-07-17 08:17:43 +02:00
|
|
|
|
ARGPARSE_group(300, N_("@\nCommands:\n ")),
|
2011-02-04 12:57:53 +01:00
|
|
|
|
|
2020-07-17 08:17:43 +02:00
|
|
|
|
ARGPARSE_c(oDecrypt, "decrypt", N_("decryption modus")),
|
|
|
|
|
ARGPARSE_c(oEncrypt, "encrypt", N_("encryption modus")),
|
2011-02-04 12:57:53 +01:00
|
|
|
|
|
2020-07-17 08:17:43 +02:00
|
|
|
|
ARGPARSE_group(301, N_("@\nOptions:\n ")),
|
2005-04-11 01:10:52 +02:00
|
|
|
|
|
2020-07-17 08:17:43 +02:00
|
|
|
|
ARGPARSE_s_s(oClass, "class", N_("tool class (confucius)")),
|
|
|
|
|
ARGPARSE_s_s(oProgram, "program", N_("program filename")),
|
2005-04-11 01:10:52 +02:00
|
|
|
|
|
2020-07-17 08:17:43 +02:00
|
|
|
|
ARGPARSE_s_s(oKeyfile, "keyfile", N_("secret key file (required)")),
|
|
|
|
|
ARGPARSE_s_s(oInput, "inputfile", N_("input file name (default stdin)")),
|
|
|
|
|
ARGPARSE_s_n(oVerbose, "verbose", N_("verbose")),
|
|
|
|
|
ARGPARSE_s_n(oQuiet, "quiet", N_("quiet")),
|
|
|
|
|
ARGPARSE_s_s(oLogFile, "log-file", N_("use a log file for the server")),
|
|
|
|
|
ARGPARSE_conffile(oOptions, "options", N_("|FILE|read options from FILE")),
|
2005-04-11 01:10:52 +02:00
|
|
|
|
|
2020-07-17 08:17:43 +02:00
|
|
|
|
/* Hidden options. */
|
|
|
|
|
ARGPARSE_s_n(oNoVerbose, "no-verbose", "@"),
|
|
|
|
|
ARGPARSE_s_s(oHomedir, "homedir", "@"),
|
|
|
|
|
ARGPARSE_noconffile(oNoOptions, "no-options", "@"),
|
|
|
|
|
|
|
|
|
|
ARGPARSE_end ()
|
|
|
|
|
};
|
2005-04-11 01:10:52 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* We keep all global options in the structure OPT. */
|
|
|
|
|
struct
|
|
|
|
|
{
|
|
|
|
|
int verbose; /* Verbosity level. */
|
|
|
|
|
int quiet; /* Be extra quiet. */
|
|
|
|
|
const char *homedir; /* Configuration directory name */
|
|
|
|
|
|
|
|
|
|
char *class;
|
|
|
|
|
char *program;
|
|
|
|
|
char *keyfile;
|
2005-04-19 14:00:29 +02:00
|
|
|
|
char *input;
|
2005-04-11 01:10:52 +02:00
|
|
|
|
} opt;
|
|
|
|
|
|
|
|
|
|
|
2017-02-20 22:19:50 +01:00
|
|
|
|
/* Print usage information and provide strings for help. */
|
2005-04-11 01:10:52 +02:00
|
|
|
|
static const char *
|
|
|
|
|
my_strusage (int level)
|
|
|
|
|
{
|
|
|
|
|
const char *p;
|
|
|
|
|
|
|
|
|
|
switch (level)
|
|
|
|
|
{
|
2020-07-17 08:17:43 +02:00
|
|
|
|
case 9: p = "GPL-3.0-or-later"; break;
|
2013-11-18 14:09:47 +01:00
|
|
|
|
case 11: p = "symcryptrun (@GNUPG@)";
|
2005-04-11 01:10:52 +02:00
|
|
|
|
break;
|
|
|
|
|
case 13: p = VERSION; break;
|
2020-07-17 08:17:43 +02:00
|
|
|
|
case 14: p = GNUPG_DEF_COPYRIGHT_LINE; break;
|
2005-04-11 01:10:52 +02:00
|
|
|
|
case 17: p = PRINTABLE_OS_NAME; break;
|
2009-07-21 16:21:05 +02:00
|
|
|
|
case 19: p = _("Please report bugs to <@EMAIL@>.\n"); break;
|
|
|
|
|
|
2005-04-11 01:10:52 +02:00
|
|
|
|
case 1:
|
|
|
|
|
case 40: p = _("Usage: symcryptrun [options] (-h for help)");
|
|
|
|
|
break;
|
|
|
|
|
case 41:
|
|
|
|
|
p = _("Syntax: symcryptrun --class CLASS --program PROGRAM "
|
2005-04-21 12:07:41 +02:00
|
|
|
|
"--keyfile KEYFILE [options...] COMMAND [inputfile]\n"
|
2005-04-11 01:10:52 +02:00
|
|
|
|
"Call a simple symmetric encryption tool\n");
|
|
|
|
|
break;
|
|
|
|
|
case 31: p = "\nHome: "; break;
|
2016-06-07 10:59:46 +02:00
|
|
|
|
case 32: p = gnupg_homedir (); break;
|
2005-04-11 01:10:52 +02:00
|
|
|
|
case 33: p = "\n"; break;
|
|
|
|
|
|
|
|
|
|
default: p = NULL; break;
|
|
|
|
|
}
|
|
|
|
|
return p;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2005-04-15 04:24:44 +02:00
|
|
|
|
|
2005-04-15 11:04:43 +02:00
|
|
|
|
/* This is in the GNU C library in unistd.h. */
|
|
|
|
|
|
|
|
|
|
#ifndef TEMP_FAILURE_RETRY
|
2012-06-05 19:29:22 +02:00
|
|
|
|
/* Evaluate EXPRESSION, and repeat as long as it returns -1 with 'errno'
|
2005-04-15 11:04:43 +02:00
|
|
|
|
set to EINTR. */
|
|
|
|
|
|
|
|
|
|
# define TEMP_FAILURE_RETRY(expression) \
|
|
|
|
|
(__extension__ \
|
|
|
|
|
({ long int __result; \
|
|
|
|
|
do __result = (long int) (expression); \
|
|
|
|
|
while (__result == -1L && errno == EINTR); \
|
|
|
|
|
__result; }))
|
|
|
|
|
#endif
|
|
|
|
|
|
2005-04-15 04:24:44 +02:00
|
|
|
|
/* Unlink a file, and shred it if SHRED is true. */
|
|
|
|
|
int
|
|
|
|
|
remove_file (char *name, int shred)
|
|
|
|
|
{
|
|
|
|
|
if (!shred)
|
|
|
|
|
return unlink (name);
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
int status;
|
|
|
|
|
pid_t pid;
|
|
|
|
|
|
|
|
|
|
pid = fork ();
|
|
|
|
|
if (pid == 0)
|
|
|
|
|
{
|
|
|
|
|
/* Child. */
|
2011-02-04 12:57:53 +01:00
|
|
|
|
|
2005-04-15 04:24:44 +02:00
|
|
|
|
/* -f forces file to be writable, and -u unlinks it afterwards. */
|
|
|
|
|
char *args[] = { SHRED, "-uf", name, NULL };
|
2011-02-04 12:57:53 +01:00
|
|
|
|
|
2005-04-15 04:24:44 +02:00
|
|
|
|
execv (SHRED, args);
|
|
|
|
|
_exit (127);
|
|
|
|
|
}
|
|
|
|
|
else if (pid < 0)
|
|
|
|
|
{
|
|
|
|
|
/* Fork failed. */
|
|
|
|
|
status = -1;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/* Parent. */
|
2011-02-04 12:57:53 +01:00
|
|
|
|
|
2005-04-15 04:24:44 +02:00
|
|
|
|
if (TEMP_FAILURE_RETRY (waitpid (pid, &status, 0)) != pid)
|
|
|
|
|
status = -1;
|
|
|
|
|
}
|
2011-02-04 12:57:53 +01:00
|
|
|
|
|
2005-04-15 04:24:44 +02:00
|
|
|
|
if (!WIFEXITED (status))
|
|
|
|
|
{
|
|
|
|
|
log_error (_("%s on %s aborted with status %i\n"),
|
|
|
|
|
SHRED, name, status);
|
|
|
|
|
unlink (name);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
else if (WEXITSTATUS (status))
|
|
|
|
|
{
|
|
|
|
|
log_error (_("%s on %s failed with status %i\n"), SHRED, name,
|
|
|
|
|
WEXITSTATUS (status));
|
|
|
|
|
unlink (name);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2005-04-11 01:10:52 +02:00
|
|
|
|
|
|
|
|
|
/* Class Confucius.
|
|
|
|
|
|
|
|
|
|
"Don't worry that other people don't know you;
|
|
|
|
|
worry that you don't know other people." Analects--1.16. */
|
|
|
|
|
|
|
|
|
|
/* Create temporary directory with mode 0700. Returns a dynamically
|
|
|
|
|
allocated string with the filename of the directory. */
|
|
|
|
|
static char *
|
|
|
|
|
confucius_mktmpdir (void)
|
|
|
|
|
{
|
2010-10-27 09:37:52 +02:00
|
|
|
|
char *name, *p;
|
2005-04-11 01:10:52 +02:00
|
|
|
|
|
2010-10-27 09:37:52 +02:00
|
|
|
|
p = getenv ("TMPDIR");
|
|
|
|
|
if (!p || !*p)
|
|
|
|
|
p = "/tmp";
|
|
|
|
|
if (p[strlen (p) - 1] == '/')
|
|
|
|
|
name = xstrconcat (p, "gpg-XXXXXX", NULL);
|
|
|
|
|
else
|
|
|
|
|
name = xstrconcat (p, "/", "gpg-XXXXXX", NULL);
|
2014-11-11 15:14:31 +01:00
|
|
|
|
if (!name || !gnupg_mkdtemp (name))
|
2005-04-11 01:10:52 +02:00
|
|
|
|
{
|
2012-06-05 19:29:22 +02:00
|
|
|
|
log_error (_("can't create temporary directory '%s': %s\n"),
|
2005-04-11 19:22:23 +02:00
|
|
|
|
name?name:"", strerror (errno));
|
2005-04-11 01:10:52 +02:00
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2005-04-11 19:22:23 +02:00
|
|
|
|
return name;
|
2005-04-11 01:10:52 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Buffer size for I/O operations. */
|
|
|
|
|
#define CONFUCIUS_BUFSIZE 4096
|
|
|
|
|
|
|
|
|
|
/* Buffer size for output lines. */
|
|
|
|
|
#define CONFUCIUS_LINESIZE 4096
|
|
|
|
|
|
|
|
|
|
|
2005-04-15 04:24:44 +02:00
|
|
|
|
/* Copy the file IN to OUT, either of which may be "-". If PLAIN is
|
|
|
|
|
true, and the copying fails, and OUT is not STDOUT, then shred the
|
|
|
|
|
file instead unlinking it. */
|
2005-04-11 01:10:52 +02:00
|
|
|
|
static int
|
2005-04-15 04:24:44 +02:00
|
|
|
|
confucius_copy_file (char *infile, char *outfile, int plain)
|
2005-04-11 01:10:52 +02:00
|
|
|
|
{
|
|
|
|
|
FILE *in;
|
|
|
|
|
int in_is_stdin = 0;
|
|
|
|
|
FILE *out;
|
|
|
|
|
int out_is_stdout = 0;
|
|
|
|
|
char data[CONFUCIUS_BUFSIZE];
|
|
|
|
|
ssize_t data_len;
|
|
|
|
|
|
|
|
|
|
if (infile[0] == '-' && infile[1] == '\0')
|
|
|
|
|
{
|
|
|
|
|
/* FIXME: Is stdin in binary mode? */
|
|
|
|
|
in = stdin;
|
|
|
|
|
in_is_stdin = 1;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
in = fopen (infile, "rb");
|
|
|
|
|
if (!in)
|
|
|
|
|
{
|
|
|
|
|
log_error (_("could not open %s for writing: %s\n"),
|
|
|
|
|
infile, strerror (errno));
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (outfile[0] == '-' && outfile[1] == '\0')
|
|
|
|
|
{
|
|
|
|
|
/* FIXME: Is stdout in binary mode? */
|
|
|
|
|
out = stdout;
|
|
|
|
|
out_is_stdout = 1;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
out = fopen (outfile, "wb");
|
|
|
|
|
if (!out)
|
|
|
|
|
{
|
|
|
|
|
log_error (_("could not open %s for writing: %s\n"),
|
|
|
|
|
infile, strerror (errno));
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Now copy the data. */
|
|
|
|
|
while ((data_len = fread (data, 1, sizeof (data), in)) > 0)
|
|
|
|
|
{
|
|
|
|
|
if (fwrite (data, 1, data_len, out) != data_len)
|
|
|
|
|
{
|
|
|
|
|
log_error (_("error writing to %s: %s\n"), outfile,
|
|
|
|
|
strerror (errno));
|
|
|
|
|
goto copy_err;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (data_len < 0 || ferror (in))
|
|
|
|
|
{
|
|
|
|
|
log_error (_("error reading from %s: %s\n"), infile, strerror (errno));
|
|
|
|
|
goto copy_err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Close IN if appropriate. */
|
|
|
|
|
if (!in_is_stdin && fclose (in) && ferror (in))
|
|
|
|
|
{
|
|
|
|
|
log_error (_("error closing %s: %s\n"), infile, strerror (errno));
|
|
|
|
|
goto copy_err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Close OUT if appropriate. */
|
|
|
|
|
if (!out_is_stdout && fclose (out) && ferror (out))
|
|
|
|
|
{
|
|
|
|
|
log_error (_("error closing %s: %s\n"), infile, strerror (errno));
|
|
|
|
|
goto copy_err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
copy_err:
|
|
|
|
|
if (!out_is_stdout)
|
2005-04-15 04:24:44 +02:00
|
|
|
|
remove_file (outfile, plain);
|
|
|
|
|
|
2005-04-11 01:10:52 +02:00
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Get a passphrase in secure storage (if possible). If AGAIN is
|
|
|
|
|
true, then this is a repeated attempt. If CANCELED is not a null
|
|
|
|
|
pointer, it will be set to true or false, depending on if the user
|
2017-04-28 03:06:33 +02:00
|
|
|
|
canceled the operation or not. On error (including cancellation), a
|
2005-04-11 01:10:52 +02:00
|
|
|
|
null pointer is returned. The passphrase must be deallocated with
|
2005-07-04 06:58:04 +02:00
|
|
|
|
confucius_drop_pass. CACHEID is the ID to be used for passphrase
|
|
|
|
|
caching and can be NULL to disable caching. */
|
2005-04-11 01:10:52 +02:00
|
|
|
|
char *
|
2005-07-04 06:58:04 +02:00
|
|
|
|
confucius_get_pass (const char *cacheid, int again, int *canceled)
|
2005-04-11 01:10:52 +02:00
|
|
|
|
{
|
|
|
|
|
int err;
|
|
|
|
|
char *pw;
|
2007-10-19 17:58:38 +02:00
|
|
|
|
char *orig_codeset;
|
2005-04-11 01:10:52 +02:00
|
|
|
|
|
|
|
|
|
if (canceled)
|
|
|
|
|
*canceled = 0;
|
2011-02-04 12:57:53 +01:00
|
|
|
|
|
2007-10-19 17:58:38 +02:00
|
|
|
|
orig_codeset = i18n_switchto_utf8 ();
|
2005-07-04 06:58:04 +02:00
|
|
|
|
pw = simple_pwquery (cacheid,
|
2005-04-11 01:10:52 +02:00
|
|
|
|
again ? _("does not match - try again"):NULL,
|
2007-01-25 09:30:47 +01:00
|
|
|
|
_("Passphrase:"), NULL, 0, &err);
|
2007-10-19 17:58:38 +02:00
|
|
|
|
i18n_switchback (orig_codeset);
|
2005-04-11 01:10:52 +02:00
|
|
|
|
|
|
|
|
|
if (!pw)
|
|
|
|
|
{
|
|
|
|
|
if (err)
|
|
|
|
|
log_error (_("error while asking for the passphrase: %s\n"),
|
|
|
|
|
gpg_strerror (err));
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
log_info (_("cancelled\n"));
|
|
|
|
|
if (canceled)
|
|
|
|
|
*canceled = 1;
|
2011-02-04 12:57:53 +01:00
|
|
|
|
}
|
2005-04-11 01:10:52 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return pw;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Drop a passphrase retrieved with confucius_get_pass. */
|
|
|
|
|
void
|
|
|
|
|
confucius_drop_pass (char *pass)
|
|
|
|
|
{
|
|
|
|
|
if (pass)
|
|
|
|
|
spwq_secure_free (pass);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Run a confucius crypto engine. If MODE is oEncrypt, encryption is
|
|
|
|
|
requested. If it is oDecrypt, decryption is requested. INFILE and
|
|
|
|
|
OUTFILE are the temporary files used in the process. */
|
|
|
|
|
int
|
2005-06-04 14:57:26 +02:00
|
|
|
|
confucius_process (int mode, char *infile, char *outfile,
|
|
|
|
|
int argc, char *argv[])
|
2005-04-11 01:10:52 +02:00
|
|
|
|
{
|
2005-06-04 14:57:26 +02:00
|
|
|
|
char **args;
|
2005-04-11 01:10:52 +02:00
|
|
|
|
int cstderr[2];
|
|
|
|
|
int master;
|
|
|
|
|
int slave;
|
|
|
|
|
int res;
|
|
|
|
|
pid_t pid;
|
|
|
|
|
pid_t wpid;
|
|
|
|
|
int tries = 0;
|
2005-07-04 06:58:04 +02:00
|
|
|
|
char cacheid[40];
|
2005-04-11 01:10:52 +02:00
|
|
|
|
|
|
|
|
|
signal (SIGPIPE, SIG_IGN);
|
|
|
|
|
|
|
|
|
|
if (!opt.program)
|
|
|
|
|
{
|
|
|
|
|
log_error (_("no --program option provided\n"));
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (mode != oDecrypt && mode != oEncrypt)
|
|
|
|
|
{
|
|
|
|
|
log_error (_("only --decrypt and --encrypt are supported\n"));
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!opt.keyfile)
|
|
|
|
|
{
|
|
|
|
|
log_error (_("no --keyfile option provided\n"));
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
2005-07-04 06:58:04 +02:00
|
|
|
|
/* Generate a hash from the keyfile name for caching. */
|
|
|
|
|
snprintf (cacheid, sizeof (cacheid), "confucius:%lu",
|
|
|
|
|
hash_string (opt.keyfile));
|
|
|
|
|
cacheid[sizeof (cacheid) - 1] = '\0';
|
2005-06-04 14:57:26 +02:00
|
|
|
|
args = malloc (sizeof (char *) * (10 + argc));
|
|
|
|
|
if (!args)
|
|
|
|
|
{
|
|
|
|
|
log_error (_("cannot allocate args vector\n"));
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
args[0] = opt.program;
|
|
|
|
|
args[1] = (mode == oEncrypt) ? "-m1" : "-m2";
|
|
|
|
|
args[2] = "-q";
|
|
|
|
|
args[3] = infile;
|
|
|
|
|
args[4] = "-z";
|
|
|
|
|
args[5] = outfile;
|
|
|
|
|
args[6] = "-s";
|
|
|
|
|
args[7] = opt.keyfile;
|
|
|
|
|
args[8] = (mode == oEncrypt) ? "-af" : "-f";
|
|
|
|
|
args[9 + argc] = NULL;
|
|
|
|
|
while (argc--)
|
|
|
|
|
args[9 + argc] = argv[argc];
|
|
|
|
|
|
2005-04-11 01:10:52 +02:00
|
|
|
|
if (pipe (cstderr) < 0)
|
|
|
|
|
{
|
|
|
|
|
log_error (_("could not create pipe: %s\n"), strerror (errno));
|
2005-06-04 14:57:26 +02:00
|
|
|
|
free (args);
|
2005-04-11 01:10:52 +02:00
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (openpty (&master, &slave, NULL, NULL, NULL) == -1)
|
|
|
|
|
{
|
|
|
|
|
log_error (_("could not create pty: %s\n"), strerror (errno));
|
|
|
|
|
close (cstderr[0]);
|
|
|
|
|
close (cstderr[1]);
|
2005-06-04 14:57:26 +02:00
|
|
|
|
free (args);
|
2005-04-11 01:10:52 +02:00
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* We don't want to deal with the worst case scenarios. */
|
|
|
|
|
assert (master > 2);
|
|
|
|
|
assert (slave > 2);
|
|
|
|
|
assert (cstderr[0] > 2);
|
|
|
|
|
assert (cstderr[1] > 2);
|
|
|
|
|
|
|
|
|
|
pid = fork ();
|
|
|
|
|
if (pid < 0)
|
|
|
|
|
{
|
|
|
|
|
log_error (_("could not fork: %s\n"), strerror (errno));
|
|
|
|
|
close (master);
|
|
|
|
|
close (slave);
|
|
|
|
|
close (cstderr[0]);
|
|
|
|
|
close (cstderr[1]);
|
2005-06-04 14:57:26 +02:00
|
|
|
|
free (args);
|
2005-04-11 01:10:52 +02:00
|
|
|
|
return 1;
|
|
|
|
|
}
|
2011-02-04 12:57:53 +01:00
|
|
|
|
else if (pid == 0)
|
2005-04-11 01:10:52 +02:00
|
|
|
|
{
|
|
|
|
|
/* Child. */
|
|
|
|
|
|
|
|
|
|
/* Close the parent ends. */
|
|
|
|
|
close (master);
|
|
|
|
|
close (cstderr[0]);
|
|
|
|
|
|
|
|
|
|
/* Change controlling terminal. */
|
|
|
|
|
if (login_tty (slave))
|
|
|
|
|
{
|
|
|
|
|
/* It's too early to output a debug message. */
|
|
|
|
|
_exit (1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dup2 (cstderr[1], 2);
|
|
|
|
|
close (cstderr[1]);
|
|
|
|
|
|
|
|
|
|
/* Now kick off the engine program. */
|
|
|
|
|
execv (opt.program, args);
|
|
|
|
|
log_error (_("execv failed: %s\n"), strerror (errno));
|
|
|
|
|
_exit (1);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/* Parent. */
|
|
|
|
|
char buffer[CONFUCIUS_LINESIZE];
|
|
|
|
|
int buffer_len = 0;
|
|
|
|
|
fd_set fds;
|
|
|
|
|
int slave_closed = 0;
|
|
|
|
|
int stderr_closed = 0;
|
|
|
|
|
|
|
|
|
|
close (slave);
|
|
|
|
|
close (cstderr[1]);
|
2005-06-04 14:57:26 +02:00
|
|
|
|
free (args);
|
2005-04-11 01:10:52 +02:00
|
|
|
|
|
|
|
|
|
/* Listen on the output FDs. */
|
|
|
|
|
do
|
|
|
|
|
{
|
|
|
|
|
FD_ZERO (&fds);
|
|
|
|
|
|
|
|
|
|
if (!slave_closed)
|
|
|
|
|
FD_SET (master, &fds);
|
|
|
|
|
if (!stderr_closed)
|
|
|
|
|
FD_SET (cstderr[0], &fds);
|
|
|
|
|
|
|
|
|
|
res = select (FD_SETSIZE, &fds, NULL, NULL, NULL);
|
|
|
|
|
if (res < 0)
|
|
|
|
|
{
|
|
|
|
|
log_error (_("select failed: %s\n"), strerror (errno));
|
|
|
|
|
|
|
|
|
|
kill (pid, SIGTERM);
|
|
|
|
|
close (master);
|
|
|
|
|
close (cstderr[0]);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (FD_ISSET (cstderr[0], &fds))
|
|
|
|
|
{
|
|
|
|
|
/* We got some output on stderr. This is just passed
|
|
|
|
|
through via the logging facility. */
|
|
|
|
|
|
|
|
|
|
res = read (cstderr[0], &buffer[buffer_len],
|
|
|
|
|
sizeof (buffer) - buffer_len - 1);
|
|
|
|
|
if (res < 0)
|
|
|
|
|
{
|
|
|
|
|
log_error (_("read failed: %s\n"), strerror (errno));
|
|
|
|
|
|
|
|
|
|
kill (pid, SIGTERM);
|
|
|
|
|
close (master);
|
|
|
|
|
close (cstderr[0]);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
2011-02-04 12:57:53 +01:00
|
|
|
|
else
|
2005-04-11 01:10:52 +02:00
|
|
|
|
{
|
|
|
|
|
char *newline;
|
|
|
|
|
|
|
|
|
|
buffer_len += res;
|
|
|
|
|
for (;;)
|
|
|
|
|
{
|
|
|
|
|
buffer[buffer_len] = '\0';
|
|
|
|
|
newline = strchr (buffer, '\n');
|
|
|
|
|
if (newline)
|
|
|
|
|
{
|
|
|
|
|
*newline = '\0';
|
|
|
|
|
log_error ("%s\n", buffer);
|
|
|
|
|
buffer_len -= newline + 1 - buffer;
|
|
|
|
|
memmove (buffer, newline + 1, buffer_len);
|
|
|
|
|
}
|
|
|
|
|
else if (buffer_len == sizeof (buffer) - 1)
|
|
|
|
|
{
|
|
|
|
|
/* Overflow. */
|
|
|
|
|
log_error ("%s\n", buffer);
|
|
|
|
|
buffer_len = 0;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (res == 0)
|
|
|
|
|
stderr_closed = 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (FD_ISSET (master, &fds))
|
|
|
|
|
{
|
|
|
|
|
char data[512];
|
|
|
|
|
|
|
|
|
|
res = read (master, data, sizeof (data));
|
|
|
|
|
if (res < 0)
|
|
|
|
|
{
|
|
|
|
|
if (errno == EIO)
|
|
|
|
|
{
|
|
|
|
|
/* Slave-side close leads to readable fd and
|
|
|
|
|
EIO. */
|
|
|
|
|
slave_closed = 1;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
log_error (_("pty read failed: %s\n"), strerror (errno));
|
|
|
|
|
|
|
|
|
|
kill (pid, SIGTERM);
|
|
|
|
|
close (master);
|
|
|
|
|
close (cstderr[0]);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (res == 0)
|
|
|
|
|
/* This never seems to be what happens on slave-side
|
|
|
|
|
close. */
|
|
|
|
|
slave_closed = 1;
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/* Check for password prompt. */
|
|
|
|
|
if (data[res - 1] == ':')
|
|
|
|
|
{
|
|
|
|
|
char *pass;
|
|
|
|
|
int canceled;
|
|
|
|
|
|
2005-07-04 06:58:04 +02:00
|
|
|
|
/* If this is not the first attempt, the
|
|
|
|
|
passphrase seems to be wrong, so clear the
|
|
|
|
|
cache. */
|
|
|
|
|
if (tries)
|
|
|
|
|
simple_pwclear (cacheid);
|
|
|
|
|
|
|
|
|
|
pass = confucius_get_pass (cacheid,
|
|
|
|
|
tries ? 1 : 0, &canceled);
|
2005-04-11 01:10:52 +02:00
|
|
|
|
if (!pass)
|
|
|
|
|
{
|
|
|
|
|
kill (pid, SIGTERM);
|
|
|
|
|
close (master);
|
|
|
|
|
close (cstderr[0]);
|
2005-07-04 06:58:04 +02:00
|
|
|
|
return canceled ? SYMC_CANCELED : 1;
|
2005-04-11 01:10:52 +02:00
|
|
|
|
}
|
|
|
|
|
write (master, pass, strlen (pass));
|
|
|
|
|
write (master, "\n", 1);
|
|
|
|
|
confucius_drop_pass (pass);
|
|
|
|
|
|
|
|
|
|
tries++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
while (!stderr_closed || !slave_closed);
|
|
|
|
|
|
|
|
|
|
close (master);
|
|
|
|
|
close (cstderr[0]);
|
|
|
|
|
|
|
|
|
|
wpid = waitpid (pid, &res, 0);
|
|
|
|
|
if (wpid < 0)
|
|
|
|
|
{
|
|
|
|
|
log_error (_("waitpid failed: %s\n"), strerror (errno));
|
|
|
|
|
|
|
|
|
|
kill (pid, SIGTERM);
|
2005-07-04 06:58:04 +02:00
|
|
|
|
/* State of cached password is unclear. Just remove it. */
|
|
|
|
|
simple_pwclear (cacheid);
|
2005-04-11 01:10:52 +02:00
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/* Shouldn't happen, as we don't use WNOHANG. */
|
|
|
|
|
assert (wpid != 0);
|
|
|
|
|
|
|
|
|
|
if (!WIFEXITED (res))
|
|
|
|
|
{
|
|
|
|
|
log_error (_("child aborted with status %i\n"), res);
|
2005-07-04 06:58:04 +02:00
|
|
|
|
|
|
|
|
|
/* State of cached password is unclear. Just remove it. */
|
|
|
|
|
simple_pwclear (cacheid);
|
|
|
|
|
|
2005-04-11 01:10:52 +02:00
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (WEXITSTATUS (res))
|
|
|
|
|
{
|
2005-07-04 06:58:04 +02:00
|
|
|
|
/* The passphrase was wrong. Remove it from the cache. */
|
|
|
|
|
simple_pwclear (cacheid);
|
|
|
|
|
|
2005-04-11 01:10:52 +02:00
|
|
|
|
/* We probably exceeded our number of attempts at guessing
|
|
|
|
|
the password. */
|
|
|
|
|
if (tries >= 3)
|
2005-07-04 06:58:04 +02:00
|
|
|
|
return SYMC_BAD_PASSPHRASE;
|
2005-04-11 01:10:52 +02:00
|
|
|
|
else
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Not reached. */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Class confucius main program. If MODE is oEncrypt, encryption is
|
|
|
|
|
requested. If it is oDecrypt, decryption is requested. The other
|
|
|
|
|
parameters are taken from the global option data. */
|
|
|
|
|
int
|
2005-06-04 14:57:26 +02:00
|
|
|
|
confucius_main (int mode, int argc, char *argv[])
|
2005-04-11 01:10:52 +02:00
|
|
|
|
{
|
|
|
|
|
int res;
|
|
|
|
|
char *tmpdir;
|
|
|
|
|
char *infile;
|
2005-04-19 14:00:29 +02:00
|
|
|
|
int infile_from_stdin = 0;
|
2005-04-11 01:10:52 +02:00
|
|
|
|
char *outfile;
|
|
|
|
|
|
|
|
|
|
tmpdir = confucius_mktmpdir ();
|
|
|
|
|
if (!tmpdir)
|
|
|
|
|
return 1;
|
2005-04-19 14:00:29 +02:00
|
|
|
|
|
|
|
|
|
if (opt.input && !(opt.input[0] == '-' && opt.input[1] == '\0'))
|
|
|
|
|
infile = xstrdup (opt.input);
|
|
|
|
|
else
|
2005-04-11 01:10:52 +02:00
|
|
|
|
{
|
2005-04-19 14:00:29 +02:00
|
|
|
|
infile_from_stdin = 1;
|
|
|
|
|
|
|
|
|
|
/* TMPDIR + "/" + "in" + "\0". */
|
|
|
|
|
infile = malloc (strlen (tmpdir) + 1 + 2 + 1);
|
|
|
|
|
if (!infile)
|
|
|
|
|
{
|
|
|
|
|
log_error (_("cannot allocate infile string: %s\n"),
|
|
|
|
|
strerror (errno));
|
|
|
|
|
rmdir (tmpdir);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
strcpy (infile, tmpdir);
|
|
|
|
|
strcat (infile, "/in");
|
2005-04-11 01:10:52 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* TMPDIR + "/" + "out" + "\0". */
|
|
|
|
|
outfile = malloc (strlen (tmpdir) + 1 + 3 + 1);
|
|
|
|
|
if (!outfile)
|
|
|
|
|
{
|
|
|
|
|
log_error (_("cannot allocate outfile string: %s\n"), strerror (errno));
|
|
|
|
|
free (infile);
|
|
|
|
|
rmdir (tmpdir);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
strcpy (outfile, tmpdir);
|
|
|
|
|
strcat (outfile, "/out");
|
|
|
|
|
|
2005-04-19 14:00:29 +02:00
|
|
|
|
if (infile_from_stdin)
|
2005-04-11 01:10:52 +02:00
|
|
|
|
{
|
2005-04-19 14:00:29 +02:00
|
|
|
|
/* Create INFILE and fill it with content. */
|
|
|
|
|
res = confucius_copy_file ("-", infile, mode == oEncrypt);
|
|
|
|
|
if (res)
|
|
|
|
|
{
|
|
|
|
|
free (outfile);
|
|
|
|
|
free (infile);
|
|
|
|
|
rmdir (tmpdir);
|
|
|
|
|
return res;
|
|
|
|
|
}
|
2005-04-11 01:10:52 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Run the engine and thus create the output file, handling
|
|
|
|
|
passphrase retrieval. */
|
2005-06-04 14:57:26 +02:00
|
|
|
|
res = confucius_process (mode, infile, outfile, argc, argv);
|
2005-04-11 01:10:52 +02:00
|
|
|
|
if (res)
|
|
|
|
|
{
|
2005-04-15 04:24:44 +02:00
|
|
|
|
remove_file (outfile, mode == oDecrypt);
|
2005-04-19 14:00:29 +02:00
|
|
|
|
if (infile_from_stdin)
|
|
|
|
|
remove_file (infile, mode == oEncrypt);
|
2005-04-11 01:10:52 +02:00
|
|
|
|
free (outfile);
|
|
|
|
|
free (infile);
|
|
|
|
|
rmdir (tmpdir);
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Dump the output file to stdout. */
|
2005-04-15 04:24:44 +02:00
|
|
|
|
res = confucius_copy_file (outfile, "-", mode == oDecrypt);
|
2005-04-11 01:10:52 +02:00
|
|
|
|
if (res)
|
|
|
|
|
{
|
2005-04-15 04:24:44 +02:00
|
|
|
|
remove_file (outfile, mode == oDecrypt);
|
2005-04-19 14:00:29 +02:00
|
|
|
|
if (infile_from_stdin)
|
|
|
|
|
remove_file (infile, mode == oEncrypt);
|
2005-04-11 01:10:52 +02:00
|
|
|
|
free (outfile);
|
|
|
|
|
free (infile);
|
|
|
|
|
rmdir (tmpdir);
|
|
|
|
|
return res;
|
|
|
|
|
}
|
2011-02-04 12:57:53 +01:00
|
|
|
|
|
2005-04-15 04:24:44 +02:00
|
|
|
|
remove_file (outfile, mode == oDecrypt);
|
2005-04-19 14:00:29 +02:00
|
|
|
|
if (infile_from_stdin)
|
|
|
|
|
remove_file (infile, mode == oEncrypt);
|
2005-04-11 01:10:52 +02:00
|
|
|
|
free (outfile);
|
|
|
|
|
free (infile);
|
|
|
|
|
rmdir (tmpdir);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* symcryptrun's entry point. */
|
|
|
|
|
int
|
|
|
|
|
main (int argc, char **argv)
|
|
|
|
|
{
|
2020-07-17 08:17:43 +02:00
|
|
|
|
gpgrt_argparse_t pargs;
|
2005-04-11 01:54:39 +02:00
|
|
|
|
int orig_argc;
|
|
|
|
|
char **orig_argv;
|
2020-07-17 08:17:43 +02:00
|
|
|
|
char *last_configname = NULL;
|
|
|
|
|
const char *configname = NULL;
|
2005-04-11 01:10:52 +02:00
|
|
|
|
int mode = 0;
|
|
|
|
|
int res;
|
|
|
|
|
char *logfile = NULL;
|
|
|
|
|
|
2015-01-28 19:57:22 +01:00
|
|
|
|
early_system_init ();
|
2020-07-17 08:17:43 +02:00
|
|
|
|
gpgrt_set_strusage (my_strusage);
|
Call log_set_prefix() with human-readable labels.
* agent/preset-passphrase.c, agent/protect-tool.c, dirmngr/dirmngr.c
* dirmngr/t-http.c, g10/gpg.c, g10/gpgv.c, g13/g13-syshelp.c
* g13/g13.c, kbx/kbxutil.c, scd/scdaemon.c, sm/gpgsm.c
* tests/gpgscm/main.c, tools/gpg-check-pattern.c
* tools/gpg-connect-agent.c, tools/gpgconf.c, tools/gpgtar.c
* tools/symcryptrun.c: Invoke log_set_prefix() with
human-readable labels.
--
Some invocations of log_set_prefix() were done with raw numeric values
instead of values that humans can understand. Use symbolic
representations instead of numeric for better readability.
Signed-off-by: Daniel Kahn Gillmor <dkg@fifthhorseman.net>
2016-08-12 07:37:57 +02:00
|
|
|
|
log_set_prefix ("symcryptrun", GPGRT_LOG_WITH_PREFIX);
|
2005-04-11 01:10:52 +02:00
|
|
|
|
|
2007-06-14 19:05:07 +02:00
|
|
|
|
/* Make sure that our subsystems are ready. */
|
2005-04-11 01:10:52 +02:00
|
|
|
|
i18n_init();
|
2010-03-22 13:46:05 +01:00
|
|
|
|
init_common_subsystems (&argc, &argv);
|
2005-04-11 01:10:52 +02:00
|
|
|
|
|
2005-04-11 01:54:39 +02:00
|
|
|
|
/* Check whether we have a config file given on the commandline */
|
|
|
|
|
orig_argc = argc;
|
|
|
|
|
orig_argv = argv;
|
|
|
|
|
pargs.argc = &argc;
|
|
|
|
|
pargs.argv = &argv;
|
2020-07-17 08:17:43 +02:00
|
|
|
|
pargs.flags= ARGPARSE_FLAG_KEEP|ARGPARSE_FLAG_NOVERSION;
|
|
|
|
|
while (gpgrt_argparse (NULL, &pargs, opts))
|
2005-04-11 01:54:39 +02:00
|
|
|
|
{
|
2020-07-17 08:17:43 +02:00
|
|
|
|
if (pargs.r_opt == oHomedir)
|
2016-06-07 10:59:46 +02:00
|
|
|
|
gnupg_set_homedir (pargs.r.ret_str);
|
2005-04-11 01:54:39 +02:00
|
|
|
|
}
|
2020-07-17 08:17:43 +02:00
|
|
|
|
/* Reset the flags. */
|
|
|
|
|
pargs.flags &= ~(ARGPARSE_FLAG_KEEP | ARGPARSE_FLAG_NOVERSION);
|
2005-04-11 01:54:39 +02:00
|
|
|
|
|
2020-07-17 08:17:43 +02:00
|
|
|
|
/* The configuraton directories for use by gpgrt_argparser. */
|
|
|
|
|
gpgrt_set_confdir (GPGRT_CONFDIR_SYS, gnupg_sysconfdir ());
|
|
|
|
|
gpgrt_set_confdir (GPGRT_CONFDIR_USER, gnupg_homedir ());
|
2011-02-04 12:57:53 +01:00
|
|
|
|
|
2005-04-11 01:54:39 +02:00
|
|
|
|
argc = orig_argc;
|
|
|
|
|
argv = orig_argv;
|
|
|
|
|
pargs.argc = &argc;
|
|
|
|
|
pargs.argv = &argv;
|
2020-07-17 08:17:43 +02:00
|
|
|
|
/* We are re-using the struct, thus the reset flag. We OR the
|
|
|
|
|
* flags so that the internal intialized flag won't be cleared. */
|
|
|
|
|
pargs.flags |= (ARGPARSE_FLAG_RESET
|
|
|
|
|
| ARGPARSE_FLAG_KEEP
|
|
|
|
|
| ARGPARSE_FLAG_SYS
|
|
|
|
|
| ARGPARSE_FLAG_USER);
|
2005-04-11 01:54:39 +02:00
|
|
|
|
|
2005-04-11 01:10:52 +02:00
|
|
|
|
/* Parse the command line. */
|
2020-07-17 08:17:43 +02:00
|
|
|
|
while (gpgrt_argparser (&pargs, opts, "symcryptrun.conf"))
|
2005-04-11 01:10:52 +02:00
|
|
|
|
{
|
|
|
|
|
switch (pargs.r_opt)
|
|
|
|
|
{
|
2020-07-17 08:17:43 +02:00
|
|
|
|
case ARGPARSE_CONFFILE:
|
|
|
|
|
{
|
|
|
|
|
if (pargs.r_type)
|
|
|
|
|
{
|
|
|
|
|
xfree (last_configname);
|
|
|
|
|
last_configname = xstrdup (pargs.r.ret_str);
|
|
|
|
|
configname = last_configname;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
configname = NULL;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
2005-04-11 01:10:52 +02:00
|
|
|
|
case oDecrypt: mode = oDecrypt; break;
|
|
|
|
|
case oEncrypt: mode = oEncrypt; break;
|
|
|
|
|
|
|
|
|
|
case oQuiet: opt.quiet = 1; break;
|
|
|
|
|
case oVerbose: opt.verbose++; break;
|
|
|
|
|
case oNoVerbose: opt.verbose = 0; break;
|
2011-02-04 12:57:53 +01:00
|
|
|
|
|
2005-04-11 01:10:52 +02:00
|
|
|
|
case oClass: opt.class = pargs.r.ret_str; break;
|
|
|
|
|
case oProgram: opt.program = pargs.r.ret_str; break;
|
|
|
|
|
case oKeyfile: opt.keyfile = pargs.r.ret_str; break;
|
2005-04-19 14:00:29 +02:00
|
|
|
|
case oInput: opt.input = pargs.r.ret_str; break;
|
2005-04-11 01:10:52 +02:00
|
|
|
|
|
|
|
|
|
case oLogFile: logfile = pargs.r.ret_str; break;
|
|
|
|
|
|
2005-04-11 01:54:39 +02:00
|
|
|
|
case oHomedir: /* Ignore this option here. */; break;
|
|
|
|
|
|
2020-07-17 08:17:43 +02:00
|
|
|
|
default:
|
|
|
|
|
if (configname)
|
|
|
|
|
pargs.err = ARGPARSE_PRINT_WARNING;
|
|
|
|
|
else
|
|
|
|
|
pargs.err = ARGPARSE_PRINT_ERROR;
|
|
|
|
|
break;
|
2005-04-11 01:10:52 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
2020-07-17 08:17:43 +02:00
|
|
|
|
gpgrt_argparse (NULL, &pargs, NULL); /* Release internal state. */
|
|
|
|
|
|
|
|
|
|
xfree (last_configname);
|
2005-04-11 01:10:52 +02:00
|
|
|
|
|
|
|
|
|
if (!mode)
|
|
|
|
|
log_error (_("either %s or %s must be given\n"),
|
|
|
|
|
"--decrypt", "--encrypt");
|
|
|
|
|
|
|
|
|
|
if (log_get_errorcount (0))
|
|
|
|
|
exit (1);
|
|
|
|
|
|
|
|
|
|
if (logfile)
|
|
|
|
|
log_set_file (logfile);
|
|
|
|
|
|
|
|
|
|
gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN);
|
2007-04-20 18:59:37 +02:00
|
|
|
|
setup_libgcrypt_logging ();
|
2005-04-11 01:10:52 +02:00
|
|
|
|
gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0);
|
|
|
|
|
|
2017-02-20 22:19:50 +01:00
|
|
|
|
/* Tell simple-pwquery about the standard socket name. */
|
2007-06-14 19:05:07 +02:00
|
|
|
|
{
|
2016-06-16 11:23:59 +02:00
|
|
|
|
char *tmp = make_filename (gnupg_socketdir (), GPG_AGENT_SOCK_NAME, NULL);
|
2007-06-14 19:05:07 +02:00
|
|
|
|
simple_pw_set_socket (tmp);
|
|
|
|
|
xfree (tmp);
|
|
|
|
|
}
|
|
|
|
|
|
2005-04-11 01:10:52 +02:00
|
|
|
|
if (!opt.class)
|
|
|
|
|
{
|
|
|
|
|
log_error (_("no class provided\n"));
|
|
|
|
|
res = 1;
|
|
|
|
|
}
|
|
|
|
|
else if (!strcmp (opt.class, "confucius"))
|
2007-06-14 19:05:07 +02:00
|
|
|
|
{
|
|
|
|
|
res = confucius_main (mode, argc, argv);
|
|
|
|
|
}
|
2005-04-11 01:10:52 +02:00
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
log_error (_("class %s is not supported\n"), opt.class);
|
|
|
|
|
res = 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return res;
|
|
|
|
|
}
|