1
0
Fork 0
mirror of git://git.gnupg.org/gnupg.git synced 2025-07-03 22:56:33 +02:00

Initial code checking for backup - not yet working.

This commit is contained in:
Werner Koch 2011-01-10 14:30:17 +01:00
parent 7d24ffaf80
commit 8c8c45725f
25 changed files with 1115 additions and 93 deletions

View file

@ -1,3 +1,18 @@
2011-01-07 Werner Koch <wk@g10code.com>
* call-dirmngr.c, call-dirmngr.h: New.
* gpg.h (server_control_s): Add DIRMNGR_LOCAL.
* gpg.c: Include call-dirmngr.h.
(gpg_deinit_default_ctrl): Call gpg_dirmngr_deinit_session_data.
2011-01-06 Werner Koch <wk@g10code.com>
* gpg.c (main): Use keyserver_spec_t.
* options.h (struct opt): Factor definition of struct keyserver
out to ../common/keyserver.h.
(keyserver_spec_t): New.
2010-12-09 Werner Koch <wk@g10code.com>
* tdbio.c (tdbio_set_dbname) [W32CE]: Take care of missing errno.

View file

@ -102,6 +102,7 @@ gpg2_SOURCES = gpg.c \
helptext.c \
keyserver.c \
keyserver-internal.h \
call-dirmngr.c call-dirmngr.h \
photoid.c photoid.h \
call-agent.c call-agent.h \
card-util.c \

256
g10/call-dirmngr.c Normal file
View file

@ -0,0 +1,256 @@
/* call-dirmngr.c - GPG operations to the Dirmngr.
* Copyright (C) 2011 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 3 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, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <time.h>
#include <assert.h>
#ifdef HAVE_LOCALE_H
# include <locale.h>
#endif
#include "gpg.h"
#include <assuan.h>
#include "util.h"
#include "membuf.h"
#include "options.h"
#include "i18n.h"
#include "asshelp.h"
#include "call-dirmngr.h"
/* Data used to associate an session with dirmngr contexts. We can't
use a simple one to one mapping because we sometimes need two
connection s to the dirmngr; for example while doing a listing and
being in a data callback we may want to retrieve a key. The local
dirmngr data takes care of this. At the end of the session the
function dirmngr_deinit_session_data is called bu gpg.c to cleanup
these resources. Note that gpg.h defines a typedef dirmngr_local_t
for this structure. */
struct dirmngr_local_s
{
/* Link to other contexts which are used simultaneously. */
struct dirmngr_local_s *next;
/* The active Assuan context. */
static assuan_context_t ctx;
/* Flag set to true while an operation is running on CTX. */
int is_active;
};
/* Deinitialize all session data of dirmngr pertaining to CTRL. */
void
gpg_dirmngr_deinit_session_data (ctrl_t ctrl)
{
dirmngr_local_t dml;
while ((dml = ctrl->dirmngr_local))
{
ctrl->dirmngr_local = dml->next;
if (dml->is_active)
log_error ("oops: trying to cleanup an active dirmngr context\n");
else
assuan_release (dml->ctx);
xfree (dml);
}
}
/* Try to connect to the Dirmngr via a socket or fork it off if
possible. Handle the server's initial greeting and set global
options. */
static gpg_error_t
create_context (ctrl_t ctrl, assuan_context_t *r_ctx)
{
gpg_error_t err;
assuan_context_t ctx;
*r_ctx = NULL;
err = start_new_dirmngr (&ctx,
GPG_ERR_SOURCE_DEFAULT,
opt.homedir,
NULL,
opt.verbose, DBG_ASSUAN,
NULL /*gpg_status2*/, ctrl);
if (!err)
{
keyserver_spec_t ksi;
/* Tell the dirmngr that we want to collect audit event. */
/* err = assuan_transact (agent_ctx, "OPTION audit-events=1", */
/* NULL, NULL, NULL, NULL, NULL, NULL); */
/* Set all configured keyservers. We clear existing keyservers
so that any keyserver configured in GPG overrides keyservers
possibly configured in Dirmngr. */
if (ksi = opt.keyservers; !err && ksi; ksi = ksi->next)
{
char *line;
line = xtryasprintf ("KEYSERVER%s %s",
ksi == opt.keyservers? " --clear":"", ksi->uri);
if (!line)
err = gpg_error_from_syserror ();
else
{
err = assuan_transact (ctx, line,
NULL, NULL, NULL, NULL, NULL, NULL);
xfree (line);
}
}
}
if (err)
assuan_release (ctx);
else
{
/* audit_log_ok (ctrl->audit, AUDIT_DIRMNGR_READY, err); */
*r_ctx = ctx;
}
return err;
}
/* Get a context for accessing dirmngr. If no context is available a
new one is created and - if requred - dirmngr started. On success
an assuan context is stored at R_CTX. This Context may only be
released by means of close_context. Note that NULL is stored at
R_CTX on error. */
static gpg_error_t
open_context (ctrl_t ctrl, assuan_context_t *r_ctx)
{
gpg_error_t err;
dirmngr_local_t dml;
*r_ctx = NULL;
for (;;)
{
for (dml = ctrl->dirmngr_local; dml && dml->is_active; dml = dml->next)
;
if (dml)
{
/* Found an inactive local session - return that. */
assert (!dml->is_active);
dml->is_active = 1;
return dml;
}
dml = xtrycalloc (1, sizeof *dml);
if (!dml)
return gpg_error_from_syserror ();
err = create_context (ctrl, &dml->ctx);
if (err)
{
xfree (dml);
return err;
}
/* To be on the Pth thread safe site we need to add it to a
list; this is far easier than to have a lock for this
function. It should not happen anyway but the code is free
because we need it for the is_active check above. */
dml->next = ctrl->dirmngr_local;
ctrl->dirmngr_local = dml;
}
}
/* Close the assuan context CTX or return it to a pool of unused
contexts. If CTX is NULL, the function does nothing. */
static void
close_context (ctrl_t ctrl, assuan_context_t ctx)
{
dirmngr_local_t dml;
if (!ctx)
return;
for (dml = ctrl->dirmngr_local; dml; dml = dml->next)
{
if (dml->ctx == ctx)
{
if (!ctx->is_active)
log_fatal ("closing inactive dirmngr context %p\n", ctx);
ctx->is_active = 0;
return;
}
}
log_fatal ("closing unknown dirmngr ctx %p\n", ctx);
}
int
gpg_dirmngr_ks_search (ctrl_t ctrl, strlist_t names,
void (*cb)(void*, ksba_cert_t), void *cb_value)
{
gpg_error_t err;
assuan_context_t ctx;
char *pattern;
char line[ASSUAN_LINELENGTH];
err = open_context (ctrl, &ctx);
if (err)
return err;
pattern = pattern_from_strlist (names);
if (!pattern)
{
if (ctx == dirmngr_ctx)
release_dirmngr (ctrl);
else
release_dirmngr2 (ctrl);
return out_of_core ();
}
snprintf (line, DIM(line)-1, "LOOKUP%s %s",
cache_only? " --cache-only":"", pattern);
line[DIM(line)-1] = 0;
xfree (pattern);
parm.ctrl = ctrl;
parm.ctx = ctx;
parm.cb = cb;
parm.cb_value = cb_value;
parm.error = 0;
init_membuf (&parm.data, 4096);
rc = assuan_transact (ctx, line, lookup_cb, &parm,
NULL, NULL, lookup_status_cb, &parm);
xfree (get_membuf (&parm.data, &len));
if (ctx == dirmngr_ctx)
release_dirmngr (ctrl);
else
release_dirmngr2 (ctrl);
if (rc)
return rc;
close_context (ctrl, ctx);
return parm.error;
}

26
g10/call-dirmngr.h Normal file
View file

@ -0,0 +1,26 @@
/* call-dirmngr.h - GPG operations to the Dirmngr
* Copyright (C) 2011 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 3 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, see <http://www.gnu.org/licenses/>.
*/
#ifndef GNUPG_G10_CALL_DIRMNGR_H
#define GNUPG_G10_CALL_DIRMNGR_H
void gpg_dirmngr_deinit_session_data (ctrl_t ctrl);
#endif /*GNUPG_G10_CALL_DIRMNGR_H*/

View file

@ -1,6 +1,6 @@
/* gpg.c - The GnuPG utility (main for gpg)
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
* 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
* 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -54,6 +54,7 @@
#include "exec.h"
#include "gc-opt-flags.h"
#include "asshelp.h"
#include "call-dirmngr.h"
#if defined(HAVE_DOSISH_SYSTEM) || defined(__CYGWIN__)
#define MY_O_BINARY O_BINARY
@ -1822,7 +1823,7 @@ gpg_init_default_ctrl (ctrl_t ctrl)
static void
gpg_deinit_default_ctrl (ctrl_t ctrl)
{
(void)ctrl;
gpg_dirmngr_deinit_session_data (ctrl);
}
@ -2658,15 +2659,15 @@ main (int argc, char **argv)
break;
case oKeyServer:
{
struct keyserver_spec *keyserver;
keyserver=parse_keyserver_uri(pargs.r.ret_str,0,
configname,configlineno);
if(!keyserver)
log_error(_("could not parse keyserver URL\n"));
keyserver_spec_t keyserver;
keyserver = parse_keyserver_uri (pargs.r.ret_str,0,
configname,configlineno);
if (!keyserver)
log_error (_("could not parse keyserver URL\n"));
else
{
keyserver->next=opt.keyserver;
opt.keyserver=keyserver;
keyserver->next = opt.keyserver;
opt.keyserver = keyserver;
}
}
break;
@ -2853,14 +2854,14 @@ main (int argc, char **argv)
break;
case oDefaultKeyserverURL:
{
struct keyserver_spec *keyserver;
keyserver=parse_keyserver_uri(pargs.r.ret_str,1,
configname,configlineno);
if(!keyserver)
log_error(_("could not parse keyserver URL\n"));
keyserver_spec_t keyserver;
keyserver = parse_keyserver_uri (pargs.r.ret_str,1,
configname,configlineno);
if (!keyserver)
log_error (_("could not parse keyserver URL\n"));
else
free_keyserver_spec(keyserver);
free_keyserver_spec (keyserver);
opt.def_keyserver_url = pargs.r.ret_str;
}
break;

View file

@ -48,6 +48,10 @@
/* Object used to keep state locally to server.c . */
struct server_local_s;
/* Object used to keep state locally to call-dirmngr.c . */
struct dirmngr_local_s;
typedef struct dirmngr_local_s *dirmngr_local_t;
/* Object used to describe a keyblok node. */
typedef struct kbnode_struct *KBNODE;
typedef struct kbnode_struct *kbnode_t;
@ -58,7 +62,11 @@ typedef struct kbnode_struct *kbnode_t;
gpg_init_default_ctrl(). */
struct server_control_s
{
/* Local data for server.c */
struct server_local_s *server_local;
/* Local data for call-dirmngr.c */
dirmngr_local_t dirmngr_local;
};

View file

@ -40,7 +40,7 @@ int keyserver_import_fprint (ctrl_t ctrl, const byte *fprint,size_t fprint_len,
int keyserver_import_keyid (ctrl_t ctrl, u32 *keyid,
struct keyserver_spec *keyserver);
int keyserver_refresh (ctrl_t ctrl, strlist_t users);
int keyserver_search (ctrl_t ctrl, strlist_t tokens);
gpg_error_t keyserver_search (ctrl_t ctrl, strlist_t tokens);
int keyserver_fetch (ctrl_t ctrl, strlist_t urilist);
int keyserver_import_cert (ctrl_t ctrl, const char *name,
unsigned char **fpr,size_t *fpr_len);

View file

@ -45,6 +45,7 @@
#ifdef USE_DNS_SRV
#include "srv.h"
#endif
#include "membuf.h"
#ifdef HAVE_W32_SYSTEM
@ -236,9 +237,9 @@ keyserver_match(struct keyserver_spec *spec)
parser any longer so it can be removed, or at least moved to
keyserver/ksutil.c for limited use in gpgkeys_ldap or the like. */
struct keyserver_spec *
parse_keyserver_uri(const char *string,int require_scheme,
const char *configname,unsigned int configlineno)
keyserver_spec_t
parse_keyserver_uri (const char *string,int require_scheme,
const char *configname,unsigned int configlineno)
{
int assume_hkp=0;
struct keyserver_spec *keyserver;
@ -1530,6 +1531,7 @@ keyserver_spawn (ctrl_t ctrl,
return ret;
}
static int
keyserver_work (ctrl_t ctrl,
enum ks_action action,strlist_t list,KEYDB_SEARCH_DESC *desc,
@ -1538,23 +1540,16 @@ keyserver_work (ctrl_t ctrl,
{
int rc=0,ret=0;
if(!keyserver)
if (!keyserver)
{
log_error(_("no keyserver known (use option --keyserver)\n"));
return G10ERR_BAD_URI;
log_error (_("no keyserver known (use option --keyserver)\n"));
return gpg_error (GPG_ERR_BAD_URI);
}
#ifdef DISABLE_KEYSERVER_HELPERS
log_error(_("external keyserver calls are not supported in this build\n"));
return G10ERR_KEYSERVER;
#else
/* Spawn a handler */
rc = keyserver_spawn (ctrl, action, list, desc, count,
&ret, fpr, fpr_len, keyserver);
if(ret)
if (ret)
{
switch(ret)
{
@ -1591,15 +1586,14 @@ keyserver_work (ctrl_t ctrl,
return G10ERR_KEYSERVER;
}
if(rc)
if (rc)
{
log_error(_("keyserver communications error: %s\n"),g10_errstr(rc));
log_error (_("keyserver communications error: %s\n"),g10_errstr(rc));
return rc;
}
return 0;
#endif /* ! DISABLE_KEYSERVER_HELPERS*/
}
int
@ -1961,15 +1955,100 @@ keyserver_refresh (ctrl_t ctrl, strlist_t users)
return rc;
}
int
/* Search for keys on the keyservers. The patterns are given in the
string list TOKENS. */
gpg_error_t
keyserver_search (ctrl_t ctrl, strlist_t tokens)
{
if (tokens)
return keyserver_work (ctrl, KS_SEARCH, tokens, NULL, 0,
NULL, NULL, opt.keyserver);
return 0;
gpg_error_t err;
int rc=0,ret=0;
char *searchstr;
/* FIXME: WORK IN PROGRESS */
if (!tokens)
return 0; /* Return success if no patterns are given. */
if (!opt.keyserver)
{
log_error (_("no keyserver known (use option --keyserver)\n"));
return gpg_error (GPG_ERR_NO_KEYSERVER);
}
/* switch(ret) */
/* { */
/* case KEYSERVER_SCHEME_NOT_FOUND: */
/* log_error(_("no handler for keyserver scheme `%s'\n"), */
/* opt.keyserver->scheme); */
/* break; */
/* case KEYSERVER_NOT_SUPPORTED: */
/* log_error(_("action `%s' not supported with keyserver " */
/* "scheme `%s'\n"), "search", opt.keyserver->scheme); */
/* break; */
/* case KEYSERVER_TIMEOUT: */
/* log_error(_("keyserver timed out\n")); */
/* break; */
/* case KEYSERVER_INTERNAL_ERROR: */
/* default: */
/* log_error(_("keyserver internal error\n")); */
/* break; */
/* } */
/* return gpg_error (GPG_ERR_KEYSERVER); */
/* Write global options */
/* for(temp=opt.keyserver_options.other;temp;temp=temp->next) */
/* fprintf(spawn->tochild,"OPTION %s\n",temp->d); */
/* Write per-keyserver options */
/* for(temp=keyserver->options;temp;temp=temp->next) */
/* fprintf(spawn->tochild,"OPTION %s\n",temp->d); */
/* Which keys do we want? Remember that the gpgkeys_ program
is going to lump these together into a search string. */
{
membuf_t mb;
strlist_t item;
init_membuf (&mb, 1024);
for (item = tokens; item; item = item->next)
{
if (item != tokens)
put_membuf (&mb, " ", 1);
put_membuf_str (&mb, item->d);
}
put_membuf (&mb, "", 1); /* Append Nul. */
searchstr = get_membuf (&mb, NULL);
if (!searchstr)
{
err = gpg_error_from_syserror ();
}
}
log_info (_("searching for \"%s\" from %s\n"), searchstr, keyserver->uri);
{
estream_t fp;
err = gpg_dirmngr_ks_search (ctrl, searchstr, &fp);
keyserver_search_prompt (ctrl, fp,searchstr);
}
leave:
xfree(line);
xfree(searchstr);
*prog=exec_finish(spawn);
return ret;
}
int
keyserver_fetch (ctrl_t ctrl, strlist_t urilist)
{

View file

@ -1,6 +1,6 @@
/* options.h
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
* 2007, 2010 Free Software Foundation, Inc.
* 2007, 2010, 2011 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -35,6 +35,13 @@
#endif
#endif
/* Declaration of a keyserver spec type. The definition is found in
../common/keyserver.h. */
struct keyserver_spec;
typedef struct keyserver_spec *keyserver_spec_t;
/* Global options for GPG. */
EXTERN_UNLESS_MAIN_MODULE
struct
{
@ -130,22 +137,7 @@ struct
int not_dash_escaped;
int escape_from;
int lock_once;
struct keyserver_spec
{
char *uri;
char *scheme;
char *auth;
char *host;
char *port;
char *path;
char *opaque;
strlist_t options;
struct
{
unsigned int direct_uri:1;
} flags;
struct keyserver_spec *next;
} *keyserver;
keyserver_spec_t keyserver; /* The list of configured keyservers. */
struct
{
unsigned int options;
@ -245,7 +237,7 @@ struct
AKL_KEYSERVER,
AKL_SPEC
} type;
struct keyserver_spec *spec;
keyserver_spec_t spec;
struct akl *next;
} *auto_key_locate;