aboutsummaryrefslogtreecommitdiffstats
path: root/g10
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2015-04-23 13:42:56 +0000
committerWerner Koch <[email protected]>2015-04-23 13:52:39 +0000
commit154f3ed2bf64de801ae0f9796338a2767ec6357b (patch)
tree064311a8189256ab5b8354409fb53e5a1ffa2b43 /g10
parentcommon: Minor change of hex2str to allow for embedded nul. (diff)
downloadgnupg-154f3ed2bf64de801ae0f9796338a2767ec6357b.tar.gz
gnupg-154f3ed2bf64de801ae0f9796338a2767ec6357b.zip
gpg: Move all DNS access to Dirmngr.
* common/dns-cert.h: Move to ../dirmngr/. * common/dns-cert.c: Move to ../dirmngr/. Change args to return the key as a buffer. * common/t-dns-cert.c: Move to ../dirmngr/. * common/pka.c, common/pka.h, common/t-pka.c: Remove. * dirmngr/server.c (data_line_cookie_write): Factor code out to data_line_write and make it a wrapper for that. (data_line_write): New. (cmd_dns_cert): New. (register_commands): Register new command. * g10/Makefile.am (LDADD): Remove DNSLIBS. * g10/call-dirmngr.c (dns_cert_parm_s): New. (dns_cert_data_cb, dns_cert_status_cb): New. (gpg_dirmngr_dns_cert): New. (gpg_dirmngr_get_pka): New. * g10/gpgv.c (gpg_dirmngr_get_pka): New dummy function. * g10/keyserver.c (keyserver_import_cert): Replace get_dns_cert by gpg_dirmngr_dns_cert. (keyserver_import_pka): Replace get_pka_info by gpg_dirmngr_get_pka. * g10/mainproc.c: Include call-dirmngr.h. (pka_uri_from_sig): Add CTX arg. Replace get_pka_info by gpg_dirmngr_get_pka. -- With this patch gpg does not do any network access itself but uses dirmngr for that. Note that we need to keep linking to NETLIBS due to the logging code and because we need TCP for our socket emulation under Windows. Probably also required for Solaris etc. Signed-off-by: Werner Koch <[email protected]>
Diffstat (limited to 'g10')
-rw-r--r--g10/Makefile.am3
-rw-r--r--g10/call-dirmngr.c235
-rw-r--r--g10/call-dirmngr.h8
-rw-r--r--g10/gpgv.c16
-rw-r--r--g10/keyserver-internal.h4
-rw-r--r--g10/keyserver.c34
-rw-r--r--g10/mainproc.c38
7 files changed, 301 insertions, 37 deletions
diff --git a/g10/Makefile.am b/g10/Makefile.am
index b66abb84c..ca99314b7 100644
--- a/g10/Makefile.am
+++ b/g10/Makefile.am
@@ -141,8 +141,7 @@ gpgv2_SOURCES = gpgv.c \
# here, even that it is not used by gpg. A proper solution would
# either to split up libkeybox.a or to use a separate keybox daemon.
LDADD = $(needed_libs) ../common/libgpgrl.a \
- $(ZLIBS) $(DNSLIBS) \
- $(LIBINTL) $(CAPLIBS) $(NETLIBS)
+ $(ZLIBS) $(LIBINTL) $(CAPLIBS) $(NETLIBS)
gpg2_LDADD = $(LDADD) $(LIBGCRYPT_LIBS) $(LIBREADLINE) \
$(KSBA_LIBS) $(LIBASSUAN_LIBS) $(GPG_ERROR_LIBS) \
$(LIBICONV) $(resource_objs) $(extra_sys_libs)
diff --git a/g10/call-dirmngr.c b/g10/call-dirmngr.c
index bb571b2e9..e452c971e 100644
--- a/g10/call-dirmngr.c
+++ b/g10/call-dirmngr.c
@@ -78,6 +78,16 @@ struct ks_put_parm_s
};
+/* Parameter structure used with the DNS_CERT command. */
+struct dns_cert_parm_s
+{
+ estream_t memfp;
+ unsigned char *fpr;
+ size_t fprlen;
+ char *url;
+};
+
+
/* Data used to associate an session with dirmngr contexts. We can't
use a simple one to one mapping because we sometimes need two
connections to the dirmngr; for example while doing a listing and
@@ -957,3 +967,228 @@ gpg_dirmngr_ks_put (ctrl_t ctrl, void *data, size_t datalen, kbnode_t keyblock)
close_context (ctrl, ctx);
return err;
}
+
+
+
+/* Data callback for the DNS_CERT command. */
+static gpg_error_t
+dns_cert_data_cb (void *opaque, const void *data, size_t datalen)
+{
+ struct dns_cert_parm_s *parm = opaque;
+ gpg_error_t err = 0;
+ size_t nwritten;
+
+ if (!data)
+ return 0; /* Ignore END commands. */
+ if (!parm->memfp)
+ return 0; /* Data is not required. */
+
+ if (es_write (parm->memfp, data, datalen, &nwritten))
+ err = gpg_error_from_syserror ();
+
+ return err;
+}
+
+
+/* Status callback for the DNS_CERT command. */
+static gpg_error_t
+dns_cert_status_cb (void *opaque, const char *line)
+{
+ struct dns_cert_parm_s *parm = opaque;
+ gpg_error_t err = 0;
+ const char *s;
+ size_t nbytes;
+
+ if ((s = has_leading_keyword (line, "FPR")))
+ {
+ char *buf;
+
+ if (!(buf = xtrystrdup (s)))
+ err = gpg_error_from_syserror ();
+ else if (parm->fpr)
+ err = gpg_error (GPG_ERR_DUP_KEY);
+ else if (!hex2str (buf, buf, strlen (buf)+1, &nbytes))
+ err = gpg_error_from_syserror ();
+ else if (nbytes < 20)
+ err = gpg_error (GPG_ERR_TOO_SHORT);
+ else
+ {
+ parm->fpr = xtrymalloc (nbytes);
+ if (!parm->fpr)
+ err = gpg_error_from_syserror ();
+ else
+ memcpy (parm->fpr, buf, (parm->fprlen = nbytes));
+ }
+ xfree (buf);
+ }
+ else if ((s = has_leading_keyword (line, "URL")) && *s)
+ {
+ if (parm->url)
+ err = gpg_error (GPG_ERR_DUP_KEY);
+ else if (!(parm->fpr = xtrymalloc (nbytes)))
+ err = gpg_error_from_syserror ();
+ else
+ memcpy (parm->fpr, line, (parm->fprlen = nbytes));
+ }
+
+ return err;
+}
+
+/* Ask the dirmngr for a DNS CERT record. Depending on the found
+ subtypes different return values are set:
+
+ - For a PGP subtype a new estream with that key will be returned at
+ R_KEY and the other return parameters are set to NULL/0.
+
+ - For an IPGP subtype the fingerprint is stored as a malloced block
+ at (R_FPR,R_FPRLEN). If an URL is available it is stored as a
+ malloced string at R_URL; NULL is stored if there is no URL.
+
+ If CERTTYPE is DNS_CERTTYPE_ANY this function returns the first
+ CERT record found with a supported type; it is expected that only
+ one CERT record is used. If CERTTYPE is one of the supported
+ certtypes, only records with this certtype are considered and the
+ first one found is returned. All R_* args are optional. */
+gpg_error_t
+gpg_dirmngr_dns_cert (ctrl_t ctrl, const char *name, const char *certtype,
+ estream_t *r_key,
+ unsigned char **r_fpr, size_t *r_fprlen,
+ char **r_url)
+{
+ gpg_error_t err;
+ assuan_context_t ctx;
+ struct dns_cert_parm_s parm;
+ char *line = NULL;
+
+ memset (&parm, 0, sizeof parm);
+ if (r_key)
+ *r_key = NULL;
+ if (r_fpr)
+ *r_fpr = NULL;
+ if (r_fprlen)
+ *r_fprlen = 0;
+ if (r_url)
+ *r_url = NULL;
+
+ err = open_context (ctrl, &ctx);
+ if (err)
+ return err;
+
+ line = es_bsprintf ("DNS_CERT %s %s", certtype, name);
+ if (!line)
+ {
+ err = gpg_error_from_syserror ();
+ goto leave;
+ }
+ if (strlen (line) + 2 >= ASSUAN_LINELENGTH)
+ {
+ err = gpg_error (GPG_ERR_TOO_LARGE);
+ goto leave;
+ }
+
+ parm.memfp = es_fopenmem (0, "rwb");
+ if (!parm.memfp)
+ {
+ err = gpg_error_from_syserror ();
+ goto leave;
+ }
+ err = assuan_transact (ctx, line, dns_cert_data_cb, &parm,
+ NULL, NULL, dns_cert_status_cb, &parm);
+ if (err)
+ goto leave;
+
+ if (r_key)
+ {
+ es_rewind (parm.memfp);
+ *r_key = parm.memfp;
+ parm.memfp = NULL;
+ }
+
+ if (r_fpr && parm.fpr)
+ {
+ *r_fpr = parm.fpr;
+ parm.fpr = NULL;
+ }
+ if (r_fprlen)
+ *r_fprlen = parm.fprlen;
+
+ if (r_url && parm.url)
+ {
+ *r_url = parm.url;
+ parm.url = NULL;
+ }
+
+ leave:
+ xfree (parm.fpr);
+ xfree (parm.url);
+ es_fclose (parm.memfp);
+ xfree (line);
+ close_context (ctrl, ctx);
+ return err;
+}
+
+
+/* Ask the dirmngr for PKA info. On success the retrieved fingerprint
+ is returned in a malloced buffer at R_FPR and its length is stored
+ at R_FPRLEN. If an URL is available it is stored as a malloced
+ string at R_URL. On error all return values are set to NULL/0. */
+gpg_error_t
+gpg_dirmngr_get_pka (ctrl_t ctrl, const char *userid,
+ unsigned char **r_fpr, size_t *r_fprlen,
+ char **r_url)
+{
+ gpg_error_t err;
+ assuan_context_t ctx;
+ struct dns_cert_parm_s parm;
+ char *line = NULL;
+
+ memset (&parm, 0, sizeof parm);
+ if (r_fpr)
+ *r_fpr = NULL;
+ if (r_fprlen)
+ *r_fprlen = 0;
+ if (r_url)
+ *r_url = NULL;
+
+ err = open_context (ctrl, &ctx);
+ if (err)
+ return err;
+
+ line = es_bsprintf ("DNS_CERT --pka -- %s", userid);
+ if (!line)
+ {
+ err = gpg_error_from_syserror ();
+ goto leave;
+ }
+ if (strlen (line) + 2 >= ASSUAN_LINELENGTH)
+ {
+ err = gpg_error (GPG_ERR_TOO_LARGE);
+ goto leave;
+ }
+
+ err = assuan_transact (ctx, line, dns_cert_data_cb, &parm,
+ NULL, NULL, dns_cert_status_cb, &parm);
+ if (err)
+ goto leave;
+
+ if (r_fpr && parm.fpr)
+ {
+ *r_fpr = parm.fpr;
+ parm.fpr = NULL;
+ }
+ if (r_fprlen)
+ *r_fprlen = parm.fprlen;
+
+ if (r_url && parm.url)
+ {
+ *r_url = parm.url;
+ parm.url = NULL;
+ }
+
+ leave:
+ xfree (parm.fpr);
+ xfree (parm.url);
+ xfree (line);
+ close_context (ctrl, ctx);
+ return err;
+}
diff --git a/g10/call-dirmngr.h b/g10/call-dirmngr.h
index bae11238c..b9b8e21a3 100644
--- a/g10/call-dirmngr.h
+++ b/g10/call-dirmngr.h
@@ -31,6 +31,14 @@ gpg_error_t gpg_dirmngr_ks_fetch (ctrl_t ctrl,
const char *url, estream_t *r_fp);
gpg_error_t gpg_dirmngr_ks_put (ctrl_t ctrl, void *data, size_t datalen,
kbnode_t keyblock);
+gpg_error_t gpg_dirmngr_dns_cert (ctrl_t ctrl,
+ const char *name, const char *certtype,
+ estream_t *r_key,
+ unsigned char **r_fpr, size_t *r_fprlen,
+ char **r_url);
+gpg_error_t gpg_dirmngr_get_pka (ctrl_t ctrl, const char *userid,
+ unsigned char **r_fpr, size_t *r_fprlen,
+ char **r_url);
#endif /*GNUPG_G10_CALL_DIRMNGR_H*/
diff --git a/g10/gpgv.c b/g10/gpgv.c
index 157fdea45..479bb9599 100644
--- a/g10/gpgv.c
+++ b/g10/gpgv.c
@@ -575,3 +575,19 @@ agent_get_keyinfo (ctrl_t ctrl, const char *hexkeygrip, char **r_serialno)
*r_serialno = NULL;
return gpg_error (GPG_ERR_NO_SECKEY);
}
+
+gpg_error_t
+gpg_dirmngr_get_pka (ctrl_t ctrl, const char *userid,
+ unsigned char **r_fpr, size_t *r_fprlen,
+ char **r_url)
+{
+ (void)ctrl;
+ (void)userid;
+ if (r_fpr)
+ *r_fpr = NULL;
+ if (r_fprlen)
+ *r_fprlen = 0;
+ if (r_url)
+ *r_url = NULL;
+ return gpg_error (GPG_ERR_NOT_FOUND);
+}
diff --git a/g10/keyserver-internal.h b/g10/keyserver-internal.h
index a955fc7da..fc1c3435d 100644
--- a/g10/keyserver-internal.h
+++ b/g10/keyserver-internal.h
@@ -42,8 +42,8 @@ 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);
-int keyserver_import_pka (ctrl_t ctrl,
- const char *name,unsigned char **fpr,size_t *fpr_len);
+gpg_error_t keyserver_import_pka (ctrl_t ctrl, const char *name,
+ unsigned char **fpr,size_t *fpr_len);
int keyserver_import_name (ctrl_t ctrl,
const char *name,unsigned char **fpr,size_t *fpr_len,
struct keyserver_spec *keyserver);
diff --git a/g10/keyserver.c b/g10/keyserver.c
index abe4bdebf..40ba49a61 100644
--- a/g10/keyserver.c
+++ b/g10/keyserver.c
@@ -41,8 +41,6 @@
#include "trustdb.h"
#include "keyserver-internal.h"
#include "util.h"
-#include "dns-cert.h"
-#include "pka.h"
#ifdef USE_DNS_SRV
#include "srv.h"
#endif
@@ -1897,7 +1895,7 @@ keyserver_import_cert (ctrl_t ctrl,
if(domain)
*domain='.';
- err = get_dns_cert (look, DNS_CERTTYPE_ANY, &key, fpr, fpr_len, &url);
+ err = gpg_dirmngr_dns_cert (ctrl, look, "*", &key, fpr, fpr_len, &url);
if (err)
;
else if (key)
@@ -1957,37 +1955,35 @@ keyserver_import_cert (ctrl_t ctrl,
/* Import key pointed to by a PKA record. Return the requested
fingerprint in fpr. */
-int
-keyserver_import_pka (ctrl_t ctrl,
- const char *name,unsigned char **fpr,size_t *fpr_len)
+gpg_error_t
+keyserver_import_pka (ctrl_t ctrl, const char *name,
+ unsigned char **fpr, size_t *fpr_len)
{
- char *uri;
- int rc = GPG_ERR_NO_PUBKEY;
-
- *fpr = xmalloc (20);
- *fpr_len = 20;
+ gpg_error_t err;
+ char *url;
- uri = get_pka_info (name, *fpr, 20);
- if (uri && *uri)
+ err = gpg_dirmngr_get_pka (ctrl, name, fpr, fpr_len, &url);
+ if (url && *url && fpr && fpr_len)
{
- /* An URI is available. Lookup the key. */
+ /* An URL is available. Lookup the key. */
struct keyserver_spec *spec;
- spec = parse_keyserver_uri (uri, 1);
+ spec = parse_keyserver_uri (url, 1);
if (spec)
{
- rc = keyserver_import_fprint (ctrl, *fpr, 20, spec);
+ err = keyserver_import_fprint (ctrl, *fpr, *fpr_len, spec);
free_keyserver_spec (spec);
}
}
- xfree (uri);
+ xfree (url);
- if (rc)
+ if (err)
{
xfree(*fpr);
*fpr = NULL;
+ *fpr_len = 0;
}
- return rc;
+ return err;
}
diff --git a/g10/mainproc.c b/g10/mainproc.c
index 0f6ba2b32..e72d07640 100644
--- a/g10/mainproc.c
+++ b/g10/mainproc.c
@@ -38,9 +38,8 @@
#include "trustdb.h"
#include "keyserver-internal.h"
#include "photoid.h"
-#include "pka.h"
#include "mbox-util.h"
-
+#include "call-dirmngr.h"
/* Put an upper limit on nested packets. The 32 is an arbitrary
value, a much lower should actually be sufficient. */
@@ -1487,7 +1486,7 @@ get_pka_address (PKT_signature *sig)
be retrieved for the signature we merely return it; if not we go
out and try to get that DNS record. */
static const char *
-pka_uri_from_sig (PKT_signature *sig)
+pka_uri_from_sig (CTX c, PKT_signature *sig)
{
if (!sig->flags.pka_tried)
{
@@ -1496,17 +1495,28 @@ pka_uri_from_sig (PKT_signature *sig)
sig->pka_info = get_pka_address (sig);
if (sig->pka_info)
{
- char *uri;
+ char *url;
+ unsigned char *fpr;
+ size_t fprlen;
- uri = get_pka_info (sig->pka_info->email,
- sig->pka_info->fpr, sizeof sig->pka_info->fpr);
- if (uri)
+ if (!gpg_dirmngr_get_pka (c->ctrl, sig->pka_info->email,
+ &fpr, &fprlen, &url))
{
- sig->pka_info->valid = 1;
- if (!*uri)
- xfree (uri);
- else
- sig->pka_info->uri = uri;
+ if (fpr && fprlen == sizeof sig->pka_info->fpr)
+ {
+ memcpy (sig->pka_info->fpr, fpr, fprlen);
+ if (url)
+ {
+ sig->pka_info->valid = 1;
+ if (!*url)
+ xfree (url);
+ else
+ sig->pka_info->uri = url;
+ url = NULL;
+ }
+ }
+ xfree (fpr);
+ xfree (url);
}
}
}
@@ -1734,7 +1744,7 @@ check_sig_and_print (CTX c, kbnode_t node)
&& (opt.keyserver_options.options & KEYSERVER_AUTO_KEY_RETRIEVE)
&& (opt.keyserver_options.options & KEYSERVER_HONOR_PKA_RECORD))
{
- const char *uri = pka_uri_from_sig (sig);
+ const char *uri = pka_uri_from_sig (c, sig);
if (uri)
{
@@ -1997,7 +2007,7 @@ check_sig_and_print (CTX c, kbnode_t node)
if (!rc)
{
if ((opt.verify_options & VERIFY_PKA_LOOKUPS))
- pka_uri_from_sig (sig); /* Make sure PKA info is available. */
+ pka_uri_from_sig (c, sig); /* Make sure PKA info is available. */
rc = check_signatures_trust (sig);
}