* call-dirmngr.c: New.

* certpath.c (gpgsm_validate_path): Check the CRL here.
* fingerprint.c (gpgsm_get_certid): New.
* gpgsm.c: New options --dirmngr-program and --disable-crl-checks.
This commit is contained in:
Werner Koch 2002-01-11 17:07:51 +00:00
parent 98b2622ef0
commit 6af7631e54
9 changed files with 343 additions and 13 deletions

View File

@ -1,3 +1,10 @@
2002-01-11 Werner Koch <wk@gnupg.org>
* call-dirmngr.c: New.
* certpath.c (gpgsm_validate_path): Check the CRL here.
* fingerprint.c (gpgsm_get_certid): New.
* gpgsm.c: New options --dirmngr-program and --disable-crl-checks.
2002-01-10 Werner Koch <wk@gnupg.org>
* base64.c (gpgsm_create_writer): Allow to set the object name

View File

@ -30,6 +30,7 @@ gpgsm_SOURCES = \
keydb.c keydb.h \
server.c \
call-agent.c \
call-dirmngr.c \
fingerprint.c \
base64.c \
certlist.c \

View File

@ -1,5 +1,5 @@
/* call-agent.c - divert operations to the agent
* Copyright (C) 2001 Free Software Foundation, Inc.
* Copyright (C) 2001, 2002 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -33,16 +33,6 @@
#include "../assuan/assuan.h"
#include "i18n.h"
#ifdef _POSIX_OPEN_MAX
#define MAX_OPEN_FDS _POSIX_OPEN_MAX
#else
#define MAX_OPEN_FDS 20
#endif
#define xtoi_1(p) (*(p) <= '9'? (*(p)- '0'): \
*(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10))
#define xtoi_2(p) ((xtoi_1(p) * 16) + xtoi_1((p)+1))
static ASSUAN_CONTEXT agent_ctx = NULL;

182
sm/call-dirmngr.c Normal file
View File

@ -0,0 +1,182 @@
/* call-dirmngr.c - communication with the dromngr
* Copyright (C) 2002 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
* GnuPG is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* GnuPG is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <time.h>
#include <assert.h>
#include <gcrypt.h>
#include "gpgsm.h"
#include "../assuan/assuan.h"
#include "i18n.h"
static ASSUAN_CONTEXT dirmngr_ctx = NULL;
struct cipher_parm_s {
ASSUAN_CONTEXT ctx;
const char *ciphertext;
size_t ciphertextlen;
};
struct genkey_parm_s {
ASSUAN_CONTEXT ctx;
const char *sexp;
size_t sexplen;
};
struct membuf {
size_t len;
size_t size;
char *buf;
int out_of_core;
};
/* Try to connect to the agent via socket or fork it off and work by
pipes. Handle the server's initial greeting */
static int
start_dirmngr (void)
{
int rc;
char *infostr, *p;
if (dirmngr_ctx)
return 0; /* fixme: We need a context for each thread or serialize
the access to the agent (which is suitable given that
the agent is not MT */
infostr = getenv ("DIRMNGR_INFO");
if (!infostr)
{
const char *pgmname;
ASSUAN_CONTEXT ctx;
const char *argv[3];
log_info (_("no running dirmngr - starting one\n"));
if (fflush (NULL))
{
log_error ("error flushing pending output: %s\n", strerror (errno));
return seterr (Write_Error);
}
if (!opt.dirmngr_program || !*opt.dirmngr_program)
opt.dirmngr_program = "/usr/sbin/dirmngr";
if ( !(pgmname = strrchr (opt.dirmngr_program, '/')))
pgmname = opt.dirmngr_program;
else
pgmname++;
argv[0] = pgmname;
argv[1] = "--server";
argv[2] = NULL;
/* connect to the agent and perform initial handshaking */
rc = assuan_pipe_connect (&ctx, opt.dirmngr_program, (char**)argv, 0);
if (rc)
{
log_error ("can't connect to the dirmngr: %s\n", assuan_strerror (rc));
return seterr (No_Dirmngr);
}
dirmngr_ctx = ctx;
}
else
{
infostr = xstrdup (infostr);
if ( !(p = strchr (infostr, ':')) || p == infostr
/* || (p-infostr)+1 >= sizeof client_addr.sun_path */)
{
log_error (_("malformed DIRMNGR_INFO environment variable\n"));
xfree (infostr);
return seterr (General_Error);
}
*p = 0;
log_error (_("socket based dirmngr communication not yet implemented\n"));
return seterr (Not_Implemented);
}
log_debug ("connection to dirmngr established\n");
return 0;
}
/* Handle a SENDCERT inquiry. */
static AssuanError
inq_certificate (void *opaque, const char *line)
{
AssuanError rc;
if (strncmp (line, "SENDCERT ", 9) || !line[9])
{
log_error ("unsupported inquiry `%s'\n", line);
return ASSUAN_Inquire_Unknown;
}
/* rc = assuan_send_data (parm->ctx, parm->sexp, parm->sexplen);*/
rc = 0;
return rc;
}
/* Call the directory manager to check whether the certificate is valid
Returns 0 for valid or usually one of the errors:
GNUPG_Certificate_Revoked
GNUPG_No_CRL_Known
GNUPG_CRL_Too_Old
*/
int
gpgsm_dirmngr_isvalid (KsbaCert cert)
{
int rc;
char *certid;
char line[ASSUAN_LINELENGTH];
rc = start_dirmngr ();
if (rc)
return rc;
certid = gpgsm_get_certid (cert);
if (!certid)
{
log_error ("error getting the certificate ID\n");
return seterr (General_Error);
}
snprintf (line, DIM(line)-1, "ISVALID %s", certid);
line[DIM(line)-1] = 0;
xfree (certid);
rc = assuan_transact (dirmngr_ctx, line, NULL, NULL, inq_certificate, NULL);
return map_assuan_err (rc);
}

View File

@ -69,6 +69,33 @@ gpgsm_validate_path (KsbaCert cert)
goto leave;
}
if (!opt.no_crl_check)
{
rc = gpgsm_dirmngr_isvalid (subject_cert);
if (rc)
{
switch (rc)
{
case GNUPG_Certificate_Revoked:
log_error (_("the certificate has been revoked\n"));
break;
case GNUPG_No_CRL_Known:
log_error (_("no CRL found for certificate\n"));
break;
case GNUPG_CRL_Too_Old:
log_error (_("the available CRL is too old\n"));
log_info (_("please make sure that the "
"\"dirmngr\" is properly installed\n"));
break;
default:
log_error (_("checking the CRL failed: %s\n"),
gnupg_strerror (rc));
break;
}
goto leave;
}
}
if (subject && !strcmp (issuer, subject))
{
if (gpgsm_check_cert_sig (subject_cert, subject_cert) )
@ -118,6 +145,10 @@ gpgsm_validate_path (KsbaCert cert)
subject_cert = issuer_cert;
issuer_cert = NULL;
}
if (opt.no_crl_check)
log_info ("CRL was not checked due to --no-crl-cechk option\n");
leave:
xfree (issuer);

View File

@ -69,6 +69,33 @@ gpgsm_validate_path (KsbaCert cert)
goto leave;
}
if (!opt.no_crl_check)
{
rc = gpgsm_dirmngr_isvalid (subject_cert);
if (rc)
{
switch (rc)
{
case GNUPG_Certificate_Revoked:
log_error (_("the certificate has been revoked\n"));
break;
case GNUPG_No_CRL_Known:
log_error (_("no CRL found for certificate\n"));
break;
case GNUPG_CRL_Too_Old:
log_error (_("the available CRL is too old\n"));
log_info (_("please make sure that the "
"\"dirmngr\" is properly installed\n"));
break;
default:
log_error (_("checking the CRL failed: %s\n"),
gnupg_strerror (rc));
break;
}
goto leave;
}
}
if (subject && !strcmp (issuer, subject))
{
if (gpgsm_check_cert_sig (subject_cert, subject_cert) )
@ -118,6 +145,10 @@ gpgsm_validate_path (KsbaCert cert)
subject_cert = issuer_cert;
issuer_cert = NULL;
}
if (opt.no_crl_check)
log_info ("CRL was not checked due to --no-crl-cechk option\n");
leave:
xfree (issuer);

View File

@ -187,6 +187,73 @@ gpgsm_get_keygrip_hexstring (KsbaCert cert)
}
/* For certain purposes we need a certificate id which has an upper
limit of the size. We use the hash of the issuer name and the
serial number for this. In most cases the serial number is not
that large and the resulting string can be passed on an assuan
command line. Everything is hexencoded with the serialnumber
delimted from the has by a dot.
The caller must free the string.
*/
char *
gpgsm_get_certid (KsbaCert cert)
{
KsbaSexp serial;
unsigned char *p;
char *endp;
unsigned char hash[20];
unsigned long n;
char *certid;
int i;
p = ksba_cert_get_issuer (cert, 0);
if (!p)
return NULL; /* Ooops: No issuer */
gcry_md_hash_buffer (GCRY_MD_SHA1, hash, p, strlen (p));
xfree (p);
serial = ksba_cert_get_serial (cert);
if (!serial)
return NULL; /* oops: no serial number */
p = serial;
if (*p != '(')
{
log_error ("Ooops: invalid serial number\n");
xfree (serial);
return NULL;
}
p++;
n = strtoul (p, &endp, 10);
p = endp;
if (*p != ':')
{
log_error ("Ooops: invalid serial number (no colon)\n");
xfree (serial);
return NULL;
}
p++;
certid = xtrymalloc ( 40 + 1 + n*2 + 1);
if (!certid)
{
xfree (serial);
return NULL; /* out of core */
}
for (i=0, endp = certid; i < 20; i++, endp += 2 )
sprintf (endp, "%02X", hash[i]);
*endp++ = '.';
for (i=0; i < n; i++, endp += 2)
sprintf (endp, "%02X", hash[i]);
*endp = 0;
xfree (serial);
return certid;
}

View File

@ -83,7 +83,7 @@ enum cmd_and_opt_values {
oEnableSpecialFilenames,
oAgentProgram,
oDirmngrProgram,
@ -95,7 +95,7 @@ enum cmd_and_opt_values {
oBase64,
oNoArmor,
oDisableCRLChecks,
oTextmode,
oFingerprint,
@ -224,6 +224,10 @@ static ARGPARSE_OPTS opts[] = {
{ oRecipient, "recipient", 2, N_("|NAME|encrypt for NAME")},
{ oDisableCRLChecks, "disable-crl-checks", 0, N_("never consult a CRL")},
#if 0
{ oDefRecipient, "default-recipient" ,2,
N_("|NAME|use NAME as default recipient")},
@ -315,6 +319,7 @@ static ARGPARSE_OPTS opts[] = {
{ oNoOptions, "no-options", 0, "@" }, /* shortcut for --options /dev/null */
{ oHomedir, "homedir", 2, "@" }, /* defaults to "~/.gnupg" */
{ oAgentProgram, "agent-program", 2 , "@" },
{ oDirmngrProgram, "dirmngr-program", 2 , "@" },
{ oNoBatch, "no-batch", 0, "@" },
{ oWithColons, "with-colons", 0, "@"},
@ -727,6 +732,10 @@ main ( int argc, char **argv)
ctrl.is_pem = 0;
ctrl.is_base64 = 0;
break;
case oDisableCRLChecks:
opt.no_crl_check = 1;
break;
case oOutput: opt.outfile = pargs.r.ret_str; break;
@ -780,6 +789,7 @@ main ( int argc, char **argv)
case oNoOptions: break; /* no-options */
case oHomedir: opt.homedir = pargs.r.ret_str; break;
case oAgentProgram: opt.agent_program = pargs.r.ret_str; break;
case oDirmngrProgram: opt.dirmngr_program = pargs.r.ret_str; break;
case oNoDefKeyring: default_keyring = 0; break;
case oNoGreeting: nogreeting = 1; break;

View File

@ -39,6 +39,7 @@ struct {
const char *homedir; /* configuration directory name */
const char *agent_program;
const char *dirmngr_program;
char *outfile; /* name of output file */
int with_key_data;/* include raw key in the column delimted output */
@ -65,6 +66,8 @@ struct {
int ignore_time_conflict; /* Ignore certain time conflicts */
int no_crl_check; /* Don't do a CRL check */
} opt;
@ -126,6 +129,8 @@ char *gpgsm_get_fingerprint_string (KsbaCert cert, int algo);
char *gpgsm_get_fingerprint_hexstring (KsbaCert cert, int algo);
char *gpgsm_get_keygrip (KsbaCert cert, char *array);
char *gpgsm_get_keygrip_hexstring (KsbaCert cert);
char *gpgsm_get_certid (KsbaCert cert);
/*-- base64.c --*/
int gpgsm_create_reader (Base64Context *ctx,
@ -190,6 +195,12 @@ int gpgsm_agent_pkdecrypt (const char *keygrip,
char **r_buf, size_t *r_buflen);
int gpgsm_agent_genkey (KsbaConstSexp keyparms, KsbaSexp *r_pubkey);
/*-- call-dirmngr.c --*/
int gpgsm_dirmngr_isvalid (KsbaCert cert);
#endif /*GPGSM_H*/