mirror of
git://git.gnupg.org/gnupg.git
synced 2025-01-03 12:11:33 +01:00
Friedman is setting up his desk
This commit is contained in:
parent
f917085be5
commit
1e443ad637
@ -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
78
agent/agent.h
Normal 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
229
agent/command.c
Normal 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);
|
||||
}
|
||||
|
@ -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
39
agent/pksign.c
Normal 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;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user