mirror of
git://git.gnupg.org/gnupg.git
synced 2024-10-31 20:08:43 +01:00
* 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:
parent
98b2622ef0
commit
6af7631e54
@ -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
|
||||
|
@ -30,6 +30,7 @@ gpgsm_SOURCES = \
|
||||
keydb.c keydb.h \
|
||||
server.c \
|
||||
call-agent.c \
|
||||
call-dirmngr.c \
|
||||
fingerprint.c \
|
||||
base64.c \
|
||||
certlist.c \
|
||||
|
@ -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
182
sm/call-dirmngr.c
Normal 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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
14
sm/gpgsm.c
14
sm/gpgsm.c
@ -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;
|
||||
|
11
sm/gpgsm.h
11
sm/gpgsm.h
@ -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*/
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user