Friedman is setting up his desk

This commit is contained in:
Werner Koch 2001-11-24 18:52:02 +00:00
parent f917085be5
commit 1e443ad637
5 changed files with 400 additions and 38 deletions

View File

@ -24,7 +24,9 @@ INCLUDES = -I$(top_srcdir)/common -I$(top_srcdir)/intl
LDFLAGS = @LDFLAGS@
gpg_agent_SOURCES = \
gpg-agent.c
gpg-agent.c agent.h \
command.c \
pksign.c
gpg_agent_LDADD = ../jnlib/libjnlib.a ../assuan/libassuan.a \
../../libgcrypt/src/.libs/libgcrypt.so.1

78
agent/agent.h Normal file
View File

@ -0,0 +1,78 @@
/* agent.h - Global definitions for the agent
* Copyright (C) 2001 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifndef AGENT_H
#define AGENT_H
#include "../common/util.h"
#include "../common/errors.h"
#define MAX_DIGEST_LEN 24
/* A large struct name "opt" to keep global flags */
struct {
unsigned int debug; /* debug flags (DBG_foo_VALUE) */
int verbose; /* verbosity level */
int quiet; /* be as quiet as possible */
int dry_run; /* don't change any persistent data */
const char *homedir; /* configuration directory name */
} opt;
#define DBG_COMMAND_VALUE 1 /* debug commands i/o */
#define DBG_MPI_VALUE 2 /* debug mpi details */
#define DBG_CRYPTO_VALUE 4 /* debug low level crypto */
#define DBG_MEMORY_VALUE 32 /* debug memory allocation stuff */
#define DBG_CACHE_VALUE 64 /* debug the caching */
#define DBG_MEMSTAT_VALUE 128 /* show memory statistics */
#define DBG_HASHING_VALUE 512 /* debug hashing operations */
#define DBG_COMMAND (opt.debug & DBG_COMMAND_VALUE)
#define DBG_CRYPTO (opt.debug & DBG_CRYPTO_VALUE)
#define DBG_MEMORY (opt.debug & DBG_MEMORY_VALUE)
#define DBG_CACHE (opt.debug & DBG_CACHE_VALUE)
#define DBG_HASHING (opt.debug & DBG_HASHING_VALUE)
struct server_local_s;
struct server_control_s {
struct server_local_s *server_local;
struct {
unsigned char value[MAX_DIGEST_LEN];
int valuelen;
} digest;
};
typedef struct server_control_s *CTRL;
/*-- gpg-agent.c --*/
void agent_exit (int rc);
/*-- command.c --*/
void start_command_handler (void);
/*-- pksign.c --*/
int agent_pksign (CTRL ctrl, FILE *outfp);
#endif /*AGENT_H*/

229
agent/command.c Normal file
View File

@ -0,0 +1,229 @@
/* command.c - gpg-agent command handler
* Copyright (C) 2001 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
/* FIXME: we should not use the default assuan buffering but setup
some buffering in secure mempory to protect session keys etc. */
#include <config.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include "agent.h"
#include "../assuan/assuan.h"
#define set_error(e,t) assuan_set_error (ctx, ASSUAN_ ## e, (t))
#define digitp(a) ((a) >= '0' && (a) <= '9')
#define hexdigitp(a) (digitp (a) \
|| ((a) >= 'A' && (a) <= 'F') \
|| ((a) >= 'a' && (a) <= 'f'))
#define atoi_1(p) (*(p) - '0' )
#define atoi_2(p) ((atoi_1(p) * 10) + atoi_1((p)+1))
/* assumes ASCII and pre-checked values */
#define xtoi_1(p) (*(p) <= '9'? (*(p)- '0'): \
*(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10))
#define xtoi_2(p) ((xtoi_1(p) * 16) + xtoi_1((p)+1))
/* Data used to associate an Assuan context with local server data */
struct server_local_s {
ASSUAN_CONTEXT assuan_ctx;
int message_fd;
};
/* SETHASH <hexstring>
The client can use this command to tell the server about the data
(which usually is a hash) to be signed. */
static int
cmd_sethash (ASSUAN_CONTEXT ctx, char *line)
{
int n;
char *p;
CTRL ctrl = assuan_get_pointer (ctx);
unsigned char *buf;
/* parse the hash value */
for (p=line,n=0; hexdigitp (*p); p++, n++)
;
if (*p)
return set_error (Parameter_Error, "invalid hexstring");
if ((n&1))
return set_error (Parameter_Error, "odd number of digits");
n /= 2;
if (n != 16 && n != 20 && n != 24 && n != 32)
return set_error (Parameter_Error, "unsupported length of hash");
if (n > MAX_DIGEST_LEN)
return set_error (Parameter_Error, "hash value to long");
buf = ctrl->digest.value;
ctrl->digest.valuelen = n;
for (p=line, n=0; n < ctrl->digest.valuelen; p += 2, n++)
buf[n] = xtoi_2 (p);
for (; n < ctrl->digest.valuelen; n++)
buf[n] = 0;
return 0;
}
/* PKSIGN <options>
Perform the actual sign operation. Neither input nor output are
sensitive to to eavesdropping */
static int
cmd_pksign (ASSUAN_CONTEXT ctx, char *line)
{
int rc;
CTRL ctrl = assuan_get_pointer (ctx);
/* fixme: check that all required data is available */
rc = agent_pksign (ctrl, assuan_get_data_fp (ctx));
/* fixme: return an error */
return 0;
}
/* MESSAGE FD=<n>
Set the file descriptor to read a message which is used with
detached signatures */
static int
cmd_message (ASSUAN_CONTEXT ctx, char *line)
{
#if 0
char *endp;
int fd;
CTRL ctrl = assuan_get_pointer (ctx);
if (strncmp (line, "FD=", 3))
return set_error (Syntax_Error, "FD=<n> expected");
line += 3;
if (!digitp (*line))
return set_error (Syntax_Error, "number required");
fd = strtoul (line, &endp, 10);
if (*endp)
return set_error (Syntax_Error, "garbage found");
if (fd == -1)
return set_error (No_Input, NULL);
ctrl->server_local->message_fd = fd;
return 0;
#endif
return set_error (Not_Implemented, NULL);
}
/* Tell the assuan library about our commands */
static int
register_commands (ASSUAN_CONTEXT ctx)
{
static struct {
const char *name;
int cmd_id;
int (*handler)(ASSUAN_CONTEXT, char *line);
} table[] = {
{ "SETHASH", 0, cmd_sethash },
{ "PKSIGN", 0, cmd_pksign },
{ "", ASSUAN_CMD_INPUT, NULL },
{ "", ASSUAN_CMD_OUTPUT, NULL },
{ "MESSAGE", 0, cmd_message },
{ NULL }
};
int i, j, rc;
for (i=j=0; table[i].name; i++)
{
rc = assuan_register_command (ctx,
table[i].cmd_id? table[i].cmd_id
: (ASSUAN_CMD_USER + j++),
table[i].name, table[i].handler);
if (rc)
return rc;
}
return 0;
}
/* Startup the server */
void
start_command_handler (void)
{
int rc;
int filedes[2];
ASSUAN_CONTEXT ctx;
struct server_control_s ctrl;
memset (&ctrl, 0, sizeof ctrl);
/* For now we use a simple pipe based server so that we can work
from scripts. We will later add options to run as a daemon and
wait for requests on a Unix domain socket */
filedes[0] = 0;
filedes[1] = 1;
rc = assuan_init_pipe_server (&ctx, filedes);
if (rc)
{
log_error ("failed to initialize the server: %s\n",
assuan_strerror(rc));
agent_exit (2);
}
rc = register_commands (ctx);
if (rc)
{
log_error ("failed to the register commands with Assuan: %s\n",
assuan_strerror(rc));
agent_exit (2);
}
assuan_set_pointer (ctx, &ctrl);
ctrl.server_local = xcalloc (1, sizeof *ctrl.server_local);
ctrl.server_local->assuan_ctx = ctx;
ctrl.server_local->message_fd = -1;
log_info ("Assuan started\n");
for (;;)
{
rc = assuan_accept (ctx);
if (rc == -1)
{
log_info ("Assuan terminated\n");
break;
}
else if (rc)
{
log_info ("Assuan accept problem: %s\n", assuan_strerror (rc));
break;
}
rc = assuan_process (ctx);
if (rc)
{
log_info ("Assuan processing failed: %s\n", assuan_strerror (rc));
continue;
}
}
assuan_deinit_pipe_server (ctx);
}

View File

@ -18,16 +18,6 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
/*
* How to use the client mode:
* printf '\0\0\0\002AAAAAAAAAAAAAAAAAAAAAPlease enter the passphrase for\n
* key 0x12345678\nJoe Hacker <joe@hackworld.foo>\n'
* | ./gpg-agent --client | od
* Or use a builtin command to shut the agent down.
* ./gpg-agent --shutdown | od
*
*/
#include <config.h>
#include <stdio.h>
@ -43,9 +33,12 @@
#include <gcrypt.h>
#include "util.h"
#include "agent.h"
#include "../assuan/assuan.h" /* malloc hooks */
#include "i18n.h"
#define N_(a) a
#define _(a) a
enum cmd_and_opt_values
@ -72,6 +65,7 @@ enum cmd_and_opt_values
aTest };
static ARGPARSE_OPTS opts[] = {
{ 301, NULL, 0, N_("@Options:\n ") },
@ -95,17 +89,6 @@ static ARGPARSE_OPTS opts[] = {
};
static struct {
const char *homedir;
int client;
int verbose;
int quiet;
unsigned int debug;
int nodetach;
int grab;
const char *logfile;
int csh_style;
} opt;
typedef struct {
int used;
@ -231,8 +214,13 @@ main (int argc, char **argv )
int greeting = 0;
int nogreeting = 0;
int server_mode = 0;
int client = 0;
int do_shutdown = 0;
int do_flush = 0;
int nodetach = 0;
int grab = 0;
int csh_style = 0;
char *logfile = NULL;
set_strusage( my_strusage );
/* log_set_name ("gpg-agent"); */
@ -252,7 +240,7 @@ main (int argc, char **argv )
shell = getenv("SHELL");
if (shell && strlen(shell) >= 3 && !strcmp(shell+strlen(shell)-3, "csh") )
opt.csh_style = 1;
csh_style = 1;
opt.homedir = getenv("GNUPGHOME");
if (!opt.homedir || !*opt.homedir)
@ -263,7 +251,7 @@ main (int argc, char **argv )
opt.homedir = "~/.gnupg-test";
#endif
}
opt.grab = 1;
grab = 1;
/* check whether we have a config file on the commandline */
orig_argc = argc;
@ -345,14 +333,14 @@ main (int argc, char **argv )
case oNoVerbose: opt.verbose = 0; break;
case oNoOptions: break; /* no-options */
case oHomedir: opt.homedir = pargs.r.ret_str; break;
case oNoDetach: opt.nodetach = 1; break;
case oNoGrab: opt.grab = 0; break;
case oClient: opt.client = 1; break;
case oShutdown: opt.client = 1; do_shutdown = 1; break;
case oFlush: opt.client = 1; do_flush = 1; break;
case oLogFile: opt.logfile = pargs.r.ret_str; break;
case oCsh: opt.csh_style = 1; break;
case oSh: opt.csh_style = 0; break;
case oNoDetach: nodetach = 1; break;
case oNoGrab: grab = 0; break;
case oClient: client = 1; break;
case oShutdown: client = 1; do_shutdown = 1; break;
case oFlush: client = 1; do_flush = 1; break;
case oLogFile: logfile = pargs.r.ret_str; break;
case oCsh: csh_style = 1; break;
case oSh: csh_style = 0; break;
case oServer: server_mode = 1; break;
default : pargs.err = configfp? 1:2; break;
@ -390,7 +378,7 @@ main (int argc, char **argv )
exit (1);
}
if (opt.client)
if (client)
{ /* a client for testing this agent */
#if 0 /* FIXME: We are going to use assuan here */
int fd;
@ -444,6 +432,10 @@ main (int argc, char **argv )
close (fd );
#endif
}
else if (server_mode)
{ /* for now this is the simple pipe based server */
start_command_handler ();
}
else
{ /* regular server mode */
int listen_fd;
@ -495,7 +487,7 @@ main (int argc, char **argv )
}
/* print the environment string, so that the caller can use
eval to set it */
if (opt.csh_style)
if (csh_style)
{
*strchr (infostr, '=') = ' ';
printf ( "setenv %s\n", infostr);
@ -510,7 +502,7 @@ main (int argc, char **argv )
if ( (opt.debug & 1) )
sleep( 20 ); /* give us some time to attach gdb to the child */
if (opt.logfile)
if (logfile)
{
/* FIXME:log_set_logfile (opt.logfile, -1);*/
}
@ -522,7 +514,7 @@ main (int argc, char **argv )
exit (1);
}
if ( !opt.nodetach )
if ( !nodetach )
{
for (i=0 ; i <= 2; i++ )
{
@ -589,6 +581,28 @@ main (int argc, char **argv )
return 0;
}
void
agent_exit (int rc)
{
#if 0
#warning no update_random_seed_file
update_random_seed_file();
#endif
#if 0
/* at this time a bit annoying */
if (opt.debug & DBG_MEMSTAT_VALUE)
{
gcry_control( GCRYCTL_DUMP_MEMORY_STATS );
gcry_control( GCRYCTL_DUMP_RANDOM_STATS );
}
if (opt.debug)
gcry_control (GCRYCTL_DUMP_SECMEM_STATS );
#endif
gcry_control (GCRYCTL_TERM_SECMEM );
rc = rc? rc : log_get_errorcount(0)? 2 : 0;
exit (rc);
}
static int
start_listening (const char *name)

39
agent/pksign.c Normal file
View File

@ -0,0 +1,39 @@
/* pksign.c - public key signing (well, acually using a secret key)
* Copyright (C) 2001 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#include <config.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include "agent.h"
/* SIGN whatever information we have accumulated in CTRL and write it back to
OUTFP. */
int
agent_pksign (CTRL ctrl, FILE *outfp)
{
return -1;
}