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

8
.gitignore vendored Normal file
View 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

View File

@ -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

View File

@ -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;
}

View File

@ -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);

View File

@ -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*/

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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)
{

View File

@ -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
View 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
View 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
View 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
View 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*/

View File

@ -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)
{

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;

View File

@ -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";