mirror of
git://git.gnupg.org/gnupg.git
synced 2025-01-03 12:11:33 +01:00
Initial code checking for backup - not yet working.
This commit is contained in:
parent
7d24ffaf80
commit
8c8c45725f
8
.gitignore
vendored
Normal file
8
.gitignore
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
Makefile.in
|
||||
aclocal.m4
|
||||
autom4te.cache/
|
||||
configure
|
||||
config.h.in
|
||||
config.h
|
||||
common/audit-events.h
|
||||
common/status-codes.h
|
@ -1,3 +1,15 @@
|
||||
2011-01-07 Werner Koch <wk@g10code.com>
|
||||
|
||||
* util.h (GPG_ERR_NO_KEYSERVER): New.
|
||||
|
||||
* keyserver.h (keyserver_spec): Move from ../g10/options.h to here.
|
||||
|
||||
* http.c (do_parse_uri): Add arg NO_SCHEME_CHECK. Change all
|
||||
callers. Support HKP and HKPS.
|
||||
(_http_parse_uri): Do proper error management.
|
||||
* http.h (parsed_uri_s): Add field IS_HTTP.
|
||||
(http_parse_uri): Support NO_SCHEME_CHECK arg.
|
||||
|
||||
2010-12-17 Werner Koch <wk@g10code.com>
|
||||
|
||||
* asshelp.c (lock_spawning): Add arg VERBOSE. Improve timeout
|
||||
@ -2251,7 +2263,7 @@
|
||||
|
||||
|
||||
Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
|
||||
2009, 2010 Free Software Foundation, Inc.
|
||||
2009, 2010, 2011 Free Software Foundation, Inc.
|
||||
|
||||
This file is free software; as a special exception the author gives
|
||||
unlimited permission to copy and/or distribute it, with or without
|
||||
|
@ -138,7 +138,8 @@ typedef unsigned long longcounter_t;
|
||||
typedef void * gnutls_session_t;
|
||||
#endif
|
||||
|
||||
static gpg_err_code_t do_parse_uri (parsed_uri_t uri, int only_local_part);
|
||||
static gpg_err_code_t do_parse_uri (parsed_uri_t uri, int only_local_part,
|
||||
int no_scheme_check);
|
||||
static int remove_escapes (char *string);
|
||||
static int insert_escapes (char *buffer, const char *string,
|
||||
const char *special);
|
||||
@ -356,7 +357,7 @@ _http_open (http_t *r_hd, http_req_t reqtype, const char *url,
|
||||
hd->flags = flags;
|
||||
hd->tls_context = tls_context;
|
||||
|
||||
err = _http_parse_uri (&hd->uri, url, errsource);
|
||||
err = _http_parse_uri (&hd->uri, url, 0, errsource);
|
||||
if (!err)
|
||||
err = send_request (hd, auth, proxy, srvtag, headers, errsource);
|
||||
|
||||
@ -368,7 +369,6 @@ _http_open (http_t *r_hd, http_req_t reqtype, const char *url,
|
||||
es_fclose (hd->fp_read);
|
||||
if (hd->fp_write)
|
||||
es_fclose (hd->fp_write);
|
||||
http_release_parsed_uri (hd->uri);
|
||||
xfree (hd);
|
||||
}
|
||||
else
|
||||
@ -511,18 +511,27 @@ http_get_status_code (http_t hd)
|
||||
|
||||
/*
|
||||
* Parse an URI and put the result into the newly allocated RET_URI.
|
||||
* The caller must always use release_parsed_uri() to releases the
|
||||
* resources (even on error).
|
||||
* On success the caller must use release_parsed_uri() to releases the
|
||||
* resources. If NO_SCHEME_CHECK is set, the function tries to parse
|
||||
* the URL in the same way it would do for an HTTP style URI.
|
||||
*/
|
||||
gpg_error_t
|
||||
_http_parse_uri (parsed_uri_t * ret_uri, const char *uri,
|
||||
gpg_err_source_t errsource)
|
||||
_http_parse_uri (parsed_uri_t *ret_uri, const char *uri,
|
||||
int no_scheme_check, gpg_err_source_t errsource)
|
||||
{
|
||||
gpg_err_code_t ec;
|
||||
|
||||
*ret_uri = xtrycalloc (1, sizeof **ret_uri + strlen (uri));
|
||||
if (!*ret_uri)
|
||||
return gpg_err_make (errsource, gpg_err_code_from_syserror ());
|
||||
strcpy ((*ret_uri)->buffer, uri);
|
||||
return gpg_err_make (errsource, do_parse_uri (*ret_uri, 0));
|
||||
ec = do_parse_uri (*ret_uri, 0, no_scheme_check);
|
||||
if (ec)
|
||||
{
|
||||
xfree (*ret_uri);
|
||||
*ret_uri = NULL;
|
||||
}
|
||||
return gpg_err_make (errsource, ec);
|
||||
}
|
||||
|
||||
void
|
||||
@ -543,7 +552,7 @@ http_release_parsed_uri (parsed_uri_t uri)
|
||||
|
||||
|
||||
static gpg_err_code_t
|
||||
do_parse_uri (parsed_uri_t uri, int only_local_part)
|
||||
do_parse_uri (parsed_uri_t uri, int only_local_part, int no_scheme_check)
|
||||
{
|
||||
uri_tuple_t *tail;
|
||||
char *p, *p2, *p3, *pp;
|
||||
@ -557,6 +566,7 @@ do_parse_uri (parsed_uri_t uri, int only_local_part)
|
||||
uri->port = 0;
|
||||
uri->params = uri->query = NULL;
|
||||
uri->use_tls = 0;
|
||||
uri->is_http = 0;
|
||||
|
||||
/* A quick validity check. */
|
||||
if (strspn (p, VALID_URI_CHARS) != n)
|
||||
@ -572,15 +582,24 @@ do_parse_uri (parsed_uri_t uri, int only_local_part)
|
||||
*pp = tolower (*(unsigned char*)pp);
|
||||
uri->scheme = p;
|
||||
if (!strcmp (uri->scheme, "http"))
|
||||
uri->port = 80;
|
||||
{
|
||||
uri->port = 80;
|
||||
uri->is_http = 1;
|
||||
}
|
||||
else if (!strcmp (uri->scheme, "hkp"))
|
||||
{
|
||||
uri->port = 11371;
|
||||
uri->is_http = 1;
|
||||
}
|
||||
#ifdef HTTP_USE_GNUTLS
|
||||
else if (!strcmp (uri->scheme, "https"))
|
||||
else if (!strcmp (uri->scheme, "https") || !strcmp (uri->scheme,"hkps"))
|
||||
{
|
||||
uri->port = 443;
|
||||
uri->is_http = 1;
|
||||
uri->use_tls = 1;
|
||||
}
|
||||
#endif
|
||||
else
|
||||
else if (!no_scheme_check)
|
||||
return GPG_ERR_INV_URI; /* Unsupported scheme */
|
||||
|
||||
p = p2;
|
||||
@ -852,12 +871,11 @@ send_request (http_t hd, const char *auth,
|
||||
if (proxy)
|
||||
http_proxy = proxy;
|
||||
|
||||
err = _http_parse_uri (&uri, http_proxy, errsource);
|
||||
err = _http_parse_uri (&uri, http_proxy, 0, errsource);
|
||||
if (err)
|
||||
{
|
||||
log_error ("invalid HTTP proxy (%s): %s\n",
|
||||
http_proxy, gpg_strerror (err));
|
||||
http_release_parsed_uri (uri);
|
||||
return gpg_err_make (errsource, GPG_ERR_CONFIGURATION);
|
||||
}
|
||||
|
||||
@ -1882,11 +1900,10 @@ main (int argc, char **argv)
|
||||
http_register_tls_callback (verify_callback);
|
||||
#endif /*HTTP_USE_GNUTLS*/
|
||||
|
||||
rc = http_parse_uri (&uri, *argv);
|
||||
rc = http_parse_uri (&uri, *argv, 0);
|
||||
if (rc)
|
||||
{
|
||||
log_error ("`%s': %s\n", *argv, gpg_strerror (rc));
|
||||
http_release_parsed_uri (uri);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -23,7 +23,8 @@
|
||||
#include <gpg-error.h>
|
||||
#include "../common/estream.h"
|
||||
|
||||
struct uri_tuple_s {
|
||||
struct uri_tuple_s
|
||||
{
|
||||
struct uri_tuple_s *next;
|
||||
const char *name; /* A pointer into name. */
|
||||
char *value; /* A pointer to value (a Nul is always appended). */
|
||||
@ -36,8 +37,9 @@ typedef struct uri_tuple_s *uri_tuple_t;
|
||||
struct parsed_uri_s
|
||||
{
|
||||
/* All these pointers point into BUFFER; most stuff is not escaped. */
|
||||
char *scheme; /* Pointer to the scheme string (lowercase). */
|
||||
int use_tls; /* Whether TLS should be used. */
|
||||
char *scheme; /* Pointer to the scheme string (always lowercase). */
|
||||
unsigned int is_http:1; /* This is a HTTP style URI. */
|
||||
unsigned int use_tls:1; /* Whether TLS should be used. */
|
||||
char *auth; /* username/password for basic auth */
|
||||
char *host; /* Host (converted to lowercase). */
|
||||
unsigned short port; /* Port (always set if the host is set). */
|
||||
@ -71,9 +73,9 @@ typedef struct http_context_s *http_t;
|
||||
void http_register_tls_callback (gpg_error_t (*cb) (http_t, void *, int));
|
||||
|
||||
gpg_error_t _http_parse_uri (parsed_uri_t *ret_uri, const char *uri,
|
||||
gpg_err_source_t errsource);
|
||||
#define http_parse_uri(a,b) \
|
||||
_http_parse_uri ((a), (b), GPG_ERR_SOURCE_DEFAULT)
|
||||
int no_scheme_check, gpg_err_source_t errsource);
|
||||
#define http_parse_uri(a,b,c) \
|
||||
_http_parse_uri ((a), (b), (c), GPG_ERR_SOURCE_DEFAULT)
|
||||
|
||||
void http_release_parsed_uri (parsed_uri_t uri);
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* keyserver.h - Public definitions for gpg keyserver helpers.
|
||||
* Copyright (C) 2001, 2002 Free Software Foundation, Inc.
|
||||
* Copyright (C) 2001, 2002, 2011 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
@ -39,4 +39,26 @@
|
||||
/* Must be 127 due to shell internal magic. */
|
||||
#define KEYSERVER_SCHEME_NOT_FOUND 127
|
||||
|
||||
/* Object to hold information pertaining to a keyserver; it further
|
||||
allows to build a list of keyservers. Note that g10/options.h has
|
||||
a typedef for this. FIXME: We should make use of the
|
||||
parse_uri_t. */
|
||||
struct keyserver_spec
|
||||
{
|
||||
struct keyserver_spec *next;
|
||||
char *uri;
|
||||
char *scheme;
|
||||
char *auth;
|
||||
char *host;
|
||||
char *port;
|
||||
char *path;
|
||||
char *opaque;
|
||||
strlist_t options;
|
||||
struct
|
||||
{
|
||||
unsigned int direct_uri:1;
|
||||
} flags;
|
||||
};
|
||||
|
||||
|
||||
#endif /*GNUPG_COMMON_KEYSERVER_H*/
|
||||
|
@ -36,6 +36,9 @@
|
||||
#ifndef GPG_ERR_MISSING_ISSUER_CERT
|
||||
#define GPG_ERR_MISSING_ISSUER_CERT 185
|
||||
#endif
|
||||
#ifndef GPG_ERR_NO_KEYSERVER
|
||||
#define GPG_ERR_NO_KEYSERVER 186
|
||||
#endif
|
||||
#ifndef GPG_ERR_FULLY_CANCELED
|
||||
#define GPG_ERR_FULLY_CANCELED 198
|
||||
#endif
|
||||
|
@ -1,3 +1,20 @@
|
||||
2011-01-06 Werner Koch <wk@g10code.com>
|
||||
|
||||
* server.c (release_ctrl_keyservers): New.
|
||||
(cmd_keyserver): New.
|
||||
|
||||
* dirmngr.h (uri_item_t): New.
|
||||
(struct server_control_s): Add field KEYSERVERS.
|
||||
|
||||
2011-01-04 Werner Koch <wk@g10code.com>
|
||||
|
||||
* ks-engine-hkp.c: New.
|
||||
* ks-engine.h: New.
|
||||
* ks-action.c, ks-action.h: New.
|
||||
* server.c: Include ks-action.h.
|
||||
(cmd_ks_search): New.
|
||||
* Makefile.am (dirmngr_SOURCES): Add new files.
|
||||
|
||||
2010-12-14 Werner Koch <wk@g10code.com>
|
||||
|
||||
* cdb.h (struct cdb) [W32]: Add field CDB_MAPPING.
|
||||
@ -1488,7 +1505,8 @@
|
||||
[Update after merge with GnuPG: see ./ChangeLog.1]
|
||||
|
||||
|
||||
Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010 g10 Code GmbH
|
||||
Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010,
|
||||
2011 Free Software Foundation, Inc.
|
||||
|
||||
This file is free software; as a special exception the author gives
|
||||
unlimited permission to copy and/or distribute it, with or without
|
||||
|
@ -49,7 +49,8 @@ noinst_HEADERS = dirmngr.h crlcache.h crlfetch.h misc.h
|
||||
dirmngr_SOURCES = dirmngr.c dirmngr.h server.c crlcache.c crlfetch.c \
|
||||
ldapserver.h ldapserver.c certcache.c certcache.h \
|
||||
cdb.h cdblib.c ldap.c misc.c dirmngr-err.h w32-ldap-help.h \
|
||||
ocsp.c ocsp.h validate.c validate.h ldap-wrapper.h $(ldap_url)
|
||||
ocsp.c ocsp.h validate.c validate.h ldap-wrapper.h $(ldap_url) \
|
||||
ks-action.c ks-action.h ks-engine.h ks-engine-hkp.c
|
||||
|
||||
if USE_LDAPWRAPPER
|
||||
dirmngr_SOURCES += ldap-wrapper.c
|
||||
|
@ -160,7 +160,7 @@ crl_fetch (ctrl_t ctrl, const char *url, ksba_reader_t *reader)
|
||||
*reader = NULL;
|
||||
|
||||
once_more:
|
||||
err = http_parse_uri (&uri, url);
|
||||
err = http_parse_uri (&uri, url, 0);
|
||||
http_release_parsed_uri (uri);
|
||||
if (err && url && !strncmp (url, "https:", 6))
|
||||
{
|
||||
@ -172,7 +172,7 @@ crl_fetch (ctrl_t ctrl, const char *url, ksba_reader_t *reader)
|
||||
if (free_this)
|
||||
{
|
||||
strcpy (stpcpy (free_this,"http:"), url+6);
|
||||
err = http_parse_uri (&uri, free_this);
|
||||
err = http_parse_uri (&uri, free_this, 0);
|
||||
http_release_parsed_uri (uri);
|
||||
if (!err)
|
||||
{
|
||||
|
@ -32,7 +32,7 @@
|
||||
#include "../common/membuf.h"
|
||||
#include "../common/sysutils.h" /* (gnupg_fd_t) */
|
||||
#include "../common/i18n.h"
|
||||
|
||||
#include "../common/http.h" /* (parsed_uri_t) */
|
||||
|
||||
/* This objects keeps information about a particular LDAP server and
|
||||
is used as item of a single linked list of servers. */
|
||||
@ -49,6 +49,17 @@ struct ldap_server_s
|
||||
typedef struct ldap_server_s *ldap_server_t;
|
||||
|
||||
|
||||
/* This objects is used to build a list of URI consisting of the
|
||||
original and the parsed URI. */
|
||||
struct uri_item_s
|
||||
{
|
||||
struct uri_item_s *next;
|
||||
parsed_uri_t parsed_uri; /* The broken down URI. */
|
||||
char uri[1]; /* The original URI. */
|
||||
};
|
||||
typedef struct uri_item_s *uri_item_t;
|
||||
|
||||
|
||||
/* A list of fingerprints. */
|
||||
struct fingerprint_list_s;
|
||||
typedef struct fingerprint_list_s *fingerprint_list_t;
|
||||
@ -163,6 +174,7 @@ struct server_control_s
|
||||
response. */
|
||||
|
||||
int audit_events; /* Send audit events to client. */
|
||||
uri_item_t keyservers; /* List of keyservers. */
|
||||
};
|
||||
|
||||
|
||||
|
90
dirmngr/ks-action.c
Normal file
90
dirmngr/ks-action.c
Normal file
@ -0,0 +1,90 @@
|
||||
/* ks-action.c - OpenPGP keyserver actions
|
||||
* 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 <assert.h>
|
||||
|
||||
#include "dirmngr.h"
|
||||
#include "misc.h"
|
||||
#include "ks-engine.h"
|
||||
#include "ks-action.h"
|
||||
|
||||
|
||||
/* Copy all data from IN to OUT. */
|
||||
static gpg_error_t
|
||||
copy_stream (estream_t in, estream_t out)
|
||||
{
|
||||
char buffer[512];
|
||||
size_t nread;
|
||||
|
||||
while (!es_read (in, buffer, sizeof buffer, &nread))
|
||||
{
|
||||
if (!nread)
|
||||
return 0; /* EOF */
|
||||
if (es_write (out, buffer, nread, NULL))
|
||||
break;
|
||||
|
||||
}
|
||||
return gpg_error_from_syserror ();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Search all configured keyservers for keys matching PATTERNS and
|
||||
write the result to the provided output stream. */
|
||||
gpg_error_t
|
||||
ks_action_search (ctrl_t ctrl, strlist_t patterns, estream_t outfp)
|
||||
{
|
||||
gpg_error_t err = 0;
|
||||
int any = 0;
|
||||
uri_item_t uri;
|
||||
estream_t infp;
|
||||
|
||||
if (!patterns)
|
||||
return gpg_error (GPG_ERR_NO_USER_ID);
|
||||
|
||||
/* FIXME: We only take care of the first pattern. To fully support
|
||||
multiple patterns we might either want to run several queries in
|
||||
parallel and merge them. We also need to decide what to do with
|
||||
errors - it might not be the best idea to ignore an error from
|
||||
one server and silently continue with another server. For now we
|
||||
stop at the first error. */
|
||||
for (uri = ctrl->keyservers; !err && uri; uri = uri->next)
|
||||
{
|
||||
if (uri->parsed_uri->is_http)
|
||||
{
|
||||
any = 1;
|
||||
err = ks_hkp_search (ctrl, uri->parsed_uri, patterns->d, &infp);
|
||||
if (!err)
|
||||
{
|
||||
err = copy_stream (infp, outfp);
|
||||
es_fclose (infp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!any)
|
||||
err = gpg_error (GPG_ERR_NO_KEYSERVER);
|
||||
return err;
|
||||
}
|
||||
|
26
dirmngr/ks-action.h
Normal file
26
dirmngr/ks-action.h
Normal file
@ -0,0 +1,26 @@
|
||||
/* ks-action.h - OpenPGP keyserver actions definitions
|
||||
* 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 DIRMNGR_KS_ACTION_H
|
||||
#define DIRMNGR_KS_ACTION_H 1
|
||||
|
||||
gpg_error_t ks_action_search (ctrl_t ctrl, strlist_t patterns, estream_t outfp);
|
||||
|
||||
|
||||
#endif /*DIRMNGR_KS_ACTION_H*/
|
258
dirmngr/ks-engine-hkp.c
Normal file
258
dirmngr/ks-engine-hkp.c
Normal file
@ -0,0 +1,258 @@
|
||||
/* ks-engine-hkp.c - HKP keyserver engine
|
||||
* 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 <assert.h>
|
||||
|
||||
#include "dirmngr.h"
|
||||
#include "misc.h"
|
||||
#include "userids.h"
|
||||
#include "ks-engine.h"
|
||||
|
||||
/* To match the behaviour of our old gpgkeys helper code we escape
|
||||
more characters than actually needed. */
|
||||
#define EXTRA_ESCAPE_CHARS "@!\"#$%&'()*+,-./:;<=>?[\\]^_{|}~"
|
||||
|
||||
/* How many redirections do we allow. */
|
||||
#define MAX_REDIRECTS 2
|
||||
|
||||
|
||||
/* Search the keyserver identified by URI for keys matching PATTERN.
|
||||
On success R_FP has an open stream to read the data. */
|
||||
gpg_error_t
|
||||
ks_hkp_search (ctrl_t ctrl, parsed_uri_t uri, const char *pattern,
|
||||
estream_t *r_fp)
|
||||
{
|
||||
gpg_error_t err;
|
||||
KEYDB_SEARCH_DESC desc;
|
||||
char fprbuf[2+40+1];
|
||||
const char *scheme;
|
||||
char portstr[10];
|
||||
http_t http = NULL;
|
||||
char *hostport = NULL;
|
||||
char *request = NULL;
|
||||
int redirects_left = MAX_REDIRECTS;
|
||||
estream_t fp = NULL;
|
||||
|
||||
*r_fp = NULL;
|
||||
|
||||
/* Remove search type indicator and adjust PATTERN accordingly.
|
||||
Note that HKP keyservers like the 0x to be present when searching
|
||||
by keyid. We need to re-format the fingerprint and keyids so to
|
||||
remove the gpg specific force-use-of-this-key flag ("!"). */
|
||||
err = classify_user_id (pattern, &desc);
|
||||
if (err)
|
||||
return err;
|
||||
switch (desc.mode)
|
||||
{
|
||||
case KEYDB_SEARCH_MODE_EXACT:
|
||||
case KEYDB_SEARCH_MODE_SUBSTR:
|
||||
case KEYDB_SEARCH_MODE_MAIL:
|
||||
case KEYDB_SEARCH_MODE_MAILSUB:
|
||||
pattern = desc.u.name;
|
||||
break;
|
||||
case KEYDB_SEARCH_MODE_SHORT_KID:
|
||||
snprintf (fprbuf, sizeof fprbuf, "0x%08lX", (ulong)desc.u.kid[1]);
|
||||
pattern = fprbuf;
|
||||
break;
|
||||
case KEYDB_SEARCH_MODE_LONG_KID:
|
||||
snprintf (fprbuf, sizeof fprbuf, "0x%08lX%08lX",
|
||||
(ulong)desc.u.kid[0], (ulong)desc.u.kid[1]);
|
||||
pattern = fprbuf;
|
||||
break;
|
||||
case KEYDB_SEARCH_MODE_FPR16:
|
||||
bin2hex (desc.u.fpr, 16, fprbuf);
|
||||
pattern = fprbuf;
|
||||
break;
|
||||
case KEYDB_SEARCH_MODE_FPR20:
|
||||
case KEYDB_SEARCH_MODE_FPR:
|
||||
bin2hex (desc.u.fpr, 20, fprbuf);
|
||||
pattern = fprbuf;
|
||||
break;
|
||||
default:
|
||||
return gpg_error (GPG_ERR_INV_USER_ID);
|
||||
}
|
||||
|
||||
/* Map scheme and port. */
|
||||
if (!strcmp (uri->scheme,"hkps") || !strcmp (uri->scheme,"https"))
|
||||
{
|
||||
scheme = "https";
|
||||
strcpy (portstr, "443");
|
||||
}
|
||||
else /* HKP or HTTP. */
|
||||
{
|
||||
scheme = "http";
|
||||
strcpy (portstr, "11371");
|
||||
}
|
||||
if (uri->port)
|
||||
snprintf (portstr, sizeof portstr, "%hu", uri->port);
|
||||
else
|
||||
{} /*fixme_do_srv_lookup ()*/
|
||||
|
||||
/* Build the request string. */
|
||||
{
|
||||
char *searchkey;
|
||||
|
||||
hostport = strconcat (scheme, "://",
|
||||
*uri->host? uri->host: "localhost",
|
||||
":", portstr, NULL);
|
||||
if (!hostport)
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
goto leave;
|
||||
}
|
||||
|
||||
searchkey = http_escape_string (pattern, EXTRA_ESCAPE_CHARS);
|
||||
if (!searchkey)
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
goto leave;
|
||||
}
|
||||
|
||||
request = strconcat (hostport,
|
||||
"/pks/lookup?op=index&options=mr&search=",
|
||||
searchkey,
|
||||
NULL);
|
||||
xfree (searchkey);
|
||||
if (!request)
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
goto leave;
|
||||
}
|
||||
}
|
||||
|
||||
/* Send the request. */
|
||||
once_more:
|
||||
err = http_open (&http, HTTP_REQ_GET, request,
|
||||
/* fixme: AUTH */ NULL,
|
||||
0,
|
||||
/* fixme: proxy*/ NULL,
|
||||
NULL, NULL,
|
||||
/*FIXME curl->srvtag*/NULL);
|
||||
if (!err)
|
||||
{
|
||||
fp = http_get_write_ptr (http);
|
||||
/* Avoid caches to get the most recent copy of the key. We set
|
||||
both the Pragma and Cache-Control versions of the header, so
|
||||
we're good with both HTTP 1.0 and 1.1. */
|
||||
es_fputs ("Pragma: no-cache\r\n"
|
||||
"Cache-Control: no-cache\r\n", fp);
|
||||
http_start_data (http);
|
||||
if (es_ferror (fp))
|
||||
err = gpg_error_from_syserror ();
|
||||
}
|
||||
if (err)
|
||||
{
|
||||
/* Fixme: After a redirection we show the old host name. */
|
||||
log_error (_("error connecting to `%s': %s\n"),
|
||||
hostport, gpg_strerror (err));
|
||||
goto leave;
|
||||
}
|
||||
|
||||
/* Wait for the response. */
|
||||
dirmngr_tick (ctrl);
|
||||
err = http_wait_response (http);
|
||||
if (err)
|
||||
{
|
||||
log_error (_("error reading HTTP response for `%s': %s\n"),
|
||||
hostport, gpg_strerror (err));
|
||||
goto leave;
|
||||
}
|
||||
|
||||
switch (http_get_status_code (http))
|
||||
{
|
||||
case 200:
|
||||
break; /* Success. */
|
||||
|
||||
case 301:
|
||||
case 302:
|
||||
{
|
||||
const char *s = http_get_header (http, "Location");
|
||||
|
||||
log_info (_("URL `%s' redirected to `%s' (%u)\n"),
|
||||
request, s?s:"[none]", http_get_status_code (http));
|
||||
if (s && *s && redirects_left-- )
|
||||
{
|
||||
xfree (request);
|
||||
request = xtrystrdup (s);
|
||||
if (request)
|
||||
{
|
||||
http_close (http, 0);
|
||||
http = NULL;
|
||||
goto once_more;
|
||||
}
|
||||
err = gpg_error_from_syserror ();
|
||||
}
|
||||
else
|
||||
err = gpg_error (GPG_ERR_NO_DATA);
|
||||
log_error (_("too many redirections\n"));
|
||||
}
|
||||
goto leave;
|
||||
|
||||
default:
|
||||
log_error (_("error accessing `%s': http status %u\n"),
|
||||
request, http_get_status_code (http));
|
||||
err = gpg_error (GPG_ERR_NO_DATA);
|
||||
goto leave;
|
||||
}
|
||||
|
||||
/* Start reading the response. */
|
||||
fp = http_get_read_ptr (http);
|
||||
if (!fp)
|
||||
{
|
||||
err = gpg_error (GPG_ERR_BUG);
|
||||
goto leave;
|
||||
}
|
||||
{
|
||||
int c = es_getc (fp);
|
||||
if (c == -1)
|
||||
{
|
||||
err = es_ferror (fp)?gpg_error_from_syserror ():gpg_error (GPG_ERR_EOF);
|
||||
log_error ("error reading response: %s\n", gpg_strerror (err));
|
||||
goto leave;
|
||||
}
|
||||
if (c == '<')
|
||||
{
|
||||
/* The document begins with a '<', assume it's a HTML
|
||||
response, which we don't support. */
|
||||
err = gpg_error (GPG_ERR_UNSUPPORTED_ENCODING);
|
||||
goto leave;
|
||||
}
|
||||
es_ungetc (c, fp);
|
||||
}
|
||||
|
||||
/* Return the read stream and close the HTTP context. */
|
||||
*r_fp = fp;
|
||||
fp = NULL;
|
||||
http_close (http, 1);
|
||||
http = NULL;
|
||||
|
||||
leave:
|
||||
es_fclose (fp);
|
||||
http_close (http, 0);
|
||||
xfree (request);
|
||||
xfree (hostport);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
32
dirmngr/ks-engine.h
Normal file
32
dirmngr/ks-engine.h
Normal file
@ -0,0 +1,32 @@
|
||||
/* ks-engine.h - Keyserver engines definitions
|
||||
* 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 DIRMNGR_KS_ENGINE_H
|
||||
#define DIRMNGR_KS_ENGINE_H 1
|
||||
|
||||
#include "../common/estream.h"
|
||||
#include "../common/http.h"
|
||||
|
||||
/*-- ks-engine-hkp.c --*/
|
||||
gpg_error_t ks_hkp_search (ctrl_t ctrl, parsed_uri_t uri, const char *pattern,
|
||||
estream_t *r_fp);
|
||||
|
||||
|
||||
|
||||
#endif /*DIRMNGR_KS_ENGINE_H*/
|
153
dirmngr/server.c
153
dirmngr/server.c
@ -1,6 +1,6 @@
|
||||
/* dirmngr.c - LDAP access
|
||||
* Copyright (C) 2002 Klarälvdalens Datakonsult AB
|
||||
* Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009 g10 Code GmbH
|
||||
* Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009, 2011 g10 Code GmbH
|
||||
*
|
||||
* This file is part of DirMngr.
|
||||
*
|
||||
@ -41,6 +41,7 @@
|
||||
#include "validate.h"
|
||||
#include "misc.h"
|
||||
#include "ldap-wrapper.h"
|
||||
#include "ks-action.h"
|
||||
|
||||
/* To avoid DoS attacks we limit the size of a certificate to
|
||||
something reasonable. */
|
||||
@ -58,7 +59,7 @@ struct server_local_s
|
||||
/* Data used to associate an Assuan context with local server data */
|
||||
assuan_context_t assuan_ctx;
|
||||
|
||||
/* Per-session LDAP serfver. */
|
||||
/* Per-session LDAP servers. */
|
||||
ldap_server_t ldapservers;
|
||||
|
||||
/* If this flag is set to true this dirmngr process will be
|
||||
@ -94,6 +95,21 @@ get_ldapservers_from_ctrl (ctrl_t ctrl)
|
||||
}
|
||||
|
||||
|
||||
/* Release all configured keyserver info from CTRL. */
|
||||
void
|
||||
release_ctrl_keyservers (ctrl_t ctrl)
|
||||
{
|
||||
while (ctrl->keyservers)
|
||||
{
|
||||
uri_item_t tmp = ctrl->keyservers->next;
|
||||
http_release_parsed_uri (ctrl->keyservers->parsed_uri);
|
||||
xfree (ctrl->keyservers);
|
||||
ctrl->keyservers = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Helper to print a message while leaving a command. */
|
||||
static gpg_error_t
|
||||
leave_cmd (assuan_context_t ctx, gpg_error_t err)
|
||||
@ -147,7 +163,7 @@ data_line_cookie_close (void *cookie)
|
||||
/* Copy the % and + escaped string S into the buffer D and replace the
|
||||
escape sequences. Note, that it is sufficient to allocate the
|
||||
target string D as long as the source string S, i.e.: strlen(s)+1.
|
||||
NOte further that If S contains an escaped binary nul the resulting
|
||||
Note further that if S contains an escaped binary Nul the resulting
|
||||
string D will contain the 0 as well as all other characters but it
|
||||
will be impossible to know whether this is the original EOS or a
|
||||
copied Nul. */
|
||||
@ -1335,6 +1351,130 @@ cmd_validate (assuan_context_t ctx, char *line)
|
||||
return leave_cmd (ctx, err);
|
||||
}
|
||||
|
||||
|
||||
static const char hlp_keyserver[] =
|
||||
"KEYSERVER [--clear] [<uri>]\n"
|
||||
"\n"
|
||||
"If called without arguments list all configured keyserver URLs.\n"
|
||||
"If called with option \"--clear\" remove all configured keyservers\n"
|
||||
"If called with an URI add this as keyserver. Note that keyservers\n"
|
||||
"are configured on a per-session base. A default keyserver may already be\n"
|
||||
"present, thus the \"--clear\" option must be used to get full control.\n"
|
||||
"If \"--clear\" and an URI are used together the clear command is\n"
|
||||
"obviously executed first. A RESET command does not change the list\n"
|
||||
"of configured keyservers.";
|
||||
static gpg_error_t
|
||||
cmd_keyserver (assuan_context_t ctx, char *line)
|
||||
{
|
||||
ctrl_t ctrl = assuan_get_pointer (ctx);
|
||||
gpg_error_t err;
|
||||
int clear_flag, add_flag;
|
||||
uri_item_t item = NULL; /* gcc 4.4.5 is not able to detect that it
|
||||
is always initialized. */
|
||||
|
||||
clear_flag = has_option (line, "--clear");
|
||||
line = skip_options (line);
|
||||
add_flag = !!*line;
|
||||
|
||||
if (add_flag)
|
||||
{
|
||||
item = xtrymalloc (sizeof *item + strlen (line));
|
||||
if (!item)
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
goto leave;
|
||||
}
|
||||
item->next = NULL;
|
||||
item->parsed_uri = NULL;
|
||||
strcpy (item->uri, line);
|
||||
|
||||
err = http_parse_uri (&item->parsed_uri, line, 1);
|
||||
if (err)
|
||||
{
|
||||
xfree (item);
|
||||
goto leave;
|
||||
}
|
||||
}
|
||||
if (clear_flag)
|
||||
release_ctrl_keyservers (ctrl);
|
||||
if (add_flag)
|
||||
{
|
||||
item->next = ctrl->keyservers;
|
||||
ctrl->keyservers = item;
|
||||
}
|
||||
|
||||
if (!add_flag && !clear_flag) /* List configured keyservers. */
|
||||
{
|
||||
uri_item_t u;
|
||||
|
||||
for (u=ctrl->keyservers; u; u = u->next)
|
||||
dirmngr_status (ctrl, "KEYSERVER", u->uri, NULL);
|
||||
}
|
||||
err = 0;
|
||||
|
||||
leave:
|
||||
return leave_cmd (ctx, err);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static const char hlp_ks_search[] =
|
||||
"KS_SEARCH {<pattern>}\n"
|
||||
"\n"
|
||||
"Search the configured OpenPGP keyservers (see command KEYSERVER)\n"
|
||||
"for keys matching PATTERN";
|
||||
static gpg_error_t
|
||||
cmd_ks_search (assuan_context_t ctx, char *line)
|
||||
{
|
||||
ctrl_t ctrl = assuan_get_pointer (ctx);
|
||||
gpg_error_t err;
|
||||
strlist_t list, sl;
|
||||
char *p;
|
||||
estream_t outfp;
|
||||
|
||||
/* No options for now. */
|
||||
line = skip_options (line);
|
||||
|
||||
/* Break the line down into an strlist. Each pattern is
|
||||
percent-plus escaped. */
|
||||
list = NULL;
|
||||
for (p=line; *p; line = p)
|
||||
{
|
||||
while (*p && *p != ' ')
|
||||
p++;
|
||||
if (*p)
|
||||
*p++ = 0;
|
||||
if (*line)
|
||||
{
|
||||
sl = xtrymalloc (sizeof *sl + strlen (line));
|
||||
if (!sl)
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
free_strlist (list);
|
||||
goto leave;
|
||||
}
|
||||
sl->flags = 0;
|
||||
strcpy_escaped_plus (sl->d, line);
|
||||
sl->next = list;
|
||||
list = sl;
|
||||
}
|
||||
}
|
||||
|
||||
/* Setup an output stream and perform the search. */
|
||||
outfp = es_fopencookie (ctx, "w", data_line_cookie_functions);
|
||||
if (!outfp)
|
||||
err = set_error (GPG_ERR_ASS_GENERAL, "error setting up a data stream");
|
||||
else
|
||||
{
|
||||
err = ks_action_search (ctrl, list, outfp);
|
||||
es_fclose (outfp);
|
||||
}
|
||||
|
||||
leave:
|
||||
return leave_cmd (ctx, err);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static const char hlp_getinfo[] =
|
||||
@ -1469,6 +1609,8 @@ register_commands (assuan_context_t ctx)
|
||||
{ "LISTCRLS", cmd_listcrls, hlp_listcrls },
|
||||
{ "CACHECERT", cmd_cachecert, hlp_cachecert },
|
||||
{ "VALIDATE", cmd_validate, hlp_validate },
|
||||
{ "KEYSERVER", cmd_keyserver, hlp_keyserver },
|
||||
{ "KS_SEARCH", cmd_ks_search, hlp_ks_search },
|
||||
{ "GETINFO", cmd_getinfo, hlp_getinfo },
|
||||
{ "KILLDIRMNGR",cmd_killdirmngr,hlp_killdirmngr },
|
||||
{ "RELOADDIRMNGR",cmd_reloaddirmngr,hlp_reloaddirmngr },
|
||||
@ -1487,6 +1629,7 @@ register_commands (assuan_context_t ctx)
|
||||
}
|
||||
|
||||
|
||||
/* Note that we do not reset the list of configured keyservers. */
|
||||
static gpg_error_t
|
||||
reset_notify (assuan_context_t ctx, char *line)
|
||||
{
|
||||
@ -1681,8 +1824,8 @@ dirmngr_status (ctrl_t ctrl, const char *keyword, ...)
|
||||
}
|
||||
|
||||
|
||||
/* Note, that we ignore CTRL for now but use the first connection to
|
||||
send the progress info back. */
|
||||
/* Send a tick progress indicator back. Fixme: This is only does for
|
||||
the currently active channel. */
|
||||
gpg_error_t
|
||||
dirmngr_tick (ctrl_t ctrl)
|
||||
{
|
||||
|
@ -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.
|
||||
|
@ -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
256
g10/call-dirmngr.c
Normal 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
26
g10/call-dirmngr.h
Normal 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*/
|
35
g10/gpg.c
35
g10/gpg.c
@ -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;
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
@ -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);
|
||||
|
123
g10/keyserver.c
123
g10/keyserver.c
@ -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)
|
||||
{
|
||||
|
@ -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;
|
||||
|
||||
|
@ -687,7 +687,7 @@ main(int argc,char *argv[])
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if(ks_strcasecmp(opt->scheme,"hkps")==0)
|
||||
if(ascii_strcasecmp(opt->scheme,"hkps")==0)
|
||||
{
|
||||
proto="https";
|
||||
port="443";
|
||||
|
Loading…
x
Reference in New Issue
Block a user