mirror of
git://git.gnupg.org/gnupg.git
synced 2025-01-03 12:11:33 +01:00
Started to code a --server mode.
It is far from being ready!
This commit is contained in:
parent
0ed45ac1b3
commit
12ca74c836
@ -1,3 +1,19 @@
|
||||
2006-12-21 Werner Koch <wk@g10code.com>
|
||||
|
||||
* gpg.c (main): New command --server.
|
||||
* gpg.h (struct server_control_s, ctrl_t): New.
|
||||
* server.c: New.
|
||||
* verify.c (gpg_verify): New.
|
||||
* mainproc.c (mainproc_context): Made SIGNED_DATA a structure.
|
||||
(proc_signature_packets_by_fd): New.
|
||||
(proc_compressed_cb): Divert depending on SIGNED_DATA.
|
||||
* plaintext.c (hash_datafile_by_fd): New.
|
||||
* mainproc.c (proc_tree): Use it here.
|
||||
|
||||
* verify.c (verify_signatures): Init AFX only when needed.
|
||||
Don't leak a context on error.
|
||||
(verify_one_file): Don't leak a context on error.
|
||||
|
||||
2006-12-07 Werner Koch <wk@g10code.com>
|
||||
|
||||
* openfile.c (copy_options_file): Use log_info instead of
|
||||
|
@ -72,6 +72,7 @@ common_source = \
|
||||
pkglue.c pkglue.h
|
||||
|
||||
gpg2_SOURCES = gpg.c \
|
||||
server.c \
|
||||
$(common_source) \
|
||||
pkclist.c \
|
||||
skclist.c \
|
||||
|
38
g10/gpg.c
38
g10/gpg.c
@ -149,6 +149,7 @@ enum cmd_and_opt_values
|
||||
aCardStatus,
|
||||
aCardEdit,
|
||||
aChangePIN,
|
||||
aServer,
|
||||
|
||||
oTextmode,
|
||||
oNoTextmode,
|
||||
@ -424,7 +425,8 @@ static ARGPARSE_OPTS opts[] = {
|
||||
{ aEnArmor, "enarmour", 256, "@"},
|
||||
{ aPrintMD, "print-md" , 256, N_("|algo [files]|print message digests")},
|
||||
{ aPrimegen, "gen-prime" , 256, "@" },
|
||||
{ aGenRandom, "gen-random" , 256, "@" },
|
||||
{ aGenRandom, "gen-random", 256, "@" },
|
||||
{ aServer, "server", 256, N_("run in server mode")},
|
||||
|
||||
{ 301, NULL, 0, N_("@\nOptions:\n ") },
|
||||
|
||||
@ -1740,6 +1742,25 @@ encode_s2k_iterations(int iterations)
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/* This fucntion called to initialized a new control object. It is
|
||||
assumed that this object has been zeroed out before calling this
|
||||
function. */
|
||||
static void
|
||||
gpg_init_default_ctrl (ctrl_t ctrl)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/* This function is called to deinitialize a control object. It is
|
||||
not deallocated. */
|
||||
static void
|
||||
gpg_deinit_default_ctrl (ctrl_t ctrl)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
main (int argc, char **argv )
|
||||
{
|
||||
@ -2094,6 +2115,10 @@ main (int argc, char **argv )
|
||||
case aVerifyFiles: multifile=1; /* fall through */
|
||||
case aVerify: set_cmd( &cmd, aVerify); break;
|
||||
|
||||
case aServer:
|
||||
set_cmd (&cmd, pargs.r_opt);
|
||||
opt.batch = 1;
|
||||
break;
|
||||
|
||||
case oArmor: opt.armor = 1; opt.no_armor=0; break;
|
||||
case oOutput: opt.outfile = pargs.r.ret_str; break;
|
||||
@ -3254,6 +3279,16 @@ main (int argc, char **argv )
|
||||
|
||||
switch( cmd )
|
||||
{
|
||||
case aServer:
|
||||
{
|
||||
ctrl_t ctrl = xtrycalloc (1, sizeof *ctrl);
|
||||
gpg_init_default_ctrl (ctrl);
|
||||
gpg_server (ctrl);
|
||||
gpg_deinit_default_ctrl (ctrl);
|
||||
xfree (ctrl);
|
||||
}
|
||||
break;
|
||||
|
||||
case aStore: /* only store the file */
|
||||
if( argc > 1 )
|
||||
wrong_args(_("--store [filename]"));
|
||||
@ -4169,3 +4204,4 @@ add_keyserver_url( const char *string, int which )
|
||||
if(critical)
|
||||
sl->flags |= 1;
|
||||
}
|
||||
|
||||
|
35
g10/gpg.h
35
g10/gpg.h
@ -43,12 +43,44 @@
|
||||
#define MAX_FINGERPRINT_LEN 20
|
||||
|
||||
|
||||
/* Forward declarations. */
|
||||
/*
|
||||
Forward declarations.
|
||||
*/
|
||||
|
||||
/* Object used to keep state locally to server.c . */
|
||||
struct server_local_s;
|
||||
|
||||
/* Object used to describe a keyblok node. */
|
||||
typedef struct kbnode_struct *KBNODE;
|
||||
/* Object used for looking ob keys. */
|
||||
typedef struct keydb_search_desc KEYDB_SEARCH_DESC;
|
||||
|
||||
|
||||
|
||||
/* Session control object. This object is passed to most functions to
|
||||
convey the status of a session. Note that the defaults are set by
|
||||
gpg_init_default_ctrl(). */
|
||||
struct server_control_s
|
||||
{
|
||||
struct server_local_s *server_local;
|
||||
};
|
||||
typedef struct server_control_s *ctrl_t;
|
||||
|
||||
|
||||
|
||||
|
||||
/*-- server.c --*/
|
||||
int gpg_server (ctrl_t);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Compatibility stuff to be faded out over time.
|
||||
*/
|
||||
|
||||
/* Simple wrappers. */
|
||||
#define g10_errstr(a) gpg_strerror ((a))
|
||||
|
||||
@ -98,5 +130,4 @@ typedef struct keydb_search_desc KEYDB_SEARCH_DESC;
|
||||
#define G10ERR_WRONG_SECKEY GPG_ERR_WRONG_SECKEY
|
||||
|
||||
|
||||
|
||||
#endif /*GNUPG_G10_GPG_H*/
|
||||
|
@ -278,6 +278,7 @@ void print_card_key_info (FILE *fp, KBNODE keyblock);
|
||||
void print_file_status( int status, const char *name, int what );
|
||||
int verify_signatures( int nfiles, char **files );
|
||||
int verify_files( int nfiles, char **files );
|
||||
int gpg_verify (ctrl_t ctrl, int sig_fd, int data_fd, FILE *out_fp);
|
||||
|
||||
/*-- decrypt.c --*/
|
||||
int decrypt_message( const char *filename );
|
||||
@ -286,6 +287,8 @@ void decrypt_messages(int nfiles, char *files[]);
|
||||
/*-- plaintext.c --*/
|
||||
int hash_datafiles( gcry_md_hd_t md, gcry_md_hd_t md2,
|
||||
strlist_t files, const char *sigfilename, int textmode );
|
||||
int hash_datafile_by_fd ( gcry_md_hd_t md, gcry_md_hd_t md2, int data_fd,
|
||||
int textmode );
|
||||
PKT_plaintext *setup_plaintext_name(const char *filename,IOBUF iobuf);
|
||||
|
||||
/*-- signal.c --*/
|
||||
|
115
g10/mainproc.c
115
g10/mainproc.c
@ -65,8 +65,26 @@ struct mainproc_context
|
||||
md_filter_context_t mfx;
|
||||
int sigs_only; /* Process only signatures and reject all other stuff. */
|
||||
int encrypt_only; /* Process only encryption messages. */
|
||||
strlist_t signed_data;
|
||||
|
||||
/* Name of the file with the complete signature or the file with the
|
||||
detached signature. This is currently only used to deduce the
|
||||
file name of the data file if that has not been given. */
|
||||
const char *sigfilename;
|
||||
|
||||
/* A structure to describe the signed data in case of a detached
|
||||
signature. */
|
||||
struct
|
||||
{
|
||||
/* A file descriptor of the the signed data. Only used if not -1. */
|
||||
int data_fd;
|
||||
/* A list of filenames with the data files or NULL. This is only
|
||||
used if DATA_FD is -1. */
|
||||
strlist_t data_names;
|
||||
/* Flag to indicated that either one of the next previous fieldss
|
||||
is used. This is only needed for better readability. */
|
||||
int used;
|
||||
} signed_data;
|
||||
|
||||
DEK *dek;
|
||||
int last_was_session_key;
|
||||
KBNODE list; /* The current list of packets. */
|
||||
@ -692,8 +710,14 @@ proc_plaintext( CTX c, PACKET *pkt )
|
||||
static int
|
||||
proc_compressed_cb( IOBUF a, void *info )
|
||||
{
|
||||
return proc_signature_packets( info, a, ((CTX)info)->signed_data,
|
||||
((CTX)info)->sigfilename );
|
||||
if ( ((CTX)info)->signed_data.used
|
||||
&& ((CTX)info)->signed_data.data_fd != -1)
|
||||
return proc_signature_packets_by_fd (info, a,
|
||||
((CTX)info)->signed_data.data_fd);
|
||||
else
|
||||
return proc_signature_packets (info, a,
|
||||
((CTX)info)->signed_data.data_names,
|
||||
((CTX)info)->sigfilename );
|
||||
}
|
||||
|
||||
static int
|
||||
@ -1124,7 +1148,11 @@ proc_signature_packets( void *anchor, IOBUF a,
|
||||
|
||||
c->anchor = anchor;
|
||||
c->sigs_only = 1;
|
||||
c->signed_data = signedfiles;
|
||||
|
||||
c->signed_data.data_fd = -1;
|
||||
c->signed_data.data_names = signedfiles;
|
||||
c->signed_data.used = !!signedfiles;
|
||||
|
||||
c->sigfilename = sigfilename;
|
||||
rc = do_proc_packets( c, a );
|
||||
|
||||
@ -1150,6 +1178,43 @@ proc_signature_packets( void *anchor, IOBUF a,
|
||||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
proc_signature_packets_by_fd (void *anchor, IOBUF a, int signed_data_fd )
|
||||
{
|
||||
int rc;
|
||||
CTX c = xcalloc (1, sizeof *c);
|
||||
|
||||
c->anchor = anchor;
|
||||
c->sigs_only = 1;
|
||||
|
||||
c->signed_data.data_fd = signed_data_fd;
|
||||
c->signed_data.data_names = NULL;
|
||||
c->signed_data.used = (signed_data_fd != -1);
|
||||
|
||||
rc = do_proc_packets ( c, a );
|
||||
|
||||
/* If we have not encountered any signature we print an error
|
||||
messages, send a NODATA status back and return an error code.
|
||||
Using log_error is required because verify_files does not check
|
||||
error codes for each file but we want to terminate the process
|
||||
with an error. */
|
||||
if (!rc && !c->any_sig_seen)
|
||||
{
|
||||
write_status_text (STATUS_NODATA, "4");
|
||||
log_error (_("no signature found\n"));
|
||||
rc = gpg_error (GPG_ERR_NO_DATA);
|
||||
}
|
||||
|
||||
/* Propagate the signature seen flag upward. Do this only on success
|
||||
so that we won't issue the nodata status several times. */
|
||||
if (!rc && c->anchor && c->any_sig_seen)
|
||||
c->anchor->any_sig_seen = 1;
|
||||
|
||||
xfree ( c );
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
proc_encryption_packets( void *anchor, IOBUF a )
|
||||
{
|
||||
@ -1899,6 +1964,8 @@ proc_tree( CTX c, KBNODE node )
|
||||
else if( node->pkt->pkttype == PKT_ONEPASS_SIG ) {
|
||||
/* check all signatures */
|
||||
if( !c->have_data ) {
|
||||
int use_textmode = 0;
|
||||
|
||||
free_md_filter_context( &c->mfx );
|
||||
/* prepare to create all requested message digests */
|
||||
if (gcry_md_open (&c->mfx.md, 0, 0))
|
||||
@ -1911,23 +1978,33 @@ proc_tree( CTX c, KBNODE node )
|
||||
gcry_md_enable (c->mfx.md,
|
||||
n1->pkt->pkt.signature->digest_algo);
|
||||
}
|
||||
/* ask for file and hash it */
|
||||
|
||||
if (n1 && n1->pkt->pkt.onepass_sig->sig_class == 0x01)
|
||||
use_textmode = 1;
|
||||
|
||||
/* Ask for file and hash it. */
|
||||
if( c->sigs_only ) {
|
||||
rc = hash_datafiles( c->mfx.md, NULL,
|
||||
c->signed_data, c->sigfilename,
|
||||
n1? (n1->pkt->pkt.onepass_sig->sig_class == 0x01):0 );
|
||||
if (c->signed_data.used && c->signed_data.data_fd != -1)
|
||||
rc = hash_datafile_by_fd (c->mfx.md, NULL,
|
||||
c->signed_data.data_fd,
|
||||
use_textmode);
|
||||
else
|
||||
rc = hash_datafiles (c->mfx.md, NULL,
|
||||
c->signed_data.data_names,
|
||||
c->sigfilename,
|
||||
use_textmode );
|
||||
}
|
||||
else {
|
||||
rc = ask_for_detached_datafile( c->mfx.md, c->mfx.md2,
|
||||
rc = ask_for_detached_datafile (c->mfx.md, c->mfx.md2,
|
||||
iobuf_get_real_fname(c->iobuf),
|
||||
n1? (n1->pkt->pkt.onepass_sig->sig_class == 0x01):0 );
|
||||
use_textmode );
|
||||
}
|
||||
if( rc ) {
|
||||
log_error("can't hash datafile: %s\n", g10_errstr(rc));
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if ( c->signed_data ) {
|
||||
else if ( c->signed_data.used ) {
|
||||
log_error (_("not a detached signature\n") );
|
||||
return;
|
||||
}
|
||||
@ -1943,7 +2020,7 @@ proc_tree( CTX c, KBNODE node )
|
||||
log_error("cleartext signature without data\n" );
|
||||
return;
|
||||
}
|
||||
else if ( c->signed_data ) {
|
||||
else if ( c->signed_data.used ) {
|
||||
log_error (_("not a detached signature\n") );
|
||||
return;
|
||||
}
|
||||
@ -2019,9 +2096,15 @@ proc_tree( CTX c, KBNODE node )
|
||||
gcry_md_start_debug( c->mfx.md2, "verify2" );
|
||||
}
|
||||
if( c->sigs_only ) {
|
||||
rc = hash_datafiles( c->mfx.md, c->mfx.md2,
|
||||
c->signed_data, c->sigfilename,
|
||||
(sig->sig_class == 0x01) );
|
||||
if (c->signed_data.used && c->signed_data.data_fd != -1)
|
||||
rc = hash_datafile_by_fd (c->mfx.md, c->mfx.md2,
|
||||
c->signed_data.data_fd,
|
||||
(sig->sig_class == 0x01));
|
||||
else
|
||||
rc = hash_datafiles (c->mfx.md, c->mfx.md2,
|
||||
c->signed_data.data_names,
|
||||
c->sigfilename,
|
||||
(sig->sig_class == 0x01));
|
||||
}
|
||||
else {
|
||||
rc = ask_for_detached_datafile( c->mfx.md, c->mfx.md2,
|
||||
@ -2033,7 +2116,7 @@ proc_tree( CTX c, KBNODE node )
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if ( c->signed_data ) {
|
||||
else if ( c->signed_data.used ) {
|
||||
log_error (_("not a detached signature\n") );
|
||||
return;
|
||||
}
|
||||
|
@ -266,6 +266,11 @@ struct {
|
||||
#define DBG_EXTPROG_VALUE 1024 /* debug external program calls */
|
||||
#define DBG_CARD_IO_VALUE 2048 /* debug smart card I/O. */
|
||||
|
||||
/* Fixme: For now alias this value. */
|
||||
#define DBG_ASSUAN_VALUE DBG_EXTPROG_VALUE
|
||||
|
||||
|
||||
/* Tests for the debugging flags. */
|
||||
#define DBG_PACKET (opt.debug & DBG_PACKET_VALUE)
|
||||
#define DBG_CIPHER (opt.debug & DBG_CIPHER_VALUE)
|
||||
#define DBG_FILTER (opt.debug & DBG_FILTER_VALUE)
|
||||
@ -274,6 +279,7 @@ struct {
|
||||
#define DBG_HASHING (opt.debug & DBG_HASHING_VALUE)
|
||||
#define DBG_EXTPROG (opt.debug & DBG_EXTPROG_VALUE)
|
||||
#define DBG_CARD_IO (opt.debug & DBG_CARD_IO_VALUE)
|
||||
#define DBG_ASSUAN (opt.debug & DBG_ASSUAN_VALUE)
|
||||
|
||||
/* FIXME: We need to check whey we did not put this into opt. */
|
||||
#define DBG_MEMORY memory_debug_mode
|
||||
|
@ -371,6 +371,7 @@ struct notation
|
||||
int proc_packets( void *ctx, iobuf_t a );
|
||||
int proc_signature_packets( void *ctx, iobuf_t a,
|
||||
strlist_t signedfiles, const char *sigfile );
|
||||
int proc_signature_packets_by_fd ( void *anchor, IOBUF a, int signed_data_fd );
|
||||
int proc_encryption_packets( void *ctx, iobuf_t a );
|
||||
int list_packets( iobuf_t a );
|
||||
|
||||
|
@ -567,6 +567,42 @@ hash_datafiles( gcry_md_hd_t md, gcry_md_hd_t md2, strlist_t files,
|
||||
}
|
||||
|
||||
|
||||
/* Hash the data from file descriptor DATA_FD and append the hash to hash
|
||||
contexts MD and MD2. */
|
||||
int
|
||||
hash_datafile_by_fd ( gcry_md_hd_t md, gcry_md_hd_t md2, int data_fd,
|
||||
int textmode )
|
||||
{
|
||||
progress_filter_context_t *pfx = new_progress_context ();
|
||||
iobuf_t fp;
|
||||
|
||||
fp = iobuf_fdopen (data_fd, "rb");
|
||||
if (fp && is_secured_file (data_fd))
|
||||
{
|
||||
iobuf_close (fp);
|
||||
fp = NULL;
|
||||
errno = EPERM;
|
||||
}
|
||||
if ( !fp )
|
||||
{
|
||||
int rc = gpg_error_from_syserror ();
|
||||
log_error ( _("can't open signed data fd=%d: %s\n"),
|
||||
data_fd, strerror (errno));
|
||||
release_progress_context (pfx);
|
||||
return rc;
|
||||
}
|
||||
|
||||
handle_progress (pfx, fp, NULL);
|
||||
|
||||
do_hash ( md, md2, fp, textmode);
|
||||
|
||||
iobuf_close(fp);
|
||||
|
||||
release_progress_context (pfx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Set up a plaintext packet with the appropriate filename. If there
|
||||
is a --set-filename, use it (it's already UTF8). If there is a
|
||||
regular filename, UTF8-ize it if necessary. If there is no
|
||||
|
526
g10/server.c
Normal file
526
g10/server.c
Normal file
@ -0,0 +1,526 @@
|
||||
/* server.c - server mode for gpg
|
||||
* Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
*
|
||||
* 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
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (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
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <ctype.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <assuan.h>
|
||||
|
||||
#include "gpg.h"
|
||||
#include "util.h"
|
||||
#include "i18n.h"
|
||||
#include "options.h"
|
||||
|
||||
|
||||
|
||||
#define set_error(e,t) assuan_set_error (ctx, gpg_error (e), (t))
|
||||
|
||||
|
||||
/* Data used to associate an Assuan context with local server data. */
|
||||
struct server_local_s
|
||||
{
|
||||
/* Our current Assuan context. */
|
||||
assuan_context_t assuan_ctx;
|
||||
/* File descriptor as set by the MESSAGE command. */
|
||||
int message_fd;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* Helper to close the message fd if it is open. */
|
||||
static void
|
||||
close_message_fd (ctrl_t ctrl)
|
||||
{
|
||||
if (ctrl->server_local->message_fd != -1)
|
||||
{
|
||||
close (ctrl->server_local->message_fd);
|
||||
ctrl->server_local->message_fd = -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Called by libassuan for Assuan options. See the Assuan manual for
|
||||
details. */
|
||||
static int
|
||||
option_handler (assuan_context_t ctx, const char *key, const char *value)
|
||||
{
|
||||
/* ctrl_t ctrl = assuan_get_pointer (ctx); */
|
||||
|
||||
/* Fixme: Implement the tty and locale args. */
|
||||
if (!strcmp (key, "display"))
|
||||
{
|
||||
}
|
||||
else if (!strcmp (key, "ttyname"))
|
||||
{
|
||||
}
|
||||
else if (!strcmp (key, "ttytype"))
|
||||
{
|
||||
}
|
||||
else if (!strcmp (key, "lc-ctype"))
|
||||
{
|
||||
}
|
||||
else if (!strcmp (key, "lc-messages"))
|
||||
{
|
||||
}
|
||||
else if (!strcmp (key, "list-mode"))
|
||||
{
|
||||
/* This is for now a dummy option. */
|
||||
}
|
||||
else
|
||||
return gpg_error (GPG_ERR_UNKNOWN_OPTION);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Called by libassuan for RESET commands. */
|
||||
static void
|
||||
reset_notify (assuan_context_t ctx)
|
||||
{
|
||||
ctrl_t ctrl = assuan_get_pointer (ctx);
|
||||
|
||||
close_message_fd (ctrl);
|
||||
assuan_close_input_fd (ctx);
|
||||
assuan_close_output_fd (ctx);
|
||||
}
|
||||
|
||||
|
||||
/* Called by libassuan for INPUT commands. */
|
||||
static void
|
||||
input_notify (assuan_context_t ctx, const char *line)
|
||||
{
|
||||
/* ctrl_t ctrl = assuan_get_pointer (ctx); */
|
||||
|
||||
if (strstr (line, "--armor"))
|
||||
; /* FIXME */
|
||||
else if (strstr (line, "--base64"))
|
||||
; /* FIXME */
|
||||
else if (strstr (line, "--binary"))
|
||||
;
|
||||
else
|
||||
; /* FIXME (autodetect encoding) */
|
||||
}
|
||||
|
||||
|
||||
/* Called by libassuan for OUTPUT commands. */
|
||||
static void
|
||||
output_notify (assuan_context_t ctx, const char *line)
|
||||
{
|
||||
/* ctrl_t ctrl = assuan_get_pointer (ctx); */
|
||||
|
||||
if (strstr (line, "--armor"))
|
||||
; /* FIXME */
|
||||
else if (strstr (line, "--base64"))
|
||||
; /* FIXME */
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* RECIPIENT <userID>
|
||||
|
||||
Set the recipient for the encryption. <userID> should be the
|
||||
internal representation of the key; the server may accept any other
|
||||
way of specification. If this is a valid and trusted recipient the
|
||||
server does respond with OK, otherwise the return is an ERR with
|
||||
the reason why the recipient can't be used, the encryption will
|
||||
then not be done for this recipient. If the policy is not to
|
||||
encrypt at all if not all recipients are valid, the client has to
|
||||
take care of this. All RECIPIENT commands are cumulative until a
|
||||
RESET or an successful ENCRYPT command. */
|
||||
static int
|
||||
cmd_recipient (assuan_context_t ctx, char *line)
|
||||
{
|
||||
return gpg_error (GPG_ERR_NOT_SUPPORTED);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* SIGNER <userID>
|
||||
|
||||
Set the signer's keys for the signature creation. <userID> should
|
||||
be the internal representation of the key; the server may accept
|
||||
any other way of specification. If this is a valid and usable
|
||||
signing key the server does respond with OK, otherwise it returns
|
||||
an ERR with the reason why the key can't be used, the signing will
|
||||
then not be done for this key. If the policy is not to sign at all
|
||||
if not all signer keys are valid, the client has to take care of
|
||||
this. All SIGNER commands are cumulative until a RESET but they
|
||||
are *not* reset by an SIGN command becuase it can be expected that
|
||||
set of signers are used for more than one sign operation.
|
||||
|
||||
Note that this command returns an INV_RECP status which is a bit
|
||||
strange, but they are very similar. */
|
||||
static int
|
||||
cmd_signer (assuan_context_t ctx, char *line)
|
||||
{
|
||||
return gpg_error (GPG_ERR_NOT_SUPPORTED);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* ENCRYPT
|
||||
|
||||
Do the actual encryption process. Takes the plaintext from the
|
||||
INPUT command, writes to the ciphertext to the file descriptor set
|
||||
with the OUTPUT command, take the recipients form all the
|
||||
recipients set so far. If this command fails the clients should
|
||||
try to delete all output currently done or otherwise mark it as
|
||||
invalid. GPG does ensure that there won't be any security problem
|
||||
with leftover data on the output in this case.
|
||||
|
||||
This command should in general not fail, as all necessary checks
|
||||
have been done while setting the recipients. The input and output
|
||||
pipes are closed. */
|
||||
static int
|
||||
cmd_encrypt (assuan_context_t ctx, char *line)
|
||||
{
|
||||
return gpg_error (GPG_ERR_NOT_SUPPORTED);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* DECRYPT
|
||||
|
||||
This performs the decrypt operation after doing some checks on the
|
||||
internal state (e.g. that only needed data has been set). */
|
||||
static int
|
||||
cmd_decrypt (assuan_context_t ctx, char *line)
|
||||
{
|
||||
return gpg_error (GPG_ERR_NOT_SUPPORTED);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* VERIFY
|
||||
|
||||
This does a verify operation on the message send to the input-FD.
|
||||
The result is written out using status lines. If an output FD was
|
||||
given, the signed text will be written to that.
|
||||
|
||||
If the signature is a detached one, the server will inquire about
|
||||
the signed material and the client must provide it.
|
||||
*/
|
||||
static int
|
||||
cmd_verify (assuan_context_t ctx, char *line)
|
||||
{
|
||||
int rc;
|
||||
ctrl_t ctrl = assuan_get_pointer (ctx);
|
||||
int fd = assuan_get_input_fd (ctx);
|
||||
int out_fd = assuan_get_output_fd (ctx);
|
||||
FILE *out_fp = NULL;
|
||||
|
||||
if (fd == -1)
|
||||
return gpg_error (GPG_ERR_ASS_NO_INPUT);
|
||||
|
||||
if (out_fd != -1)
|
||||
{
|
||||
out_fp = fdopen ( dup(out_fd), "w");
|
||||
if (!out_fp)
|
||||
return set_error (GPG_ERR_ASS_GENERAL, "fdopen() failed");
|
||||
}
|
||||
|
||||
log_debug ("WARNING: The server mode work in progress and not ready for use\n");
|
||||
|
||||
/* Need to dup it because it might get closed and libassuan won't
|
||||
know about it then. */
|
||||
rc = gpg_verify (ctrl,
|
||||
dup (fd),
|
||||
dup (ctrl->server_local->message_fd),
|
||||
out_fp);
|
||||
|
||||
if (out_fp)
|
||||
fclose (out_fp);
|
||||
close_message_fd (ctrl);
|
||||
assuan_close_input_fd (ctx);
|
||||
assuan_close_output_fd (ctx);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* SIGN [--detached]
|
||||
|
||||
Sign the data set with the INPUT command and write it to the sink
|
||||
set by OUTPUT. With "--detached" specified, a detached signature
|
||||
is created. */
|
||||
static int
|
||||
cmd_sign (assuan_context_t ctx, char *line)
|
||||
{
|
||||
return gpg_error (GPG_ERR_NOT_SUPPORTED);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* IMPORT
|
||||
|
||||
Import keys as read from the input-fd, return status message for
|
||||
each imported one. The import checks the validity of the key. */
|
||||
static int
|
||||
cmd_import (assuan_context_t ctx, char *line)
|
||||
{
|
||||
return gpg_error (GPG_ERR_NOT_SUPPORTED);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* EXPORT [--data [--armor|--base64]] [--] pattern
|
||||
|
||||
Similar to the --export command line command, this command exports
|
||||
public keys matching PATTERN. The output is send to the output fd
|
||||
unless the --data option has been used in which case the output
|
||||
gets send inline using regular data lines. The options "--armor"
|
||||
and "--base" ospecify an output format if "--data" has been used.
|
||||
Recall that in general the output format is set with the OUTPUT
|
||||
command.
|
||||
*/
|
||||
static int
|
||||
cmd_export (assuan_context_t ctx, char *line)
|
||||
{
|
||||
return gpg_error (GPG_ERR_NOT_SUPPORTED);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* DELKEYS
|
||||
|
||||
Fixme
|
||||
*/
|
||||
static int
|
||||
cmd_delkeys (assuan_context_t ctx, char *line)
|
||||
{
|
||||
return gpg_error (GPG_ERR_NOT_SUPPORTED);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* MESSAGE FD[=<n>]
|
||||
|
||||
Set the file descriptor to read a message which is used with
|
||||
detached signatures. */
|
||||
static int
|
||||
cmd_message (assuan_context_t ctx, char *line)
|
||||
{
|
||||
int rc;
|
||||
int fd;
|
||||
ctrl_t ctrl = assuan_get_pointer (ctx);
|
||||
|
||||
rc = assuan_command_parse_fd (ctx, line, &fd);
|
||||
if (rc)
|
||||
return rc;
|
||||
if (fd == -1)
|
||||
return gpg_error (GPG_ERR_ASS_NO_INPUT);
|
||||
ctrl->server_local->message_fd = fd;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* LISTKEYS [<patterns>]
|
||||
LISTSECRETKEYS [<patterns>]
|
||||
|
||||
fixme
|
||||
*/
|
||||
static int
|
||||
do_listkeys (assuan_context_t ctx, char *line, int mode)
|
||||
{
|
||||
return gpg_error (GPG_ERR_NOT_SUPPORTED);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
cmd_listkeys (assuan_context_t ctx, char *line)
|
||||
{
|
||||
return do_listkeys (ctx, line, 3);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
cmd_listsecretkeys (assuan_context_t ctx, char *line)
|
||||
{
|
||||
return do_listkeys (ctx, line, 2);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* GENKEY
|
||||
|
||||
Read the parameters in native format from the input fd and create a
|
||||
new OpenPGP key.
|
||||
*/
|
||||
static int
|
||||
cmd_genkey (assuan_context_t ctx, char *line)
|
||||
{
|
||||
return gpg_error (GPG_ERR_NOT_SUPPORTED);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* Helper to register our commands with libassuan. */
|
||||
static int
|
||||
register_commands (assuan_context_t ctx)
|
||||
{
|
||||
static struct
|
||||
{
|
||||
const char *name;
|
||||
int (*handler)(assuan_context_t, char *line);
|
||||
} table[] = {
|
||||
{ "RECIPIENT", cmd_recipient },
|
||||
{ "SIGNER", cmd_signer },
|
||||
{ "ENCRYPT", cmd_encrypt },
|
||||
{ "DECRYPT", cmd_decrypt },
|
||||
{ "VERIFY", cmd_verify },
|
||||
{ "SIGN", cmd_sign },
|
||||
{ "IMPORT", cmd_import },
|
||||
{ "EXPORT", cmd_export },
|
||||
{ "INPUT", NULL },
|
||||
{ "OUTPUT", NULL },
|
||||
{ "MESSAGE", cmd_message },
|
||||
{ "LISTKEYS", cmd_listkeys },
|
||||
{ "LISTSECRETKEYS",cmd_listsecretkeys },
|
||||
{ "GENKEY", cmd_genkey },
|
||||
{ "DELKEYS", cmd_delkeys },
|
||||
{ NULL }
|
||||
};
|
||||
int i, rc;
|
||||
|
||||
for (i=0; table[i].name; i++)
|
||||
{
|
||||
rc = assuan_register_command (ctx, table[i].name, table[i].handler);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* Startup the server. CTRL must have been allocated by the caller
|
||||
and set to the default values. */
|
||||
int
|
||||
gpg_server (ctrl_t ctrl)
|
||||
{
|
||||
int rc;
|
||||
int filedes[2];
|
||||
assuan_context_t ctx;
|
||||
static const char hello[] = ("GNU Privacy Guard's OpenPGP server "
|
||||
VERSION " ready");
|
||||
|
||||
/* We use a pipe based server so that we can work from scripts.
|
||||
assuan_init_pipe_server will automagically detect when we are
|
||||
called with a socketpair and ignore FILEDES in this case. */
|
||||
filedes[0] = 0;
|
||||
filedes[1] = 1;
|
||||
rc = assuan_init_pipe_server (&ctx, filedes);
|
||||
if (rc)
|
||||
{
|
||||
log_error ("failed to initialize the server: %s\n", gpg_strerror (rc));
|
||||
goto leave;
|
||||
}
|
||||
|
||||
rc = register_commands (ctx);
|
||||
if (rc)
|
||||
{
|
||||
log_error ("failed to the register commands with Assuan: %s\n",
|
||||
gpg_strerror(rc));
|
||||
goto leave;
|
||||
}
|
||||
|
||||
assuan_set_pointer (ctx, ctrl);
|
||||
if (opt.verbose || opt.debug)
|
||||
{
|
||||
char *tmp = NULL;
|
||||
const char *s1 = getenv ("GPG_AGENT_INFO");
|
||||
|
||||
if (asprintf (&tmp,
|
||||
"Home: %s\n"
|
||||
"Config: %s\n"
|
||||
"AgentInfo: %s\n"
|
||||
"%s",
|
||||
opt.homedir,
|
||||
"fixme: need config filename",
|
||||
s1?s1:"[not set]",
|
||||
hello) > 0)
|
||||
{
|
||||
assuan_set_hello_line (ctx, tmp);
|
||||
free (tmp);
|
||||
}
|
||||
}
|
||||
else
|
||||
assuan_set_hello_line (ctx, hello);
|
||||
assuan_register_reset_notify (ctx, reset_notify);
|
||||
assuan_register_input_notify (ctx, input_notify);
|
||||
assuan_register_output_notify (ctx, output_notify);
|
||||
assuan_register_option_handler (ctx, option_handler);
|
||||
|
||||
ctrl->server_local = xtrycalloc (1, sizeof *ctrl->server_local);
|
||||
if (!ctrl->server_local)
|
||||
{
|
||||
rc = gpg_error_from_syserror ();
|
||||
goto leave;
|
||||
}
|
||||
ctrl->server_local->assuan_ctx = ctx;
|
||||
ctrl->server_local->message_fd = -1;
|
||||
|
||||
if (DBG_ASSUAN)
|
||||
assuan_set_log_stream (ctx, log_get_stream ());
|
||||
|
||||
for (;;)
|
||||
{
|
||||
rc = assuan_accept (ctx);
|
||||
if (rc == -1)
|
||||
{
|
||||
rc = 0;
|
||||
break;
|
||||
}
|
||||
else if (rc)
|
||||
{
|
||||
log_info ("Assuan accept problem: %s\n", gpg_strerror (rc));
|
||||
break;
|
||||
}
|
||||
|
||||
rc = assuan_process (ctx);
|
||||
if (rc)
|
||||
{
|
||||
log_info ("Assuan processing failed: %s\n", gpg_strerror (rc));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
leave:
|
||||
xfree (ctrl->server_local);
|
||||
ctrl->server_local = NULL;
|
||||
assuan_deinit_server (ctx);
|
||||
return rc;
|
||||
}
|
||||
|
83
g10/verify.c
83
g10/verify.c
@ -55,15 +55,13 @@ int
|
||||
verify_signatures( int nfiles, char **files )
|
||||
{
|
||||
IOBUF fp;
|
||||
armor_filter_context_t *afx;
|
||||
progress_filter_context_t *pfx;
|
||||
armor_filter_context_t *afx = NULL;
|
||||
progress_filter_context_t *pfx = new_progress_context ();
|
||||
const char *sigfile;
|
||||
int i, rc;
|
||||
strlist_t sl;
|
||||
|
||||
pfx = new_progress_context ();
|
||||
afx = new_armor_context ();
|
||||
/* decide whether we should handle a detached or a normal signature,
|
||||
/* Decide whether we should handle a detached or a normal signature,
|
||||
* which is needed so that the code later can hash the correct data and
|
||||
* not have a normal signature act as detached signature and ignoring the
|
||||
* indended signed material from the 2nd file or stdin.
|
||||
@ -72,7 +70,7 @@ verify_signatures( int nfiles, char **files )
|
||||
* 3. gpg file <file2 - detached
|
||||
* 4. gpg file file2 - detached
|
||||
* The question is how decide between case 2 and 3? The only way
|
||||
* we can do it is by reading one byte from stdin and the unget
|
||||
* we can do it is by reading one byte from stdin and then unget
|
||||
* it; the problem here is that we may be reading from the
|
||||
* terminal (which could be detected using isatty() but won't work
|
||||
* when under contol of a pty using program (e.g. expect)) and
|
||||
@ -87,7 +85,6 @@ verify_signatures( int nfiles, char **files )
|
||||
* that all quite easily in mainproc.c
|
||||
*/
|
||||
|
||||
|
||||
sigfile = nfiles? *files : NULL;
|
||||
|
||||
/* open the signature file */
|
||||
@ -102,13 +99,15 @@ verify_signatures( int nfiles, char **files )
|
||||
rc = gpg_error_from_syserror ();
|
||||
log_error(_("can't open `%s': %s\n"),
|
||||
print_fname_stdin(sigfile), strerror (errno));
|
||||
release_progress_context (pfx);
|
||||
return rc;
|
||||
goto leave;
|
||||
}
|
||||
handle_progress (pfx, fp, sigfile);
|
||||
|
||||
if( !opt.no_armor && use_armor_filter( fp ) )
|
||||
if ( !opt.no_armor && use_armor_filter( fp ) )
|
||||
{
|
||||
afx = new_armor_context ();
|
||||
push_armor_filter (afx, fp);
|
||||
}
|
||||
|
||||
sl = NULL;
|
||||
for(i=nfiles-1 ; i > 0 ; i-- )
|
||||
@ -123,12 +122,14 @@ verify_signatures( int nfiles, char **files )
|
||||
rc = 0;
|
||||
}
|
||||
|
||||
leave:
|
||||
release_armor_context (afx);
|
||||
release_progress_context (pfx);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
print_file_status( int status, const char *name, int what )
|
||||
{
|
||||
@ -144,10 +145,9 @@ verify_one_file( const char *name )
|
||||
{
|
||||
IOBUF fp;
|
||||
armor_filter_context_t *afx = NULL;
|
||||
progress_filter_context_t *pfx;
|
||||
progress_filter_context_t *pfx = new_progress_context ();
|
||||
int rc;
|
||||
|
||||
pfx = new_progress_context ();
|
||||
print_file_status( STATUS_FILE_START, name, 1 );
|
||||
fp = iobuf_open(name);
|
||||
if (fp)
|
||||
@ -163,8 +163,7 @@ verify_one_file( const char *name )
|
||||
log_error(_("can't open `%s': %s\n"),
|
||||
print_fname_stdin(name), strerror (errno));
|
||||
print_file_status( STATUS_FILE_ERROR, name, 1 );
|
||||
release_progress_context (pfx);
|
||||
return rc;
|
||||
goto leave;
|
||||
}
|
||||
handle_progress (pfx, fp, name);
|
||||
|
||||
@ -178,6 +177,8 @@ verify_one_file( const char *name )
|
||||
rc = proc_signature_packets( NULL, fp, NULL, name );
|
||||
iobuf_close(fp);
|
||||
write_status( STATUS_FILE_DONE );
|
||||
|
||||
leave:
|
||||
release_armor_context (afx);
|
||||
release_progress_context (pfx);
|
||||
return rc;
|
||||
@ -217,3 +218,57 @@ verify_files( int nfiles, char **files )
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* Perform a verify operation. To verify detached signatures, DATA_FD
|
||||
shall be the descriptor of the signed data; for regular signatures
|
||||
it needs to be -1. If OUT_FP is not NULL and DATA_FD is not -1 the
|
||||
the signed material gets written that stream.
|
||||
|
||||
FIXME: OUTFP is not yet implemented.
|
||||
*/
|
||||
int
|
||||
gpg_verify (ctrl_t ctrl, int sig_fd, int data_fd, FILE *out_fp)
|
||||
{
|
||||
int rc;
|
||||
iobuf_t fp;
|
||||
armor_filter_context_t *afx = NULL;
|
||||
progress_filter_context_t *pfx = new_progress_context ();
|
||||
|
||||
fp = iobuf_fdopen (sig_fd, "rb");
|
||||
if (fp && is_secured_file (sig_fd))
|
||||
{
|
||||
fp = NULL;
|
||||
errno = EPERM;
|
||||
}
|
||||
if ( !fp )
|
||||
{
|
||||
rc = gpg_error_from_syserror ();
|
||||
log_error (_("can't open fd %d: %s\n"), sig_fd, strerror (errno));
|
||||
goto leave;
|
||||
}
|
||||
|
||||
handle_progress (pfx, fp, NULL);
|
||||
|
||||
if ( !opt.no_armor && use_armor_filter (fp) )
|
||||
{
|
||||
afx = new_armor_context ();
|
||||
push_armor_filter (afx, fp);
|
||||
}
|
||||
|
||||
rc = proc_signature_packets_by_fd ( NULL, fp, data_fd );
|
||||
|
||||
if ( afx && afx->no_openpgp_data
|
||||
&& (rc == -1 || gpg_err_code (rc) == GPG_ERR_EOF) )
|
||||
rc = gpg_error (GPG_ERR_NO_DATA);
|
||||
|
||||
leave:
|
||||
if (fp)
|
||||
iobuf_close (fp);
|
||||
release_progress_context (pfx);
|
||||
release_armor_context (afx);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user