mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-22 10:19:57 +01:00
Implemented the chain model for X.509 validation.
This commit is contained in:
parent
ebd36b6344
commit
74d344a521
@ -1,3 +1,7 @@
|
|||||||
|
2007-08-08 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
|
* configure.ac: Use AC_CANONICAL_HOST and not AC_CANONICAL_TARGET.
|
||||||
|
|
||||||
2007-07-09 Werner Koch <wk@g10code.com>
|
2007-07-09 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
* configure.ac (AM_ICONV): Check for it even when building without
|
* configure.ac (AM_ICONV): Check for it even when building without
|
||||||
|
11
NEWS
11
NEWS
@ -1,11 +1,14 @@
|
|||||||
Noteworthy changes in version 2.0.6
|
Noteworthy changes in version 2.0.6
|
||||||
------------------------------------------------
|
------------------------------------------------
|
||||||
|
|
||||||
* gpgsm does now grok --default-key.
|
* GPGSM does now grok --default-key.
|
||||||
|
|
||||||
|
* GPGCONF is now aware of --default-key and --encrypt-to.
|
||||||
|
|
||||||
|
* GPGSM does again correctly print the serial number as well the the
|
||||||
|
various keyids. This was broken since 2.0.4.
|
||||||
|
|
||||||
|
|
||||||
* gpgconf is now aware of --default-key and --encrypt-to.
|
|
||||||
|
|
||||||
|
|
||||||
Noteworthy changes in version 2.0.5 (2007-07-05)
|
Noteworthy changes in version 2.0.5 (2007-07-05)
|
||||||
------------------------------------------------
|
------------------------------------------------
|
||||||
|
|
||||||
|
@ -1,3 +1,8 @@
|
|||||||
|
2007-08-06 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
|
* trustlist.c (read_one_trustfile): Add flag "cm".
|
||||||
|
(agent_istrusted): Ditto.
|
||||||
|
|
||||||
2007-08-02 Werner Koch <wk@g10code.com>
|
2007-08-02 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
* gpg-agent.c: Include gc-opt-flags.h and remove their definition
|
* gpg-agent.c: Include gc-opt-flags.h and remove their definition
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* trustlist.c - Maintain the list of trusted keys
|
/* trustlist.c - Maintain the list of trusted keys
|
||||||
* Copyright (C) 2002, 2004, 2006 Free Software Foundation, Inc.
|
* Copyright (C) 2002, 2004, 2006, 2007 Free Software Foundation, Inc.
|
||||||
*
|
*
|
||||||
* This file is part of GnuPG.
|
* This file is part of GnuPG.
|
||||||
*
|
*
|
||||||
@ -42,6 +42,7 @@ struct trustitem_s
|
|||||||
int for_smime:1; /* Set by '*' or 'S' as first flag. */
|
int for_smime:1; /* Set by '*' or 'S' as first flag. */
|
||||||
int relax:1; /* Relax checking of root certificate
|
int relax:1; /* Relax checking of root certificate
|
||||||
constraints. */
|
constraints. */
|
||||||
|
int cm:1; /* Use chain model for validation. */
|
||||||
} flags;
|
} flags;
|
||||||
unsigned char fpr[20]; /* The binary fingerprint. */
|
unsigned char fpr[20]; /* The binary fingerprint. */
|
||||||
};
|
};
|
||||||
@ -267,6 +268,8 @@ read_one_trustfile (const char *fname, int allow_include,
|
|||||||
}
|
}
|
||||||
else if (n == 5 && !memcmp (p, "relax", 5))
|
else if (n == 5 && !memcmp (p, "relax", 5))
|
||||||
ti->flags.relax = 1;
|
ti->flags.relax = 1;
|
||||||
|
else if (n == 2 && !memcmp (p, "cm", 2))
|
||||||
|
ti->flags.cm = 1;
|
||||||
else
|
else
|
||||||
log_error ("flag `%.*s' in `%s', line %d ignored\n",
|
log_error ("flag `%.*s' in `%s', line %d ignored\n",
|
||||||
n, p, fname, lnr);
|
n, p, fname, lnr);
|
||||||
@ -396,6 +399,14 @@ agent_istrusted (ctrl_t ctrl, const char *fpr)
|
|||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
else if (ti->flags.cm)
|
||||||
|
{
|
||||||
|
err = agent_write_status (ctrl,
|
||||||
|
"TRUSTLISTFLAG", "cm",
|
||||||
|
NULL);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
}
|
||||||
return 0; /* Trusted. */
|
return 0; /* Trusted. */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,10 @@
|
|||||||
|
2007-08-07 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
|
* tlv.c, tlv.h: Move from ../scd/.
|
||||||
|
* tlv.c (parse_sexp, parse_ber_header): Add ERRSOURCE arg and prefix
|
||||||
|
name with a _.
|
||||||
|
* tlv.h: Use macro to convey ERRSOURCE.
|
||||||
|
|
||||||
2007-08-02 Werner Koch <wk@g10code.com>
|
2007-08-02 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
* gc-opt-flags.h: New.
|
* gc-opt-flags.h: New.
|
||||||
@ -29,7 +36,7 @@
|
|||||||
|
|
||||||
2007-07-04 Werner Koch <wk@g10code.com>
|
2007-07-04 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
* estream.c (es_init_do): Do not throw an error if pth as already
|
* estream.c (es_init_do): Do not throw an error if pth has already
|
||||||
been initialized.
|
been initialized.
|
||||||
|
|
||||||
2007-06-26 Werner Koch <wk@g10code.com>
|
2007-06-26 Werner Koch <wk@g10code.com>
|
||||||
|
@ -36,6 +36,7 @@ common_sources = \
|
|||||||
gc-opt-flags.h \
|
gc-opt-flags.h \
|
||||||
keyserver.h \
|
keyserver.h \
|
||||||
sexp-parse.h \
|
sexp-parse.h \
|
||||||
|
tlv.c tlv.h \
|
||||||
init.c init.h \
|
init.c init.h \
|
||||||
sexputil.c \
|
sexputil.c \
|
||||||
sysutils.c sysutils.h \
|
sysutils.c sysutils.h \
|
||||||
|
@ -72,10 +72,10 @@ gnupg_get_isotime (gnupg_isotime_t timebuf)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* set the time to NEWTIME so that gnupg_get_time returns a time
|
/* Set the time to NEWTIME so that gnupg_get_time returns a time
|
||||||
starting with this one. With FREEZE set to 1 the returned time
|
starting with this one. With FREEZE set to 1 the returned time
|
||||||
will never change. Just for completeness, a value of (time_t)-1
|
will never change. Just for completeness, a value of (time_t)-1
|
||||||
for NEWTIME gets you back to rality. Note that this is obviously
|
for NEWTIME gets you back to reality. Note that this is obviously
|
||||||
not thread-safe but this is not required. */
|
not thread-safe but this is not required. */
|
||||||
void
|
void
|
||||||
gnupg_set_time (time_t newtime, int freeze)
|
gnupg_set_time (time_t newtime, int freeze)
|
||||||
@ -165,7 +165,7 @@ scan_isodatestr( const char *string )
|
|||||||
return stamp;
|
return stamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Scan am ISO timestamp and return a epoch based timestamp. The only
|
/* Scan am ISO timestamp and return an Epoch based timestamp. The only
|
||||||
supported format is "yyyymmddThhmmss" delimited by white space, nul, a
|
supported format is "yyyymmddThhmmss" delimited by white space, nul, a
|
||||||
colon or a comma. Returns (time_t)(-1) for an invalid string. */
|
colon or a comma. Returns (time_t)(-1) for an invalid string. */
|
||||||
time_t
|
time_t
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
#define GPG_ERR_BAD_BER (1) /*G10ERR_GENERAL*/
|
#define GPG_ERR_BAD_BER (1) /*G10ERR_GENERAL*/
|
||||||
#define GPG_ERR_INV_SEXP (45) /*G10ERR_INV_ARG*/
|
#define GPG_ERR_INV_SEXP (45) /*G10ERR_INV_ARG*/
|
||||||
typedef int gpg_error_t;
|
typedef int gpg_error_t;
|
||||||
#define gpg_error(n) (n)
|
#define gpg_make_err(x,n) (n)
|
||||||
#else
|
#else
|
||||||
#include <gpg-error.h>
|
#include <gpg-error.h>
|
||||||
#endif
|
#endif
|
||||||
@ -151,10 +151,11 @@ find_tlv_unchecked (const unsigned char *buffer, size_t length,
|
|||||||
and the length part from the TLV triplet. Update BUFFER and SIZE
|
and the length part from the TLV triplet. Update BUFFER and SIZE
|
||||||
on success. */
|
on success. */
|
||||||
gpg_error_t
|
gpg_error_t
|
||||||
parse_ber_header (unsigned char const **buffer, size_t *size,
|
_parse_ber_header (unsigned char const **buffer, size_t *size,
|
||||||
int *r_class, int *r_tag,
|
int *r_class, int *r_tag,
|
||||||
int *r_constructed, int *r_ndef,
|
int *r_constructed, int *r_ndef,
|
||||||
size_t *r_length, size_t *r_nhdr)
|
size_t *r_length, size_t *r_nhdr,
|
||||||
|
gpg_err_source_t errsource)
|
||||||
{
|
{
|
||||||
int c;
|
int c;
|
||||||
unsigned long tag;
|
unsigned long tag;
|
||||||
@ -167,7 +168,7 @@ parse_ber_header (unsigned char const **buffer, size_t *size,
|
|||||||
|
|
||||||
/* Get the tag. */
|
/* Get the tag. */
|
||||||
if (!length)
|
if (!length)
|
||||||
return gpg_error (GPG_ERR_EOF);
|
return gpg_err_make (errsource, GPG_ERR_EOF);
|
||||||
c = *buf++; length--; ++*r_nhdr;
|
c = *buf++; length--; ++*r_nhdr;
|
||||||
|
|
||||||
*r_class = (c & 0xc0) >> 6;
|
*r_class = (c & 0xc0) >> 6;
|
||||||
@ -181,7 +182,7 @@ parse_ber_header (unsigned char const **buffer, size_t *size,
|
|||||||
{
|
{
|
||||||
tag <<= 7;
|
tag <<= 7;
|
||||||
if (!length)
|
if (!length)
|
||||||
return gpg_error (GPG_ERR_EOF);
|
return gpg_err_make (errsource, GPG_ERR_EOF);
|
||||||
c = *buf++; length--; ++*r_nhdr;
|
c = *buf++; length--; ++*r_nhdr;
|
||||||
tag |= c & 0x7f;
|
tag |= c & 0x7f;
|
||||||
|
|
||||||
@ -192,7 +193,7 @@ parse_ber_header (unsigned char const **buffer, size_t *size,
|
|||||||
|
|
||||||
/* Get the length. */
|
/* Get the length. */
|
||||||
if (!length)
|
if (!length)
|
||||||
return gpg_error (GPG_ERR_EOF);
|
return gpg_err_make (errsource, GPG_ERR_EOF);
|
||||||
c = *buf++; length--; ++*r_nhdr;
|
c = *buf++; length--; ++*r_nhdr;
|
||||||
|
|
||||||
if ( !(c & 0x80) )
|
if ( !(c & 0x80) )
|
||||||
@ -200,20 +201,20 @@ parse_ber_header (unsigned char const **buffer, size_t *size,
|
|||||||
else if (c == 0x80)
|
else if (c == 0x80)
|
||||||
*r_ndef = 1;
|
*r_ndef = 1;
|
||||||
else if (c == 0xff)
|
else if (c == 0xff)
|
||||||
return gpg_error (GPG_ERR_BAD_BER);
|
return gpg_err_make (errsource, GPG_ERR_BAD_BER);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
unsigned long len = 0;
|
unsigned long len = 0;
|
||||||
int count = c & 0x7f;
|
int count = c & 0x7f;
|
||||||
|
|
||||||
if (count > sizeof (len) || count > sizeof (size_t))
|
if (count > sizeof (len) || count > sizeof (size_t))
|
||||||
return gpg_error (GPG_ERR_BAD_BER);
|
return gpg_err_make (errsource, GPG_ERR_BAD_BER);
|
||||||
|
|
||||||
for (; count; count--)
|
for (; count; count--)
|
||||||
{
|
{
|
||||||
len <<= 8;
|
len <<= 8;
|
||||||
if (!length)
|
if (!length)
|
||||||
return gpg_error (GPG_ERR_EOF);
|
return gpg_err_make (errsource, GPG_ERR_EOF);
|
||||||
c = *buf++; length--; ++*r_nhdr;
|
c = *buf++; length--; ++*r_nhdr;
|
||||||
len |= c & 0xff;
|
len |= c & 0xff;
|
||||||
}
|
}
|
||||||
@ -254,8 +255,9 @@ parse_ber_header (unsigned char const **buffer, size_t *size,
|
|||||||
handle_error ();
|
handle_error ();
|
||||||
*/
|
*/
|
||||||
gpg_error_t
|
gpg_error_t
|
||||||
parse_sexp (unsigned char const **buf, size_t *buflen,
|
_parse_sexp (unsigned char const **buf, size_t *buflen,
|
||||||
int *depth, unsigned char const **tok, size_t *toklen)
|
int *depth, unsigned char const **tok, size_t *toklen,
|
||||||
|
gpg_err_source_t errsource)
|
||||||
{
|
{
|
||||||
const unsigned char *s;
|
const unsigned char *s;
|
||||||
size_t n, vlen;
|
size_t n, vlen;
|
||||||
@ -265,7 +267,7 @@ parse_sexp (unsigned char const **buf, size_t *buflen,
|
|||||||
*tok = NULL;
|
*tok = NULL;
|
||||||
*toklen = 0;
|
*toklen = 0;
|
||||||
if (!n)
|
if (!n)
|
||||||
return *depth ? gpg_error (GPG_ERR_INV_SEXP) : 0;
|
return *depth ? gpg_err_make (errsource, GPG_ERR_INV_SEXP) : 0;
|
||||||
if (*s == '(')
|
if (*s == '(')
|
||||||
{
|
{
|
||||||
s++; n--;
|
s++; n--;
|
||||||
@ -277,7 +279,7 @@ parse_sexp (unsigned char const **buf, size_t *buflen,
|
|||||||
if (*s == ')')
|
if (*s == ')')
|
||||||
{
|
{
|
||||||
if (!*depth)
|
if (!*depth)
|
||||||
return gpg_error (GPG_ERR_INV_SEXP);
|
return gpg_err_make (errsource, GPG_ERR_INV_SEXP);
|
||||||
*toklen = 1;
|
*toklen = 1;
|
||||||
s++; n--;
|
s++; n--;
|
||||||
(*depth)--;
|
(*depth)--;
|
||||||
@ -288,10 +290,10 @@ parse_sexp (unsigned char const **buf, size_t *buflen,
|
|||||||
for (vlen=0; n && *s && *s != ':' && (*s >= '0' && *s <= '9'); s++, n--)
|
for (vlen=0; n && *s && *s != ':' && (*s >= '0' && *s <= '9'); s++, n--)
|
||||||
vlen = vlen*10 + (*s - '0');
|
vlen = vlen*10 + (*s - '0');
|
||||||
if (!n || *s != ':')
|
if (!n || *s != ':')
|
||||||
return gpg_error (GPG_ERR_INV_SEXP);
|
return gpg_err_make (errsource, GPG_ERR_INV_SEXP);
|
||||||
s++; n--;
|
s++; n--;
|
||||||
if (vlen > n)
|
if (vlen > n)
|
||||||
return gpg_error (GPG_ERR_INV_SEXP);
|
return gpg_err_make (errsource, GPG_ERR_INV_SEXP);
|
||||||
*tok = s;
|
*tok = s;
|
||||||
*toklen = vlen;
|
*toklen = vlen;
|
||||||
s += vlen;
|
s += vlen;
|
@ -80,11 +80,14 @@ const unsigned char *find_tlv_unchecked (const unsigned char *buffer,
|
|||||||
/* ASN.1 BER parser: Parse BUFFER of length SIZE and return the tag
|
/* ASN.1 BER parser: Parse BUFFER of length SIZE and return the tag
|
||||||
and the length part from the TLV triplet. Update BUFFER and SIZE
|
and the length part from the TLV triplet. Update BUFFER and SIZE
|
||||||
on success. */
|
on success. */
|
||||||
gpg_error_t parse_ber_header (unsigned char const **buffer, size_t *size,
|
gpg_error_t _parse_ber_header (unsigned char const **buffer, size_t *size,
|
||||||
int *r_class, int *r_tag,
|
int *r_class, int *r_tag,
|
||||||
int *r_constructed,
|
int *r_constructed,
|
||||||
int *r_ndef, size_t *r_length, size_t *r_nhdr);
|
int *r_ndef, size_t *r_length, size_t *r_nhdr,
|
||||||
|
gpg_err_source_t errsource);
|
||||||
|
#define parse_ber_header(a,b,c,d,e,f,g,h) \
|
||||||
|
_parse_ber_header ((a),(b),(c),(d),(e),(f),(g),(h),\
|
||||||
|
GPG_ERR_SOURCE_DEFAULT)
|
||||||
|
|
||||||
|
|
||||||
/* Return the next token of an canconical encoded S-expression. BUF
|
/* Return the next token of an canconical encoded S-expression. BUF
|
||||||
@ -99,8 +102,11 @@ gpg_error_t parse_ber_header (unsigned char const **buffer, size_t *size,
|
|||||||
reflect on return the actual depth of the tree. To detect the end
|
reflect on return the actual depth of the tree. To detect the end
|
||||||
of the S-expression it is advisable to check DEPTH after a
|
of the S-expression it is advisable to check DEPTH after a
|
||||||
successful return. */
|
successful return. */
|
||||||
gpg_error_t parse_sexp (unsigned char const **buf, size_t *buflen,
|
gpg_error_t _parse_sexp (unsigned char const **buf, size_t *buflen,
|
||||||
int *depth, unsigned char const **tok, size_t *toklen);
|
int *depth, unsigned char const **tok, size_t *toklen,
|
||||||
|
gpg_err_source_t errsource);
|
||||||
|
#define parse_sexp(a,b,c,d,e) \
|
||||||
|
_parse_sexp ((a),(b),(c),(d),(e), GPG_ERR_SOURCE_DEFAULT)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -112,7 +112,7 @@ const char *isotimestamp (u32 stamp); /* GMT */
|
|||||||
const char *asctimestamp (u32 stamp); /* localized */
|
const char *asctimestamp (u32 stamp); /* localized */
|
||||||
|
|
||||||
|
|
||||||
/* Copy one iso ddate to another, this is inline so that we can do a
|
/* Copy one ISO date to another, this is inline so that we can do a
|
||||||
sanity check. */
|
sanity check. */
|
||||||
static inline void
|
static inline void
|
||||||
gnupg_copy_time (gnupg_isotime_t d, const gnupg_isotime_t s)
|
gnupg_copy_time (gnupg_isotime_t d, const gnupg_isotime_t s)
|
||||||
|
@ -56,8 +56,8 @@ VERSION=$PACKAGE_VERSION
|
|||||||
AC_CONFIG_AUX_DIR(scripts)
|
AC_CONFIG_AUX_DIR(scripts)
|
||||||
AC_CONFIG_SRCDIR(sm/gpgsm.c)
|
AC_CONFIG_SRCDIR(sm/gpgsm.c)
|
||||||
AM_CONFIG_HEADER(config.h)
|
AM_CONFIG_HEADER(config.h)
|
||||||
AC_CANONICAL_TARGET()
|
|
||||||
AM_INIT_AUTOMAKE($PACKAGE, $VERSION)
|
AM_INIT_AUTOMAKE($PACKAGE, $VERSION)
|
||||||
|
AC_CANONICAL_HOST
|
||||||
AB_INIT
|
AB_INIT
|
||||||
|
|
||||||
AC_GNU_SOURCE
|
AC_GNU_SOURCE
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
2007-08-09 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
|
* gpgsm.texi (Certificate Options): Describe --validation-model.
|
||||||
|
|
||||||
2007-07-23 Werner Koch <wk@g10code.com>
|
2007-07-23 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
* scdaemon.texi (Scdaemon Commands): Remove obsolete --print-atr.
|
* scdaemon.texi (Scdaemon Commands): Remove obsolete --print-atr.
|
||||||
|
31
doc/DETAILS
31
doc/DETAILS
@ -253,8 +253,8 @@ more arguments in future versions.
|
|||||||
presence of the letter 'T' inside.
|
presence of the letter 'T' inside.
|
||||||
|
|
||||||
VALIDSIG <fingerprint in hex> <sig_creation_date> <sig-timestamp>
|
VALIDSIG <fingerprint in hex> <sig_creation_date> <sig-timestamp>
|
||||||
<expire-timestamp> [ <sig-version> <reserved> <pubkey-algo>
|
<expire-timestamp> <sig-version> <reserved> <pubkey-algo>
|
||||||
<hash-algo> <sig-class> <primary-key-fpr> ]
|
<hash-algo> <sig-class> [ <primary-key-fpr> ]
|
||||||
|
|
||||||
The signature with the keyid is good. This is the same as
|
The signature with the keyid is good. This is the same as
|
||||||
GOODSIG but has the fingerprint as the argument. Both status
|
GOODSIG but has the fingerprint as the argument. Both status
|
||||||
@ -269,8 +269,9 @@ more arguments in future versions.
|
|||||||
useful to get back to the primary key without running gpg
|
useful to get back to the primary key without running gpg
|
||||||
again for this purpose.
|
again for this purpose.
|
||||||
|
|
||||||
The optional parameters are used for OpenPGP and are not
|
The primary-key-fpr parameter is used for OpenPGP and not
|
||||||
available for CMS signatures.
|
available for CMS signatures. The sig-version as well as the
|
||||||
|
sig class is not defined for CMS and currently set to 0 and 00.
|
||||||
|
|
||||||
Note, that *-TIMESTAMP may either be a number with seconds
|
Note, that *-TIMESTAMP may either be a number with seconds
|
||||||
since epoch or an ISO 8601 string which can be detected by the
|
since epoch or an ISO 8601 string which can be detected by the
|
||||||
@ -310,13 +311,21 @@ more arguments in future versions.
|
|||||||
|
|
||||||
|
|
||||||
TRUST_UNDEFINED <error token>
|
TRUST_UNDEFINED <error token>
|
||||||
TRUST_NEVER <error token>
|
TRUST_NEVER <error token>
|
||||||
TRUST_MARGINAL
|
TRUST_MARGINAL [0 [<validation_model>]]
|
||||||
TRUST_FULLY
|
TRUST_FULLY [0 [<validation_model>]]
|
||||||
TRUST_ULTIMATE
|
TRUST_ULTIMATE [0 [<validation_model>]]
|
||||||
For good signatures one of these status lines are emitted
|
For good signatures one of these status lines are emitted to
|
||||||
to indicate how trustworthy the signature is. The error token
|
indicate how trustworthy the signature is. The error token
|
||||||
values are currently only emitted by gpgsm.
|
values are currently only emitted by gpgsm. VALIDATION_MODEL
|
||||||
|
describes the algorithm used to check the validity of the key.
|
||||||
|
The default is the standard gpg Web of Trust model respective
|
||||||
|
the standard X.509 model. The defined values are
|
||||||
|
|
||||||
|
"pgp" for the standard PGP WoT.
|
||||||
|
"shell" for the standard X.509 model.
|
||||||
|
"chain" for the chain model.
|
||||||
|
|
||||||
|
|
||||||
PKA_TRUST_GOOD <mailbox>
|
PKA_TRUST_GOOD <mailbox>
|
||||||
PKA_TRUST_BAD <mailbox>
|
PKA_TRUST_BAD <mailbox>
|
||||||
|
@ -412,6 +412,17 @@ requests in Dirmngr's configuration too (option
|
|||||||
@option{--allow-ocsp} and configure dirmngr properly. If you don't do
|
@option{--allow-ocsp} and configure dirmngr properly. If you don't do
|
||||||
so you will get the error code @samp{Not supported}.
|
so you will get the error code @samp{Not supported}.
|
||||||
|
|
||||||
|
|
||||||
|
@item --validation-model @var{name}
|
||||||
|
@opindex validation-model
|
||||||
|
This option changes the default validation model. The only possible
|
||||||
|
values are "shell" (which is the default) and "chain" which forces the
|
||||||
|
use of the chain model. The chain model is also used if an option in
|
||||||
|
the @file{trustlist.txt} or an attribute of the certificate requests it.
|
||||||
|
However the standard model (shell) is in that case always tried first.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@end table
|
@end table
|
||||||
|
|
||||||
@c *******************************************
|
@c *******************************************
|
||||||
@ -550,7 +561,8 @@ encryption. For convenience the strings @code{3DES}, @code{AES} and
|
|||||||
@opindex faked-system-time
|
@opindex faked-system-time
|
||||||
This option is only useful for testing; it sets the system time back or
|
This option is only useful for testing; it sets the system time back or
|
||||||
forth to @var{epoch} which is the number of seconds elapsed since the year
|
forth to @var{epoch} which is the number of seconds elapsed since the year
|
||||||
1970.
|
1970. Alternativly @var{epoch} may be given as a full ISO time string
|
||||||
|
(e.g. "20070924T154812").
|
||||||
|
|
||||||
@item --with-ephemeral-keys
|
@item --with-ephemeral-keys
|
||||||
@opindex with-ephemeral-keys
|
@opindex with-ephemeral-keys
|
||||||
|
@ -122,7 +122,7 @@ This should return the Root cert of the issuer. See note above.
|
|||||||
|
|
||||||
@item By exact match on serial number and issuer's DN.
|
@item By exact match on serial number and issuer's DN.
|
||||||
This is indicated by a hash mark, followed by the hexadecmal
|
This is indicated by a hash mark, followed by the hexadecmal
|
||||||
representation of the serial number, the followed by a slash and the
|
representation of the serial number, then followed by a slash and the
|
||||||
RFC-2253 encoded DN of the issuer. See note above.
|
RFC-2253 encoded DN of the issuer. See note above.
|
||||||
|
|
||||||
@cartouche
|
@cartouche
|
||||||
|
@ -1,3 +1,8 @@
|
|||||||
|
2007-08-09 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
|
* argparse.c (show_help): Expand the @EMAIL@ macro in the package
|
||||||
|
bug reporting address.
|
||||||
|
|
||||||
2007-08-02 Werner Koch <wk@g10code.com>
|
2007-08-02 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
* t-stringhelp.c (test_compare_filenames): New.
|
* t-stringhelp.c (test_compare_filenames): New.
|
||||||
|
@ -832,8 +832,21 @@ show_help( ARGPARSE_OPTS *opts, unsigned flags )
|
|||||||
puts("\n(A single dash may be used instead of the double ones)");
|
puts("\n(A single dash may be used instead of the double ones)");
|
||||||
}
|
}
|
||||||
if( (s=strusage(19)) ) { /* bug reports to ... */
|
if( (s=strusage(19)) ) { /* bug reports to ... */
|
||||||
|
char *s2;
|
||||||
|
|
||||||
putchar('\n');
|
putchar('\n');
|
||||||
fputs(s, stdout);
|
s2 = strstr (s, "@EMAIL@");
|
||||||
|
if (s2)
|
||||||
|
{
|
||||||
|
if (s2-s)
|
||||||
|
fwrite (s, s2-s, 1, stdout);
|
||||||
|
fputs (PACKAGE_BUGREPORT, stdout);
|
||||||
|
s2 += 7;
|
||||||
|
if (*s2)
|
||||||
|
fputs (s2, stdout);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
fputs(s, stdout);
|
||||||
}
|
}
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
exit(0);
|
exit(0);
|
||||||
|
1060
po/pt_BR.po
1060
po/pt_BR.po
File diff suppressed because it is too large
Load Diff
1050
po/zh_CN.po
1050
po/zh_CN.po
File diff suppressed because it is too large
Load Diff
1050
po/zh_TW.po
1050
po/zh_TW.po
File diff suppressed because it is too large
Load Diff
@ -1,3 +1,7 @@
|
|||||||
|
2007-08-07 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
|
* tlv.c, tlv.h: Move to ../common/.
|
||||||
|
|
||||||
2007-08-02 Werner Koch <wk@g10code.com>
|
2007-08-02 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
* scdaemon.c: Include gc-opt-flags.h and remove their definition
|
* scdaemon.c: Include gc-opt-flags.h and remove their definition
|
||||||
|
@ -38,7 +38,6 @@ scdaemon_SOURCES = \
|
|||||||
apdu.c apdu.h \
|
apdu.c apdu.h \
|
||||||
ccid-driver.c ccid-driver.h \
|
ccid-driver.c ccid-driver.h \
|
||||||
iso7816.c iso7816.h \
|
iso7816.c iso7816.h \
|
||||||
tlv.c tlv.h \
|
|
||||||
app.c app-common.h app-help.c $(card_apps)
|
app.c app-common.h app-help.c $(card_apps)
|
||||||
|
|
||||||
|
|
||||||
@ -55,7 +54,6 @@ scdaemon_LDADD = $(libcommonpth) ../jnlib/libjnlib.a ../gl/libgnu.a \
|
|||||||
# apdu.c apdu.h \
|
# apdu.c apdu.h \
|
||||||
# ccid-driver.c ccid-driver.h \
|
# ccid-driver.c ccid-driver.h \
|
||||||
# iso7816.c iso7816.h \
|
# iso7816.c iso7816.h \
|
||||||
# tlv.c tlv.h \
|
|
||||||
# atr.c atr.h \
|
# atr.c atr.h \
|
||||||
# app.c app-common.h app-help.c $(card_apps)
|
# app.c app-common.h app-help.c $(card_apps)
|
||||||
#
|
#
|
||||||
|
62
sm/ChangeLog
62
sm/ChangeLog
@ -1,3 +1,65 @@
|
|||||||
|
2007-08-09 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
|
* gpgsm.c (main) [W32]: Enable CRL check by default.
|
||||||
|
(main): Update the default control structure after reading the
|
||||||
|
options.
|
||||||
|
(gpgsm_parse_validation_model, parse_validation_model): New.
|
||||||
|
(main): New option --validation-model.
|
||||||
|
* certchain.c (gpgsm_validate_chain): Implement this option.
|
||||||
|
* server.c (option_handler): Ditto.
|
||||||
|
|
||||||
|
* certchain.c (is_cert_still_valid): Reformatted. Add arg
|
||||||
|
FORCE_OCSP. Changed callers to set this flag when using the chain
|
||||||
|
model.
|
||||||
|
|
||||||
|
2007-08-08 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
|
* certdump.c (gpgsm_print_serial): Fixed brown paper bag style bugs
|
||||||
|
which prefixed the output with a 3A and cut it off at a 00.
|
||||||
|
|
||||||
|
* keylist.c (list_cert_raw): Print the certificate ID first and
|
||||||
|
rename "Serial number" to "S/N".
|
||||||
|
(list_cert_std): Ditto.
|
||||||
|
|
||||||
|
2007-08-07 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
|
* gpgsm.c (main): Allow a string for --faked-system-time.
|
||||||
|
|
||||||
|
2007-08-06 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
|
Implementation of the chain model.
|
||||||
|
|
||||||
|
* gpgsm.h (struct rootca_flags_s): Define new members VALID and
|
||||||
|
CHAIN_MODEL.
|
||||||
|
* call-agent.c (gpgsm_agent_istrusted): Mark ROOTCA_FLAGS valid.
|
||||||
|
(istrusted_status_cb): Set CHAIN_MODEL.
|
||||||
|
* certchain.c (gpgsm_validate_chain): Replace LM alias by LISTMODE
|
||||||
|
and FP by LISTFP.
|
||||||
|
(gpgsm_validate_chain): Factor some code out to ...
|
||||||
|
(check_validity_period, ask_marktrusted): .. new.
|
||||||
|
(check_validity_cm_basic, check_validity_cm_main): New.
|
||||||
|
(do_validate_chain): New with all code from gpgsm_validate_chain.
|
||||||
|
New arg ROOTCA_FLAGS.
|
||||||
|
(gpgsm_validate_chain): Provide ROOTCA_FLAGS and fallback to chain
|
||||||
|
model. Add RETFLAGS arg and changed all callers to pass NULL. Add
|
||||||
|
CHECKTIME arg and changed all callers to pass a nil value.
|
||||||
|
(has_validity_model_chain): New.
|
||||||
|
* verify.c (gpgsm_verify): Check for chain model and return as
|
||||||
|
part of the trust status.
|
||||||
|
|
||||||
|
* gpgsm.h (VALIDATE_FLAG_NO_DIRMNGR): New.
|
||||||
|
(VALIDATE_FLAG_NO_DIRMNGR): New.
|
||||||
|
* call-dirmngr.c (gpgsm_dirmngr_isvalid): Use constant here.
|
||||||
|
|
||||||
|
2007-08-03 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
|
* keylist.c (list_cert_colon): Avoid duplicate listing of kludge
|
||||||
|
uids.
|
||||||
|
|
||||||
|
* verify.c (gpgsm_verify): Make STATUS_VERIFY return the hash and
|
||||||
|
pk algo.
|
||||||
|
* certcheck.c (gpgsm_check_cms_signature): Add arg R_PKALGO.
|
||||||
|
|
||||||
2007-08-02 Werner Koch <wk@g10code.com>
|
2007-08-02 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
* gpgsm.c (main): Factored GC_OPT_FLAGS out to gc-opt-flags.h.
|
* gpgsm.c (main): Factored GC_OPT_FLAGS out to gc-opt-flags.h.
|
||||||
|
@ -486,6 +486,8 @@ istrusted_status_cb (void *opaque, const char *line)
|
|||||||
;
|
;
|
||||||
if (!strncmp (line, "relax", 5) && (line[5] == ' ' || !line[5]))
|
if (!strncmp (line, "relax", 5) && (line[5] == ' ' || !line[5]))
|
||||||
flags->relax = 1;
|
flags->relax = 1;
|
||||||
|
else if (!strncmp (line, "cm", 2) && (line[2] == ' ' || !line[2]))
|
||||||
|
flags->chain_model = 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -521,6 +523,8 @@ gpgsm_agent_istrusted (ctrl_t ctrl, ksba_cert_t cert,
|
|||||||
|
|
||||||
rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL,
|
rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL,
|
||||||
istrusted_status_cb, rootca_flags);
|
istrusted_status_cb, rootca_flags);
|
||||||
|
if (!rc)
|
||||||
|
rootca_flags->valid = 1;
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -394,8 +394,10 @@ isvalid_status_cb (void *opaque, const char *line)
|
|||||||
GPG_ERR_NO_CRL_KNOWN
|
GPG_ERR_NO_CRL_KNOWN
|
||||||
GPG_ERR_CRL_TOO_OLD
|
GPG_ERR_CRL_TOO_OLD
|
||||||
|
|
||||||
With USE_OCSP set to true, the dirmngr is asked to do an OCSP
|
Values for USE_OCSP:
|
||||||
request first.
|
0 = Do CRL check.
|
||||||
|
1 = Do an OCSP check.
|
||||||
|
2 = Do an OCSP check using only the default responder.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
gpgsm_dirmngr_isvalid (ctrl_t ctrl,
|
gpgsm_dirmngr_isvalid (ctrl_t ctrl,
|
||||||
@ -445,7 +447,8 @@ gpgsm_dirmngr_isvalid (ctrl_t ctrl,
|
|||||||
|
|
||||||
/* FIXME: If --disable-crl-checks has been set, we should pass an
|
/* FIXME: If --disable-crl-checks has been set, we should pass an
|
||||||
option to dirmngr, so that no fallback CRL check is done after an
|
option to dirmngr, so that no fallback CRL check is done after an
|
||||||
ocsp check. */
|
ocsp check. It is not a problem right now as dirmngr does not
|
||||||
|
fallback to CRL checking. */
|
||||||
|
|
||||||
/* It is sufficient to send the options only once because we have
|
/* It is sufficient to send the options only once because we have
|
||||||
one connection per process only. */
|
one connection per process only. */
|
||||||
@ -456,7 +459,9 @@ gpgsm_dirmngr_isvalid (ctrl_t ctrl,
|
|||||||
NULL, NULL, NULL, NULL, NULL, NULL);
|
NULL, NULL, NULL, NULL, NULL, NULL);
|
||||||
did_options = 1;
|
did_options = 1;
|
||||||
}
|
}
|
||||||
snprintf (line, DIM(line)-1, "ISVALID %s", certid);
|
snprintf (line, DIM(line)-1, "ISVALID%s %s",
|
||||||
|
use_ocsp == 2? " --only-ocsp --force-default-responder":"",
|
||||||
|
certid);
|
||||||
line[DIM(line)-1] = 0;
|
line[DIM(line)-1] = 0;
|
||||||
xfree (certid);
|
xfree (certid);
|
||||||
|
|
||||||
@ -504,9 +509,10 @@ gpgsm_dirmngr_isvalid (ctrl_t ctrl,
|
|||||||
rc = gpg_error (GPG_ERR_INV_CRL);
|
rc = gpg_error (GPG_ERR_INV_CRL);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Note, the flag = 1: This avoids checking this
|
/* Note the no_dirmngr flag: This avoids checking
|
||||||
certificate over and over again. */
|
this certificate over and over again. */
|
||||||
rc = gpgsm_validate_chain (ctrl, rspcert, NULL, 0, NULL, 1);
|
rc = gpgsm_validate_chain (ctrl, rspcert, "", NULL, 0, NULL,
|
||||||
|
VALIDATE_FLAG_NO_DIRMNGR, NULL);
|
||||||
if (rc)
|
if (rc)
|
||||||
{
|
{
|
||||||
log_error ("invalid certificate used for CRL/OCSP: %s\n",
|
log_error ("invalid certificate used for CRL/OCSP: %s\n",
|
||||||
|
686
sm/certchain.c
686
sm/certchain.c
@ -1,6 +1,6 @@
|
|||||||
/* certchain.c - certificate chain validation
|
/* certchain.c - certificate chain validation
|
||||||
* Copyright (C) 2001, 2002, 2003, 2004, 2005,
|
* Copyright (C) 2001, 2002, 2003, 2004, 2005,
|
||||||
* 2006 Free Software Foundation, Inc.
|
* 2006, 2007 Free Software Foundation, Inc.
|
||||||
*
|
*
|
||||||
* This file is part of GnuPG.
|
* This file is part of GnuPG.
|
||||||
*
|
*
|
||||||
@ -37,6 +37,7 @@
|
|||||||
#include "keydb.h"
|
#include "keydb.h"
|
||||||
#include "../kbx/keybox.h" /* for KEYBOX_FLAG_* */
|
#include "../kbx/keybox.h" /* for KEYBOX_FLAG_* */
|
||||||
#include "i18n.h"
|
#include "i18n.h"
|
||||||
|
#include "tlv.h"
|
||||||
|
|
||||||
|
|
||||||
/* Object to keep track of certain root certificates. */
|
/* Object to keep track of certain root certificates. */
|
||||||
@ -141,6 +142,71 @@ compare_certs (ksba_cert_t a, ksba_cert_t b)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Return true if CERT has the validityModel extensions and defines
|
||||||
|
the use of the chain model. */
|
||||||
|
static int
|
||||||
|
has_validation_model_chain (ksba_cert_t cert, int listmode, estream_t listfp)
|
||||||
|
{
|
||||||
|
gpg_error_t err;
|
||||||
|
int idx, yes;
|
||||||
|
const char *oid;
|
||||||
|
size_t off, derlen, objlen, hdrlen;
|
||||||
|
const unsigned char *der;
|
||||||
|
int class, tag, constructed, ndef;
|
||||||
|
char *oidbuf;
|
||||||
|
|
||||||
|
for (idx=0; !(err=ksba_cert_get_extension (cert, idx,
|
||||||
|
&oid, NULL, &off, &derlen));idx++)
|
||||||
|
if (!strcmp (oid, "1.3.6.1.4.1.8301.3.5") )
|
||||||
|
break;
|
||||||
|
if (err)
|
||||||
|
return 0; /* Not found. */
|
||||||
|
der = ksba_cert_get_image (cert, NULL);
|
||||||
|
if (!der)
|
||||||
|
{
|
||||||
|
err = gpg_error (GPG_ERR_INV_OBJ); /* Oops */
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
der += off;
|
||||||
|
|
||||||
|
err = parse_ber_header (&der, &derlen, &class, &tag, &constructed,
|
||||||
|
&ndef, &objlen, &hdrlen);
|
||||||
|
if (!err && (objlen > derlen || tag != TAG_SEQUENCE))
|
||||||
|
err = gpg_error (GPG_ERR_INV_OBJ);
|
||||||
|
if (err)
|
||||||
|
goto leave;
|
||||||
|
derlen = objlen;
|
||||||
|
err = parse_ber_header (&der, &derlen, &class, &tag, &constructed,
|
||||||
|
&ndef, &objlen, &hdrlen);
|
||||||
|
if (!err && (objlen > derlen || tag != TAG_OBJECT_ID))
|
||||||
|
err = gpg_error (GPG_ERR_INV_OBJ);
|
||||||
|
if (err)
|
||||||
|
goto leave;
|
||||||
|
oidbuf = ksba_oid_to_str (der, objlen);
|
||||||
|
if (!oidbuf)
|
||||||
|
{
|
||||||
|
err = gpg_error_from_syserror ();
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opt.verbose)
|
||||||
|
do_list (0, listmode, listfp,
|
||||||
|
_("validation model requested by certificate: %s"),
|
||||||
|
!strcmp (oidbuf, "1.3.6.1.4.1.8301.3.5.1")? _("chain") :
|
||||||
|
!strcmp (oidbuf, "1.3.6.1.4.1.8301.3.5.2")? _("shell") :
|
||||||
|
/* */ oidbuf);
|
||||||
|
yes = !strcmp (oidbuf, "1.3.6.1.4.1.8301.3.5.1");
|
||||||
|
ksba_free (oidbuf);
|
||||||
|
return yes;
|
||||||
|
|
||||||
|
|
||||||
|
leave:
|
||||||
|
log_error ("error parsing validityModel: %s\n", gpg_strerror (err));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
unknown_criticals (ksba_cert_t cert, int listmode, estream_t fp)
|
unknown_criticals (ksba_cert_t cert, int listmode, estream_t fp)
|
||||||
{
|
{
|
||||||
@ -155,6 +221,7 @@ unknown_criticals (ksba_cert_t cert, int listmode, estream_t fp)
|
|||||||
"2.5.29.19", /* basic Constraints */
|
"2.5.29.19", /* basic Constraints */
|
||||||
"2.5.29.32", /* certificatePolicies */
|
"2.5.29.32", /* certificatePolicies */
|
||||||
"2.5.29.37", /* extendedKeyUsage - handled by certlist.c */
|
"2.5.29.37", /* extendedKeyUsage - handled by certlist.c */
|
||||||
|
"1.3.6.1.4.1.8301.3.5", /* validityModel - handled here. */
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
int rc = 0, i, idx, crit;
|
int rc = 0, i, idx, crit;
|
||||||
@ -653,73 +720,310 @@ gpgsm_is_root_cert (ksba_cert_t cert)
|
|||||||
|
|
||||||
/* This is a helper for gpgsm_validate_chain. */
|
/* This is a helper for gpgsm_validate_chain. */
|
||||||
static gpg_error_t
|
static gpg_error_t
|
||||||
is_cert_still_valid (ctrl_t ctrl, int lm, estream_t fp,
|
is_cert_still_valid (ctrl_t ctrl, int force_ocsp, int lm, estream_t fp,
|
||||||
ksba_cert_t subject_cert, ksba_cert_t issuer_cert,
|
ksba_cert_t subject_cert, ksba_cert_t issuer_cert,
|
||||||
int *any_revoked, int *any_no_crl, int *any_crl_too_old)
|
int *any_revoked, int *any_no_crl, int *any_crl_too_old)
|
||||||
{
|
{
|
||||||
if (!opt.no_crl_check || ctrl->use_ocsp)
|
gpg_error_t err;
|
||||||
{
|
|
||||||
gpg_error_t err;
|
|
||||||
|
|
||||||
err = gpgsm_dirmngr_isvalid (ctrl,
|
if (opt.no_crl_check && !ctrl->use_ocsp)
|
||||||
subject_cert, issuer_cert, ctrl->use_ocsp);
|
return 0;
|
||||||
if (err)
|
|
||||||
|
err = gpgsm_dirmngr_isvalid (ctrl,
|
||||||
|
subject_cert, issuer_cert,
|
||||||
|
force_ocsp? 2 : !!ctrl->use_ocsp);
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
if (!lm)
|
||||||
|
gpgsm_cert_log_name (NULL, subject_cert);
|
||||||
|
switch (gpg_err_code (err))
|
||||||
{
|
{
|
||||||
/* Fixme: We should change the wording because we may
|
case GPG_ERR_CERT_REVOKED:
|
||||||
have used OCSP. */
|
do_list (1, lm, fp, _("certificate has been revoked"));
|
||||||
|
*any_revoked = 1;
|
||||||
|
/* Store that in the keybox so that key listings are able to
|
||||||
|
return the revoked flag. We don't care about error,
|
||||||
|
though. */
|
||||||
|
keydb_set_cert_flags (subject_cert, 1, KEYBOX_FLAG_VALIDITY, 0,
|
||||||
|
~0, VALIDITY_REVOKED);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GPG_ERR_NO_CRL_KNOWN:
|
||||||
|
do_list (1, lm, fp, _("no CRL found for certificate"));
|
||||||
|
*any_no_crl = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GPG_ERR_NO_DATA:
|
||||||
|
do_list (1, lm, fp, _("the status of the certificate is unknown"));
|
||||||
|
*any_no_crl = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GPG_ERR_CRL_TOO_OLD:
|
||||||
|
do_list (1, lm, fp, _("the available CRL is too old"));
|
||||||
if (!lm)
|
if (!lm)
|
||||||
gpgsm_cert_log_name (NULL, subject_cert);
|
log_info (_("please make sure that the "
|
||||||
switch (gpg_err_code (err))
|
"\"dirmngr\" is properly installed\n"));
|
||||||
{
|
*any_crl_too_old = 1;
|
||||||
case GPG_ERR_CERT_REVOKED:
|
break;
|
||||||
do_list (1, lm, fp, _("certificate has been revoked"));
|
|
||||||
*any_revoked = 1;
|
default:
|
||||||
/* Store that in the keybox so that key listings are
|
do_list (1, lm, fp, _("checking the CRL failed: %s"),
|
||||||
able to return the revoked flag. We don't care
|
gpg_strerror (err));
|
||||||
about error, though. */
|
return err;
|
||||||
keydb_set_cert_flags (subject_cert, 1, KEYBOX_FLAG_VALIDITY, 0,
|
|
||||||
~0, VALIDITY_REVOKED);
|
|
||||||
break;
|
|
||||||
case GPG_ERR_NO_CRL_KNOWN:
|
|
||||||
do_list (1, lm, fp, _("no CRL found for certificate"));
|
|
||||||
*any_no_crl = 1;
|
|
||||||
break;
|
|
||||||
case GPG_ERR_CRL_TOO_OLD:
|
|
||||||
do_list (1, lm, fp, _("the available CRL is too old"));
|
|
||||||
if (!lm)
|
|
||||||
log_info (_("please make sure that the "
|
|
||||||
"\"dirmngr\" is properly installed\n"));
|
|
||||||
*any_crl_too_old = 1;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
do_list (1, lm, fp, _("checking the CRL failed: %s"),
|
|
||||||
gpg_strerror (err));
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Helper for gpgsm_validate_chain to check the validity period of
|
||||||
|
SUBJECT_CERT. The caller needs to pass EXPTIME which will be
|
||||||
|
updated to the nearest expiration time seen. A DEPTH of 0 indicates
|
||||||
|
the target certifciate, -1 the final root certificate and other
|
||||||
|
values intermediate certificates. */
|
||||||
|
static gpg_error_t
|
||||||
|
check_validity_period (ksba_isotime_t current_time,
|
||||||
|
ksba_cert_t subject_cert,
|
||||||
|
ksba_isotime_t exptime,
|
||||||
|
int listmode, estream_t listfp, int depth)
|
||||||
|
{
|
||||||
|
gpg_error_t err;
|
||||||
|
ksba_isotime_t not_before, not_after;
|
||||||
|
|
||||||
|
err = ksba_cert_get_validity (subject_cert, 0, not_before);
|
||||||
|
if (!err)
|
||||||
|
err = ksba_cert_get_validity (subject_cert, 1, not_after);
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
do_list (1, listmode, listfp,
|
||||||
|
_("certificate with invalid validity: %s"), gpg_strerror (err));
|
||||||
|
return gpg_error (GPG_ERR_BAD_CERT);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*not_after)
|
||||||
|
{
|
||||||
|
if (!*exptime)
|
||||||
|
gnupg_copy_time (exptime, not_after);
|
||||||
|
else if (strcmp (not_after, exptime) < 0 )
|
||||||
|
gnupg_copy_time (exptime, not_after);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*not_before && strcmp (current_time, not_before) < 0 )
|
||||||
|
{
|
||||||
|
do_list (1, listmode, listfp,
|
||||||
|
depth == 0 ? _("certificate not yet valid") :
|
||||||
|
depth == -1 ? _("root certificate not yet valid") :
|
||||||
|
/* other */ _("intermediate certificate not yet valid"));
|
||||||
|
if (!listmode)
|
||||||
|
{
|
||||||
|
log_info (" (valid from ");
|
||||||
|
gpgsm_dump_time (not_before);
|
||||||
|
log_printf (")\n");
|
||||||
|
}
|
||||||
|
return gpg_error (GPG_ERR_CERT_TOO_YOUNG);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*not_after && strcmp (current_time, not_after) > 0 )
|
||||||
|
{
|
||||||
|
do_list (opt.ignore_expiration?0:1, listmode, listfp,
|
||||||
|
depth == 0 ? _("certificate has expired") :
|
||||||
|
depth == -1 ? _("root certificate has expired") :
|
||||||
|
/* other */ _("intermediate certificate has expired"));
|
||||||
|
if (!listmode)
|
||||||
|
{
|
||||||
|
log_info (" (expired at ");
|
||||||
|
gpgsm_dump_time (not_after);
|
||||||
|
log_printf (")\n");
|
||||||
|
}
|
||||||
|
if (opt.ignore_expiration)
|
||||||
|
log_info ("WARNING: ignoring expiration\n");
|
||||||
|
else
|
||||||
|
return gpg_error (GPG_ERR_CERT_EXPIRED);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This is a variant of check_validity_period used with the chain
|
||||||
|
model. The dextra contraint here is that notBefore and notAfter
|
||||||
|
must exists and if the additional argument CHECK_TIME is given this
|
||||||
|
time is used to check the validity period of SUBJECT_CERT. */
|
||||||
|
static gpg_error_t
|
||||||
|
check_validity_period_cm (ksba_isotime_t current_time,
|
||||||
|
ksba_isotime_t check_time,
|
||||||
|
ksba_cert_t subject_cert,
|
||||||
|
ksba_isotime_t exptime,
|
||||||
|
int listmode, estream_t listfp, int depth)
|
||||||
|
{
|
||||||
|
gpg_error_t err;
|
||||||
|
ksba_isotime_t not_before, not_after;
|
||||||
|
|
||||||
|
err = ksba_cert_get_validity (subject_cert, 0, not_before);
|
||||||
|
if (!err)
|
||||||
|
err = ksba_cert_get_validity (subject_cert, 1, not_after);
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
do_list (1, listmode, listfp,
|
||||||
|
_("certificate with invalid validity: %s"), gpg_strerror (err));
|
||||||
|
return gpg_error (GPG_ERR_BAD_CERT);
|
||||||
|
}
|
||||||
|
if (!*not_before || !*not_after)
|
||||||
|
{
|
||||||
|
do_list (1, listmode, listfp,
|
||||||
|
_("required certificate attributes missing: %s%s%s"),
|
||||||
|
!*not_before? "notBefore":"",
|
||||||
|
(!*not_before && !*not_after)? ", ":"",
|
||||||
|
!*not_before? "notAfter":"");
|
||||||
|
return gpg_error (GPG_ERR_BAD_CERT);
|
||||||
|
}
|
||||||
|
if (strcmp (not_before, not_after) > 0 )
|
||||||
|
{
|
||||||
|
do_list (1, listmode, listfp,
|
||||||
|
_("certificate with invalid validity"));
|
||||||
|
log_info (" (valid from ");
|
||||||
|
gpgsm_dump_time (not_before);
|
||||||
|
log_printf (" expired at ");
|
||||||
|
gpgsm_dump_time (not_after);
|
||||||
|
log_printf (")\n");
|
||||||
|
return gpg_error (GPG_ERR_BAD_CERT);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!*exptime)
|
||||||
|
gnupg_copy_time (exptime, not_after);
|
||||||
|
else if (strcmp (not_after, exptime) < 0 )
|
||||||
|
gnupg_copy_time (exptime, not_after);
|
||||||
|
|
||||||
|
if (strcmp (current_time, not_before) < 0 )
|
||||||
|
{
|
||||||
|
do_list (1, listmode, listfp,
|
||||||
|
depth == 0 ? _("certificate not yet valid") :
|
||||||
|
depth == -1 ? _("root certificate not yet valid") :
|
||||||
|
/* other */ _("intermediate certificate not yet valid"));
|
||||||
|
if (!listmode)
|
||||||
|
{
|
||||||
|
log_info (" (valid from ");
|
||||||
|
gpgsm_dump_time (not_before);
|
||||||
|
log_printf (")\n");
|
||||||
|
}
|
||||||
|
return gpg_error (GPG_ERR_CERT_TOO_YOUNG);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*check_time
|
||||||
|
&& (strcmp (check_time, not_before) < 0
|
||||||
|
|| strcmp (check_time, not_after) > 0))
|
||||||
|
{
|
||||||
|
/* Note that we don't need a case for the root certificate
|
||||||
|
because its own consitency has already been checked. */
|
||||||
|
do_list(opt.ignore_expiration?0:1, listmode, listfp,
|
||||||
|
depth == 0 ?
|
||||||
|
_("signature not created during lifetime of certificate") :
|
||||||
|
depth == 1 ?
|
||||||
|
_("certificate not created during lifetime of issuer") :
|
||||||
|
_("intermediate certificate not created during lifetime "
|
||||||
|
"of issuer"));
|
||||||
|
if (!listmode)
|
||||||
|
{
|
||||||
|
log_info (depth== 0? _(" ( signature created at ") :
|
||||||
|
/* */ _(" (certificate created at ") );
|
||||||
|
gpgsm_dump_time (check_time);
|
||||||
|
log_printf (")\n");
|
||||||
|
log_info (depth==0? _(" (certificate valid from ") :
|
||||||
|
/* */ _(" ( issuer valid from ") );
|
||||||
|
gpgsm_dump_time (not_before);
|
||||||
|
log_info (" to ");
|
||||||
|
gpgsm_dump_time (not_after);
|
||||||
|
log_printf (")\n");
|
||||||
|
}
|
||||||
|
if (opt.ignore_expiration)
|
||||||
|
log_info ("WARNING: ignoring expiration\n");
|
||||||
|
else
|
||||||
|
return gpg_error (GPG_ERR_CERT_EXPIRED);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Ask the user whether he wants to mark the certificate CERT trusted.
|
||||||
|
Returns true if the CERT is the trusted. We also check whether the
|
||||||
|
agent is at all enabled to allow marktrusted and don't call it in
|
||||||
|
this session again if it is not. */
|
||||||
|
static int
|
||||||
|
ask_marktrusted (ctrl_t ctrl, ksba_cert_t cert, int listmode)
|
||||||
|
{
|
||||||
|
static int no_more_questions;
|
||||||
|
int rc;
|
||||||
|
char *fpr;
|
||||||
|
int success = 0;
|
||||||
|
|
||||||
|
fpr = gpgsm_get_fingerprint_string (cert, GCRY_MD_SHA1);
|
||||||
|
log_info (_("fingerprint=%s\n"), fpr? fpr : "?");
|
||||||
|
xfree (fpr);
|
||||||
|
|
||||||
|
if (no_more_questions)
|
||||||
|
rc = gpg_error (GPG_ERR_NOT_SUPPORTED);
|
||||||
|
else
|
||||||
|
rc = gpgsm_agent_marktrusted (ctrl, cert);
|
||||||
|
if (!rc)
|
||||||
|
{
|
||||||
|
log_info (_("root certificate has now been marked as trusted\n"));
|
||||||
|
success = 1;
|
||||||
|
}
|
||||||
|
else if (!listmode)
|
||||||
|
{
|
||||||
|
gpgsm_dump_cert ("issuer", cert);
|
||||||
|
log_info ("after checking the fingerprint, you may want "
|
||||||
|
"to add it manually to the list of trusted certificates.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gpg_err_code (rc) == GPG_ERR_NOT_SUPPORTED)
|
||||||
|
{
|
||||||
|
if (!no_more_questions)
|
||||||
|
log_info (_("interactive marking as trusted "
|
||||||
|
"not enabled in gpg-agent\n"));
|
||||||
|
no_more_questions = 1;
|
||||||
|
}
|
||||||
|
else if (gpg_err_code (rc) == GPG_ERR_CANCELED)
|
||||||
|
{
|
||||||
|
log_info (_("interactive marking as trusted "
|
||||||
|
"disabled for this session\n"));
|
||||||
|
no_more_questions = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
set_already_asked_marktrusted (cert);
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Validate a chain and optionally return the nearest expiration time
|
/* Validate a chain and optionally return the nearest expiration time
|
||||||
in R_EXPTIME. With LISTMODE set to 1 a special listmode is
|
in R_EXPTIME. With LISTMODE set to 1 a special listmode is
|
||||||
activated where only information about the certificate is printed
|
activated where only information about the certificate is printed
|
||||||
to FP and no output is send to the usual log stream.
|
to LISTFP and no output is send to the usual log stream. If
|
||||||
|
CHECKTIME_ARG is set, it is used only in the chain model instead of the
|
||||||
|
current time.
|
||||||
|
|
||||||
Defined flag bits: 0 - do not do any dirmngr isvalid checks.
|
Defined flag bits
|
||||||
|
|
||||||
|
VALIDATE_FLAG_NO_DIRMNGR - Do not do any dirmngr isvalid checks.
|
||||||
|
VALIDATE_FLAG_CHAIN_MODEL - Check according to chain model.
|
||||||
*/
|
*/
|
||||||
int
|
static int
|
||||||
gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime,
|
do_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t checktime_arg,
|
||||||
int listmode, estream_t fp, unsigned int flags)
|
ksba_isotime_t r_exptime,
|
||||||
|
int listmode, estream_t listfp, unsigned int flags,
|
||||||
|
struct rootca_flags_s *rootca_flags)
|
||||||
{
|
{
|
||||||
int rc = 0, depth = 0, maxdepth;
|
int rc = 0, depth, maxdepth;
|
||||||
char *issuer = NULL;
|
char *issuer = NULL;
|
||||||
char *subject = NULL;
|
char *subject = NULL;
|
||||||
KEYDB_HANDLE kh = NULL;
|
KEYDB_HANDLE kh = NULL;
|
||||||
ksba_cert_t subject_cert = NULL, issuer_cert = NULL;
|
ksba_cert_t subject_cert = NULL, issuer_cert = NULL;
|
||||||
ksba_isotime_t current_time;
|
ksba_isotime_t current_time;
|
||||||
|
ksba_isotime_t check_time;
|
||||||
ksba_isotime_t exptime;
|
ksba_isotime_t exptime;
|
||||||
int any_expired = 0;
|
int any_expired = 0;
|
||||||
int any_revoked = 0;
|
int any_revoked = 0;
|
||||||
@ -729,11 +1033,26 @@ gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime,
|
|||||||
int is_qualified = -1; /* Indicates whether the certificate stems
|
int is_qualified = -1; /* Indicates whether the certificate stems
|
||||||
from a qualified root certificate.
|
from a qualified root certificate.
|
||||||
-1 = unknown, 0 = no, 1 = yes. */
|
-1 = unknown, 0 = no, 1 = yes. */
|
||||||
int lm = listmode;
|
|
||||||
chain_item_t chain = NULL; /* A list of all certificates in the chain. */
|
chain_item_t chain = NULL; /* A list of all certificates in the chain. */
|
||||||
|
|
||||||
|
|
||||||
gnupg_get_isotime (current_time);
|
gnupg_get_isotime (current_time);
|
||||||
|
|
||||||
|
if ( (flags & VALIDATE_FLAG_CHAIN_MODEL) )
|
||||||
|
{
|
||||||
|
if (!strcmp (checktime_arg, "19700101T000000"))
|
||||||
|
{
|
||||||
|
do_list (1, listmode, listfp,
|
||||||
|
_("WARNING: creation time of signature not known - "
|
||||||
|
"assuming current time"));
|
||||||
|
gnupg_copy_time (check_time, current_time);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
gnupg_copy_time (check_time, checktime_arg);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
*check_time = 0;
|
||||||
|
|
||||||
if (r_exptime)
|
if (r_exptime)
|
||||||
*r_exptime = 0;
|
*r_exptime = 0;
|
||||||
*exptime = 0;
|
*exptime = 0;
|
||||||
@ -758,12 +1077,12 @@ gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime,
|
|||||||
subject_cert = cert;
|
subject_cert = cert;
|
||||||
ksba_cert_ref (subject_cert);
|
ksba_cert_ref (subject_cert);
|
||||||
maxdepth = 50;
|
maxdepth = 50;
|
||||||
|
depth = 0;
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
int is_root;
|
int is_root;
|
||||||
gpg_error_t istrusted_rc = -1;
|
gpg_error_t istrusted_rc = -1;
|
||||||
struct rootca_flags_s rootca_flags;
|
|
||||||
|
|
||||||
/* Put the certificate on our list. */
|
/* Put the certificate on our list. */
|
||||||
{
|
{
|
||||||
@ -788,13 +1107,16 @@ gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime,
|
|||||||
|
|
||||||
if (!issuer)
|
if (!issuer)
|
||||||
{
|
{
|
||||||
do_list (1, lm, fp, _("no issuer found in certificate"));
|
do_list (1, listmode, listfp, _("no issuer found in certificate"));
|
||||||
rc = gpg_error (GPG_ERR_BAD_CERT);
|
rc = gpg_error (GPG_ERR_BAD_CERT);
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Is this a self-issued certificate (i.e. the root certificate)? */
|
/* Is this a self-issued certificate (i.e. the root
|
||||||
|
certificate)? This is actually the same test as done by
|
||||||
|
gpgsm_is_root_cert but here we want to keep the issuer and
|
||||||
|
subject for later use. */
|
||||||
is_root = (subject && !strcmp (issuer, subject));
|
is_root = (subject && !strcmp (issuer, subject));
|
||||||
if (is_root)
|
if (is_root)
|
||||||
{
|
{
|
||||||
@ -804,71 +1126,41 @@ gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime,
|
|||||||
check right here so that we can access special flags
|
check right here so that we can access special flags
|
||||||
associated with that specific root certificate. */
|
associated with that specific root certificate. */
|
||||||
istrusted_rc = gpgsm_agent_istrusted (ctrl, subject_cert,
|
istrusted_rc = gpgsm_agent_istrusted (ctrl, subject_cert,
|
||||||
&rootca_flags);
|
rootca_flags);
|
||||||
|
/* If the chain model extended attribute is used, make sure
|
||||||
|
that our chain model flag is set. */
|
||||||
|
if (has_validation_model_chain (subject_cert, listmode, listfp))
|
||||||
|
rootca_flags->chain_model = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Check the validity period. */
|
/* Check the validity period. */
|
||||||
{
|
if ( (flags & VALIDATE_FLAG_CHAIN_MODEL) )
|
||||||
ksba_isotime_t not_before, not_after;
|
rc = check_validity_period_cm (current_time, check_time, subject_cert,
|
||||||
|
exptime, listmode, listfp,
|
||||||
rc = ksba_cert_get_validity (subject_cert, 0, not_before);
|
(depth && is_root)? -1: depth);
|
||||||
if (!rc)
|
else
|
||||||
rc = ksba_cert_get_validity (subject_cert, 1, not_after);
|
rc = check_validity_period (current_time, subject_cert,
|
||||||
if (rc)
|
exptime, listmode, listfp,
|
||||||
{
|
(depth && is_root)? -1: depth);
|
||||||
do_list (1, lm, fp, _("certificate with invalid validity: %s"),
|
if (gpg_err_code (rc) == GPG_ERR_CERT_EXPIRED)
|
||||||
gpg_strerror (rc));
|
{
|
||||||
rc = gpg_error (GPG_ERR_BAD_CERT);
|
any_expired = 1;
|
||||||
goto leave;
|
rc = 0;
|
||||||
}
|
}
|
||||||
|
else if (rc)
|
||||||
if (*not_after)
|
goto leave;
|
||||||
{
|
|
||||||
if (!*exptime)
|
|
||||||
gnupg_copy_time (exptime, not_after);
|
|
||||||
else if (strcmp (not_after, exptime) < 0 )
|
|
||||||
gnupg_copy_time (exptime, not_after);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*not_before && strcmp (current_time, not_before) < 0 )
|
|
||||||
{
|
|
||||||
do_list (1, lm, fp, _("certificate not yet valid"));
|
|
||||||
if (!lm)
|
|
||||||
{
|
|
||||||
log_info ("(valid from ");
|
|
||||||
gpgsm_dump_time (not_before);
|
|
||||||
log_printf (")\n");
|
|
||||||
}
|
|
||||||
rc = gpg_error (GPG_ERR_CERT_TOO_YOUNG);
|
|
||||||
goto leave;
|
|
||||||
}
|
|
||||||
if (*not_after && strcmp (current_time, not_after) > 0 )
|
|
||||||
{
|
|
||||||
do_list (opt.ignore_expiration?0:1, lm, fp,
|
|
||||||
_("certificate has expired"));
|
|
||||||
if (!lm)
|
|
||||||
{
|
|
||||||
log_info ("(expired at ");
|
|
||||||
gpgsm_dump_time (not_after);
|
|
||||||
log_printf (")\n");
|
|
||||||
}
|
|
||||||
if (opt.ignore_expiration)
|
|
||||||
log_info ("WARNING: ignoring expiration\n");
|
|
||||||
else
|
|
||||||
any_expired = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Assert that we understand all critical extensions. */
|
/* Assert that we understand all critical extensions. */
|
||||||
rc = unknown_criticals (subject_cert, listmode, fp);
|
rc = unknown_criticals (subject_cert, listmode, listfp);
|
||||||
if (rc)
|
if (rc)
|
||||||
goto leave;
|
goto leave;
|
||||||
|
|
||||||
/* Do a policy check. */
|
/* Do a policy check. */
|
||||||
if (!opt.no_policy_check)
|
if (!opt.no_policy_check)
|
||||||
{
|
{
|
||||||
rc = check_cert_policy (subject_cert, listmode, fp);
|
rc = check_cert_policy (subject_cert, listmode, listfp);
|
||||||
if (gpg_err_code (rc) == GPG_ERR_NO_POLICY_MATCH)
|
if (gpg_err_code (rc) == GPG_ERR_NO_POLICY_MATCH)
|
||||||
{
|
{
|
||||||
any_no_policy_match = 1;
|
any_no_policy_match = 1;
|
||||||
@ -879,7 +1171,7 @@ gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Is this a self-issued certificate? */
|
/* If this is the root certificate we are at the end of the chain. */
|
||||||
if (is_root)
|
if (is_root)
|
||||||
{
|
{
|
||||||
if (!istrusted_rc)
|
if (!istrusted_rc)
|
||||||
@ -888,7 +1180,7 @@ gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime,
|
|||||||
{
|
{
|
||||||
/* We only check the signature if the certificate is not
|
/* We only check the signature if the certificate is not
|
||||||
trusted for better diagnostics. */
|
trusted for better diagnostics. */
|
||||||
do_list (1, lm, fp,
|
do_list (1, listmode, listfp,
|
||||||
_("self-signed certificate has a BAD signature"));
|
_("self-signed certificate has a BAD signature"));
|
||||||
if (DBG_X509)
|
if (DBG_X509)
|
||||||
{
|
{
|
||||||
@ -898,9 +1190,9 @@ gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime,
|
|||||||
: GPG_ERR_BAD_CERT);
|
: GPG_ERR_BAD_CERT);
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
if (!rootca_flags.relax)
|
if (!rootca_flags->relax)
|
||||||
{
|
{
|
||||||
rc = allowed_ca (subject_cert, NULL, listmode, fp);
|
rc = allowed_ca (subject_cert, NULL, listmode, listfp);
|
||||||
if (rc)
|
if (rc)
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
@ -957,57 +1249,17 @@ gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime,
|
|||||||
;
|
;
|
||||||
else if (gpg_err_code (rc) == GPG_ERR_NOT_TRUSTED)
|
else if (gpg_err_code (rc) == GPG_ERR_NOT_TRUSTED)
|
||||||
{
|
{
|
||||||
do_list (0, lm, fp, _("root certificate is not marked trusted"));
|
do_list (0, listmode, listfp,
|
||||||
|
_("root certificate is not marked trusted"));
|
||||||
/* If we already figured out that the certificate is
|
/* If we already figured out that the certificate is
|
||||||
expired it does not make much sense to ask the user
|
expired it does not make much sense to ask the user
|
||||||
whether we wants to trust the root certificate. He
|
whether we wants to trust the root certificate. We
|
||||||
should do this only if the certificate under question
|
should do this only if the certificate under question
|
||||||
will then be usable. We also check whether the agent
|
will then be usable. */
|
||||||
is at all enabled to allo marktrusted and don't call
|
|
||||||
it in this session again if it is not. */
|
|
||||||
if ( !any_expired
|
if ( !any_expired
|
||||||
&& (!lm || !already_asked_marktrusted (subject_cert)))
|
&& (!listmode || !already_asked_marktrusted (subject_cert))
|
||||||
{
|
&& ask_marktrusted (ctrl, subject_cert, listmode) )
|
||||||
static int no_more_questions; /* during this session. */
|
rc = 0;
|
||||||
int rc2;
|
|
||||||
char *fpr = gpgsm_get_fingerprint_string (subject_cert,
|
|
||||||
GCRY_MD_SHA1);
|
|
||||||
log_info (_("fingerprint=%s\n"), fpr? fpr : "?");
|
|
||||||
xfree (fpr);
|
|
||||||
if (no_more_questions)
|
|
||||||
rc2 = gpg_error (GPG_ERR_NOT_SUPPORTED);
|
|
||||||
else
|
|
||||||
rc2 = gpgsm_agent_marktrusted (ctrl, subject_cert);
|
|
||||||
if (!rc2)
|
|
||||||
{
|
|
||||||
log_info (_("root certificate has now"
|
|
||||||
" been marked as trusted\n"));
|
|
||||||
rc = 0;
|
|
||||||
}
|
|
||||||
else if (!lm)
|
|
||||||
{
|
|
||||||
gpgsm_dump_cert ("issuer", subject_cert);
|
|
||||||
log_info ("after checking the fingerprint, you may want "
|
|
||||||
"to add it manually to the list of trusted "
|
|
||||||
"certificates.\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (gpg_err_code (rc2) == GPG_ERR_NOT_SUPPORTED)
|
|
||||||
{
|
|
||||||
if (!no_more_questions)
|
|
||||||
log_info (_("interactive marking as trusted "
|
|
||||||
"not enabled in gpg-agent\n"));
|
|
||||||
no_more_questions = 1;
|
|
||||||
}
|
|
||||||
else if (gpg_err_code (rc2) == GPG_ERR_CANCELED)
|
|
||||||
{
|
|
||||||
log_info (_("interactive marking as trusted "
|
|
||||||
"disabled for this session\n"));
|
|
||||||
no_more_questions = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
set_already_asked_marktrusted (subject_cert);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1019,12 +1271,14 @@ gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime,
|
|||||||
goto leave;
|
goto leave;
|
||||||
|
|
||||||
/* Check for revocations etc. */
|
/* Check for revocations etc. */
|
||||||
if ((flags & 1))
|
if ((flags & VALIDATE_FLAG_NO_DIRMNGR))
|
||||||
;
|
;
|
||||||
else if (opt.no_trusted_cert_crl_check || rootca_flags.relax)
|
else if (opt.no_trusted_cert_crl_check || rootca_flags->relax)
|
||||||
;
|
;
|
||||||
else
|
else
|
||||||
rc = is_cert_still_valid (ctrl, lm, fp,
|
rc = is_cert_still_valid (ctrl,
|
||||||
|
(flags & VALIDATE_FLAG_CHAIN_MODEL),
|
||||||
|
listmode, listfp,
|
||||||
subject_cert, subject_cert,
|
subject_cert, subject_cert,
|
||||||
&any_revoked, &any_no_crl,
|
&any_revoked, &any_no_crl,
|
||||||
&any_crl_too_old);
|
&any_crl_too_old);
|
||||||
@ -1032,13 +1286,13 @@ gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime,
|
|||||||
goto leave;
|
goto leave;
|
||||||
|
|
||||||
break; /* Okay: a self-signed certicate is an end-point. */
|
break; /* Okay: a self-signed certicate is an end-point. */
|
||||||
}
|
} /* End is_root. */
|
||||||
|
|
||||||
|
|
||||||
/* Take care that the chain does not get too long. */
|
/* Take care that the chain does not get too long. */
|
||||||
depth++;
|
if ((depth+1) > maxdepth)
|
||||||
if (depth > maxdepth)
|
|
||||||
{
|
{
|
||||||
do_list (1, lm, fp, _("certificate chain too long\n"));
|
do_list (1, listmode, listfp, _("certificate chain too long\n"));
|
||||||
rc = gpg_error (GPG_ERR_BAD_CERT_CHAIN);
|
rc = gpg_error (GPG_ERR_BAD_CERT_CHAIN);
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
@ -1050,8 +1304,8 @@ gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime,
|
|||||||
{
|
{
|
||||||
if (rc == -1)
|
if (rc == -1)
|
||||||
{
|
{
|
||||||
do_list (0, lm, fp, _("issuer certificate not found"));
|
do_list (0, listmode, listfp, _("issuer certificate not found"));
|
||||||
if (!lm)
|
if (!listmode)
|
||||||
{
|
{
|
||||||
log_info ("issuer certificate: #/");
|
log_info ("issuer certificate: #/");
|
||||||
gpgsm_dump_string (issuer);
|
gpgsm_dump_string (issuer);
|
||||||
@ -1083,7 +1337,7 @@ gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime,
|
|||||||
rc = gpgsm_check_cert_sig (issuer_cert, subject_cert);
|
rc = gpgsm_check_cert_sig (issuer_cert, subject_cert);
|
||||||
if (rc)
|
if (rc)
|
||||||
{
|
{
|
||||||
do_list (0, lm, fp, _("certificate has a BAD signature"));
|
do_list (0, listmode, listfp, _("certificate has a BAD signature"));
|
||||||
if (DBG_X509)
|
if (DBG_X509)
|
||||||
{
|
{
|
||||||
gpgsm_dump_cert ("signing issuer", issuer_cert);
|
gpgsm_dump_cert ("signing issuer", issuer_cert);
|
||||||
@ -1113,8 +1367,9 @@ gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
do_list (0, lm, fp, _("found another possible matching "
|
do_list (0, listmode, listfp,
|
||||||
"CA certificate - trying again"));
|
_("found another possible matching "
|
||||||
|
"CA certificate - trying again"));
|
||||||
ksba_cert_release (issuer_cert);
|
ksba_cert_release (issuer_cert);
|
||||||
issuer_cert = tmp_cert;
|
issuer_cert = tmp_cert;
|
||||||
goto try_another_cert;
|
goto try_another_cert;
|
||||||
@ -1128,14 +1383,15 @@ gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime,
|
|||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
is_root = 0;
|
is_root = gpgsm_is_root_cert (issuer_cert);
|
||||||
istrusted_rc = -1;
|
istrusted_rc = -1;
|
||||||
|
|
||||||
|
|
||||||
/* Check that a CA is allowed to issue certificates. */
|
/* Check that a CA is allowed to issue certificates. */
|
||||||
{
|
{
|
||||||
int chainlen;
|
int chainlen;
|
||||||
|
|
||||||
rc = allowed_ca (issuer_cert, &chainlen, listmode, fp);
|
rc = allowed_ca (issuer_cert, &chainlen, listmode, listfp);
|
||||||
if (rc)
|
if (rc)
|
||||||
{
|
{
|
||||||
/* Not allowed. Check whether this is a trusted root
|
/* Not allowed. Check whether this is a trusted root
|
||||||
@ -1146,12 +1402,11 @@ gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime,
|
|||||||
certificates carry proper BasicContraints our way of
|
certificates carry proper BasicContraints our way of
|
||||||
overriding an error in the way is justified for
|
overriding an error in the way is justified for
|
||||||
performance reasons. */
|
performance reasons. */
|
||||||
if (gpgsm_is_root_cert (issuer_cert))
|
if (is_root)
|
||||||
{
|
{
|
||||||
is_root = 1;
|
|
||||||
istrusted_rc = gpgsm_agent_istrusted (ctrl, issuer_cert,
|
istrusted_rc = gpgsm_agent_istrusted (ctrl, issuer_cert,
|
||||||
&rootca_flags);
|
rootca_flags);
|
||||||
if (!istrusted_rc && rootca_flags.relax)
|
if (!istrusted_rc && rootca_flags->relax)
|
||||||
{
|
{
|
||||||
/* Ignore the error due to the relax flag. */
|
/* Ignore the error due to the relax flag. */
|
||||||
rc = 0;
|
rc = 0;
|
||||||
@ -1161,9 +1416,9 @@ gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime,
|
|||||||
}
|
}
|
||||||
if (rc)
|
if (rc)
|
||||||
goto leave;
|
goto leave;
|
||||||
if (chainlen >= 0 && (depth - 1) > chainlen)
|
if (chainlen >= 0 && depth > chainlen)
|
||||||
{
|
{
|
||||||
do_list (1, lm, fp,
|
do_list (1, listmode, listfp,
|
||||||
_("certificate chain longer than allowed by CA (%d)"),
|
_("certificate chain longer than allowed by CA (%d)"),
|
||||||
chainlen);
|
chainlen);
|
||||||
rc = gpg_error (GPG_ERR_BAD_CERT_CHAIN);
|
rc = gpg_error (GPG_ERR_BAD_CERT_CHAIN);
|
||||||
@ -1188,13 +1443,15 @@ gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime,
|
|||||||
/* Check for revocations etc. Note that for a root certificate
|
/* Check for revocations etc. Note that for a root certificate
|
||||||
this test is done a second time later. This should eventually
|
this test is done a second time later. This should eventually
|
||||||
be fixed. */
|
be fixed. */
|
||||||
if ((flags & 1))
|
if ((flags & VALIDATE_FLAG_NO_DIRMNGR))
|
||||||
rc = 0;
|
rc = 0;
|
||||||
else if (is_root && (opt.no_trusted_cert_crl_check
|
else if (is_root && (opt.no_trusted_cert_crl_check
|
||||||
|| (!istrusted_rc && rootca_flags.relax)))
|
|| (!istrusted_rc && rootca_flags->relax)))
|
||||||
;
|
rc = 0;
|
||||||
else
|
else
|
||||||
rc = is_cert_still_valid (ctrl, lm, fp,
|
rc = is_cert_still_valid (ctrl,
|
||||||
|
(flags & VALIDATE_FLAG_CHAIN_MODEL),
|
||||||
|
listmode, listfp,
|
||||||
subject_cert, issuer_cert,
|
subject_cert, issuer_cert,
|
||||||
&any_revoked, &any_no_crl, &any_crl_too_old);
|
&any_revoked, &any_no_crl, &any_crl_too_old);
|
||||||
if (rc)
|
if (rc)
|
||||||
@ -1202,13 +1459,29 @@ gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime,
|
|||||||
|
|
||||||
|
|
||||||
if (opt.verbose && !listmode)
|
if (opt.verbose && !listmode)
|
||||||
log_info ("certificate is good\n");
|
log_info (depth == 0 ? _("certificate is good\n") :
|
||||||
|
!is_root ? _("intermediate certificate is good\n") :
|
||||||
|
/* other */ _("root certificate is good\n"));
|
||||||
|
|
||||||
|
/* Under the chain model the next check time is the creation
|
||||||
|
time of the subject certificate. */
|
||||||
|
if ( (flags & VALIDATE_FLAG_CHAIN_MODEL) )
|
||||||
|
{
|
||||||
|
rc = ksba_cert_get_validity (subject_cert, 0, check_time);
|
||||||
|
if (rc)
|
||||||
|
{
|
||||||
|
/* That will never happen as we have already checked
|
||||||
|
this above. */
|
||||||
|
BUG ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* For the next round the current issuer becomes the new subject. */
|
/* For the next round the current issuer becomes the new subject. */
|
||||||
keydb_search_reset (kh);
|
keydb_search_reset (kh);
|
||||||
ksba_cert_release (subject_cert);
|
ksba_cert_release (subject_cert);
|
||||||
subject_cert = issuer_cert;
|
subject_cert = issuer_cert;
|
||||||
issuer_cert = NULL;
|
issuer_cert = NULL;
|
||||||
|
depth++;
|
||||||
} /* End chain traversal. */
|
} /* End chain traversal. */
|
||||||
|
|
||||||
if (!listmode)
|
if (!listmode)
|
||||||
@ -1238,7 +1511,7 @@ gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime,
|
|||||||
|
|
||||||
leave:
|
leave:
|
||||||
/* If we have traversed a complete chain up to the root we will
|
/* If we have traversed a complete chain up to the root we will
|
||||||
reset the ephemeral flag for all these certificates. his is done
|
reset the ephemeral flag for all these certificates. This is done
|
||||||
regardless of any error because those errors may only be
|
regardless of any error because those errors may only be
|
||||||
transient. */
|
transient. */
|
||||||
if (chain && chain->is_root)
|
if (chain && chain->is_root)
|
||||||
@ -1306,6 +1579,61 @@ gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Validate a certifcate chain. For a description see the
|
||||||
|
do_validate_chain. This function is a wrapper to handle a root
|
||||||
|
certificate with the chain_model flag set. If RETFLAGS is not
|
||||||
|
NULL, flags indicating now the verification was done are stored
|
||||||
|
there. The only defined flag for RETFLAGS is
|
||||||
|
VALIDATE_FLAG_CHAIN_MODEL.
|
||||||
|
|
||||||
|
If you are verifying a signature you should set CHECKTIME to the
|
||||||
|
creation time of the signature. If your are verifying a
|
||||||
|
certificate, set it nil (i.e. the empty string). If the creation
|
||||||
|
date of the signature is not known use the special date
|
||||||
|
"19700101T000000" which is treated in a special way here. */
|
||||||
|
int
|
||||||
|
gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t checktime,
|
||||||
|
ksba_isotime_t r_exptime,
|
||||||
|
int listmode, estream_t listfp, unsigned int flags,
|
||||||
|
unsigned int *retflags)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
struct rootca_flags_s rootca_flags;
|
||||||
|
unsigned int dummy_retflags;
|
||||||
|
|
||||||
|
if (!retflags)
|
||||||
|
retflags = &dummy_retflags;
|
||||||
|
|
||||||
|
if (ctrl->validation_model == 1)
|
||||||
|
flags |= VALIDATE_FLAG_CHAIN_MODEL;
|
||||||
|
|
||||||
|
*retflags = (flags & VALIDATE_FLAG_CHAIN_MODEL);
|
||||||
|
memset (&rootca_flags, 0, sizeof rootca_flags);
|
||||||
|
|
||||||
|
rc = do_validate_chain (ctrl, cert, checktime,
|
||||||
|
r_exptime, listmode, listfp, flags,
|
||||||
|
&rootca_flags);
|
||||||
|
if (gpg_err_code (rc) == GPG_ERR_CERT_EXPIRED
|
||||||
|
&& !(flags & VALIDATE_FLAG_CHAIN_MODEL)
|
||||||
|
&& (rootca_flags.valid && rootca_flags.chain_model))
|
||||||
|
{
|
||||||
|
do_list (0, listmode, listfp, _("switching to chain model"));
|
||||||
|
rc = do_validate_chain (ctrl, cert, checktime,
|
||||||
|
r_exptime, listmode, listfp,
|
||||||
|
(flags |= VALIDATE_FLAG_CHAIN_MODEL),
|
||||||
|
&rootca_flags);
|
||||||
|
*retflags |= VALIDATE_FLAG_CHAIN_MODEL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opt.verbose)
|
||||||
|
do_list (0, listmode, listfp, _("validation model used: %s"),
|
||||||
|
(*retflags & VALIDATE_FLAG_CHAIN_MODEL)?
|
||||||
|
_("chain model"):_("shell model"));
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Check that the given certificate is valid but DO NOT check any
|
/* Check that the given certificate is valid but DO NOT check any
|
||||||
constraints. We assume that the issuers certificate is already in
|
constraints. We assume that the issuers certificate is already in
|
||||||
the DB and that this one is valid; which it should be because it
|
the DB and that this one is valid; which it should be because it
|
||||||
@ -1399,7 +1727,7 @@ gpgsm_basic_cert_check (ksba_cert_t cert)
|
|||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
if (opt.verbose)
|
if (opt.verbose)
|
||||||
log_info ("certificate is good\n");
|
log_info (_("certificate is good\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
leave:
|
leave:
|
||||||
|
@ -343,13 +343,17 @@ gpgsm_check_cert_sig (ksba_cert_t issuer_cert, ksba_cert_t cert)
|
|||||||
|
|
||||||
int
|
int
|
||||||
gpgsm_check_cms_signature (ksba_cert_t cert, ksba_const_sexp_t sigval,
|
gpgsm_check_cms_signature (ksba_cert_t cert, ksba_const_sexp_t sigval,
|
||||||
gcry_md_hd_t md, int algo)
|
gcry_md_hd_t md, int mdalgo, int *r_pkalgo)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
ksba_sexp_t p;
|
ksba_sexp_t p;
|
||||||
gcry_mpi_t frame;
|
gcry_mpi_t frame;
|
||||||
gcry_sexp_t s_sig, s_hash, s_pkey;
|
gcry_sexp_t s_sig, s_hash, s_pkey;
|
||||||
size_t n;
|
size_t n;
|
||||||
|
int pkalgo;
|
||||||
|
|
||||||
|
if (r_pkalgo)
|
||||||
|
*r_pkalgo = 0;
|
||||||
|
|
||||||
n = gcry_sexp_canon_len (sigval, 0, NULL, NULL);
|
n = gcry_sexp_canon_len (sigval, 0, NULL, NULL);
|
||||||
if (!n)
|
if (!n)
|
||||||
@ -385,8 +389,10 @@ gpgsm_check_cms_signature (ksba_cert_t cert, ksba_const_sexp_t sigval,
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pkalgo = pk_algo_from_sexp (s_pkey);
|
||||||
rc = do_encode_md (md, algo, pk_algo_from_sexp (s_pkey),
|
if (r_pkalgo)
|
||||||
|
*r_pkalgo = pkalgo;
|
||||||
|
rc = do_encode_md (md, mdalgo, pkalgo,
|
||||||
gcry_pk_get_nbits (s_pkey), s_pkey, &frame);
|
gcry_pk_get_nbits (s_pkey), s_pkey, &frame);
|
||||||
if (rc)
|
if (rc)
|
||||||
{
|
{
|
||||||
|
@ -71,10 +71,10 @@ gpgsm_print_serial (estream_t fp, ksba_const_sexp_t sn)
|
|||||||
p++;
|
p++;
|
||||||
n = strtoul (p, &endp, 10);
|
n = strtoul (p, &endp, 10);
|
||||||
p = endp;
|
p = endp;
|
||||||
if (*p!=':')
|
if (*p++ != ':')
|
||||||
es_fputs ("[Internal Error - invalid S-expression]", fp);
|
es_fputs ("[Internal Error - invalid S-expression]", fp);
|
||||||
else
|
else
|
||||||
es_write_hexstring (fp, p, strlen (p), 0, NULL);
|
es_write_hexstring (fp, p, n, 0, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -936,7 +936,7 @@ gpgsm_format_keydesc (ksba_cert_t cert)
|
|||||||
_("Please enter the passphrase to unlock the"
|
_("Please enter the passphrase to unlock the"
|
||||||
" secret key for:\n"
|
" secret key for:\n"
|
||||||
"\"%s\"\n"
|
"\"%s\"\n"
|
||||||
"S/N %s, ID %08lX, created %s" ),
|
"S/N %s, ID 0x%08lX, created %s" ),
|
||||||
subject? subject:"?",
|
subject? subject:"?",
|
||||||
sn? sn: "?",
|
sn? sn: "?",
|
||||||
gpgsm_get_short_fingerprint (cert),
|
gpgsm_get_short_fingerprint (cert),
|
||||||
|
@ -374,7 +374,8 @@ gpgsm_add_to_certlist (ctrl_t ctrl, const char *name, int secret,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!rc)
|
if (!rc)
|
||||||
rc = gpgsm_validate_chain (ctrl, cert, NULL, 0, NULL, 0);
|
rc = gpgsm_validate_chain (ctrl, cert, "", NULL,
|
||||||
|
0, NULL, 0, NULL);
|
||||||
if (!rc)
|
if (!rc)
|
||||||
{
|
{
|
||||||
certlist_t cl = xtrycalloc (1, sizeof *cl);
|
certlist_t cl = xtrycalloc (1, sizeof *cl);
|
||||||
|
49
sm/gpgsm.c
49
sm/gpgsm.c
@ -195,6 +195,7 @@ enum cmd_and_opt_values {
|
|||||||
oSetFilename,
|
oSetFilename,
|
||||||
oSetPolicyURL,
|
oSetPolicyURL,
|
||||||
oUseEmbeddedFilename,
|
oUseEmbeddedFilename,
|
||||||
|
oValidationModel,
|
||||||
oComment,
|
oComment,
|
||||||
oDefaultComment,
|
oDefaultComment,
|
||||||
oThrowKeyid,
|
oThrowKeyid,
|
||||||
@ -302,6 +303,8 @@ static ARGPARSE_OPTS opts[] = {
|
|||||||
{ oDisableOCSP, "disable-ocsp", 0, "@" },
|
{ oDisableOCSP, "disable-ocsp", 0, "@" },
|
||||||
{ oEnableOCSP, "enable-ocsp", 0, N_("check validity using OCSP")},
|
{ oEnableOCSP, "enable-ocsp", 0, N_("check validity using OCSP")},
|
||||||
|
|
||||||
|
{ oValidationModel, "validation-model", 2, "@"},
|
||||||
|
|
||||||
{ oIncludeCerts, "include-certs", 1,
|
{ oIncludeCerts, "include-certs", 1,
|
||||||
N_("|N|number of certificates to include") },
|
N_("|N|number of certificates to include") },
|
||||||
|
|
||||||
@ -423,7 +426,7 @@ static ARGPARSE_OPTS opts[] = {
|
|||||||
{ oLCmessages, "lc-messages", 2, "@" },
|
{ oLCmessages, "lc-messages", 2, "@" },
|
||||||
{ oDirmngrProgram, "dirmngr-program", 2 , "@" },
|
{ oDirmngrProgram, "dirmngr-program", 2 , "@" },
|
||||||
{ oProtectToolProgram, "protect-tool-program", 2 , "@" },
|
{ oProtectToolProgram, "protect-tool-program", 2 , "@" },
|
||||||
{ oFakedSystemTime, "faked-system-time", 4, "@" }, /* (epoch time) */
|
{ oFakedSystemTime, "faked-system-time", 2, "@" }, /* (epoch time) */
|
||||||
|
|
||||||
|
|
||||||
{ oNoBatch, "no-batch", 0, "@" },
|
{ oNoBatch, "no-batch", 0, "@" },
|
||||||
@ -472,6 +475,8 @@ static int allow_special_filenames;
|
|||||||
/* Default value for include-certs. */
|
/* Default value for include-certs. */
|
||||||
static int default_include_certs = 1; /* Only include the signer's cert. */
|
static int default_include_certs = 1; /* Only include the signer's cert. */
|
||||||
|
|
||||||
|
/* Whether the chain mode shall be used for validation. */
|
||||||
|
static int default_validation_model;
|
||||||
|
|
||||||
|
|
||||||
static char *build_list (const char *text,
|
static char *build_list (const char *text,
|
||||||
@ -700,6 +705,17 @@ do_add_recipient (ctrl_t ctrl, const char *name,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
parse_validation_model (const char *model)
|
||||||
|
{
|
||||||
|
int i = gpgsm_parse_validation_model (model);
|
||||||
|
if (i == -1)
|
||||||
|
log_error (_("unknown validation model `%s'\n"), model);
|
||||||
|
else
|
||||||
|
default_validation_model = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
main ( int argc, char **argv)
|
main ( int argc, char **argv)
|
||||||
{
|
{
|
||||||
@ -772,9 +788,6 @@ main ( int argc, char **argv)
|
|||||||
opt.def_cipher_algoid = "3DES"; /*des-EDE3-CBC*/
|
opt.def_cipher_algoid = "3DES"; /*des-EDE3-CBC*/
|
||||||
|
|
||||||
opt.homedir = default_homedir ();
|
opt.homedir = default_homedir ();
|
||||||
#ifdef HAVE_W32_SYSTEM
|
|
||||||
opt.no_crl_check = 1;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* First check whether we have a config file on the commandline */
|
/* First check whether we have a config file on the commandline */
|
||||||
orig_argc = argc;
|
orig_argc = argc;
|
||||||
@ -1095,7 +1108,12 @@ main ( int argc, char **argv)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case oFakedSystemTime:
|
case oFakedSystemTime:
|
||||||
gnupg_set_time ( (time_t)pargs.r.ret_ulong, 0);
|
{
|
||||||
|
time_t faked_time = isotime2epoch (pargs.r.ret_str);
|
||||||
|
if (faked_time == (time_t)(-1))
|
||||||
|
faked_time = (time_t)strtoul (pargs.r.ret_str, NULL, 10);
|
||||||
|
gnupg_set_time (faked_time, 0);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case oNoDefKeyring: default_keyring = 0; break;
|
case oNoDefKeyring: default_keyring = 0; break;
|
||||||
@ -1174,7 +1192,8 @@ main ( int argc, char **argv)
|
|||||||
case oNoRandomSeedFile: use_random_seed = 0; break;
|
case oNoRandomSeedFile: use_random_seed = 0; break;
|
||||||
|
|
||||||
case oEnableSpecialFilenames: allow_special_filenames =1; break;
|
case oEnableSpecialFilenames: allow_special_filenames =1; break;
|
||||||
|
|
||||||
|
case oValidationModel: parse_validation_model (pargs.r.ret_str); break;
|
||||||
|
|
||||||
case aDummy:
|
case aDummy:
|
||||||
break;
|
break;
|
||||||
@ -1201,7 +1220,11 @@ main ( int argc, char **argv)
|
|||||||
|
|
||||||
if (log_get_errorcount(0))
|
if (log_get_errorcount(0))
|
||||||
gpgsm_exit(2);
|
gpgsm_exit(2);
|
||||||
|
|
||||||
|
/* Now that we have the optiosn parsed we need to update the default
|
||||||
|
control structure. */
|
||||||
|
gpgsm_init_default_ctrl (&ctrl);
|
||||||
|
|
||||||
if (nogreeting)
|
if (nogreeting)
|
||||||
greeting = 0;
|
greeting = 0;
|
||||||
|
|
||||||
@ -1715,9 +1738,21 @@ gpgsm_init_default_ctrl (struct server_control_s *ctrl)
|
|||||||
{
|
{
|
||||||
ctrl->include_certs = default_include_certs;
|
ctrl->include_certs = default_include_certs;
|
||||||
ctrl->use_ocsp = opt.enable_ocsp;
|
ctrl->use_ocsp = opt.enable_ocsp;
|
||||||
|
ctrl->validation_model = default_validation_model;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
gpgsm_parse_validation_model (const char *model)
|
||||||
|
{
|
||||||
|
if (!ascii_strcasecmp (model, "shell") )
|
||||||
|
return 0;
|
||||||
|
else if ( !ascii_strcasecmp (model, "chain") )
|
||||||
|
return 1;
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Check whether the filename has the form "-&nnnn", where n is a
|
/* Check whether the filename has the form "-&nnnn", where n is a
|
||||||
non-zero number. Returns this number or -1 if it is not the case. */
|
non-zero number. Returns this number or -1 if it is not the case. */
|
||||||
|
17
sm/gpgsm.h
17
sm/gpgsm.h
@ -164,6 +164,7 @@ struct server_control_s
|
|||||||
certificates up the chain (0 = none, 1 = only
|
certificates up the chain (0 = none, 1 = only
|
||||||
signer) */
|
signer) */
|
||||||
int use_ocsp; /* Set to true if OCSP should be used. */
|
int use_ocsp; /* Set to true if OCSP should be used. */
|
||||||
|
int validation_model; /* Set to 1 for the chain model. */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -185,8 +186,10 @@ typedef struct certlist_s *certlist_t;
|
|||||||
/* A structure carrying information about trusted root certificates. */
|
/* A structure carrying information about trusted root certificates. */
|
||||||
struct rootca_flags_s
|
struct rootca_flags_s
|
||||||
{
|
{
|
||||||
|
unsigned int valid:1; /* The rest of the structure has valid
|
||||||
|
information. */
|
||||||
unsigned int relax:1; /* Relax checking of root certificates. */
|
unsigned int relax:1; /* Relax checking of root certificates. */
|
||||||
|
unsigned int chain_model:1; /* Root requires the use of the chain model. */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -194,6 +197,7 @@ struct rootca_flags_s
|
|||||||
/*-- gpgsm.c --*/
|
/*-- gpgsm.c --*/
|
||||||
void gpgsm_exit (int rc);
|
void gpgsm_exit (int rc);
|
||||||
void gpgsm_init_default_ctrl (struct server_control_s *ctrl);
|
void gpgsm_init_default_ctrl (struct server_control_s *ctrl);
|
||||||
|
int gpgsm_parse_validation_model (const char *model);
|
||||||
|
|
||||||
/*-- server.c --*/
|
/*-- server.c --*/
|
||||||
void gpgsm_server (certlist_t default_recplist);
|
void gpgsm_server (certlist_t default_recplist);
|
||||||
@ -253,7 +257,7 @@ char *gpgsm_format_keydesc (ksba_cert_t cert);
|
|||||||
/*-- certcheck.c --*/
|
/*-- certcheck.c --*/
|
||||||
int gpgsm_check_cert_sig (ksba_cert_t issuer_cert, ksba_cert_t cert);
|
int gpgsm_check_cert_sig (ksba_cert_t issuer_cert, ksba_cert_t cert);
|
||||||
int gpgsm_check_cms_signature (ksba_cert_t cert, ksba_const_sexp_t sigval,
|
int gpgsm_check_cms_signature (ksba_cert_t cert, ksba_const_sexp_t sigval,
|
||||||
gcry_md_hd_t md, int hash_algo);
|
gcry_md_hd_t md, int hash_algo, int *r_pkalgo);
|
||||||
/* fixme: move create functions to another file */
|
/* fixme: move create functions to another file */
|
||||||
int gpgsm_create_cms_signature (ctrl_t ctrl,
|
int gpgsm_create_cms_signature (ctrl_t ctrl,
|
||||||
ksba_cert_t cert, gcry_md_hd_t md, int mdalgo,
|
ksba_cert_t cert, gcry_md_hd_t md, int mdalgo,
|
||||||
@ -261,12 +265,19 @@ int gpgsm_create_cms_signature (ctrl_t ctrl,
|
|||||||
|
|
||||||
|
|
||||||
/*-- certchain.c --*/
|
/*-- certchain.c --*/
|
||||||
|
|
||||||
|
/* Flags used with gpgsm_validate_chain. */
|
||||||
|
#define VALIDATE_FLAG_NO_DIRMNGR 1
|
||||||
|
#define VALIDATE_FLAG_CHAIN_MODEL 2
|
||||||
|
|
||||||
|
|
||||||
int gpgsm_walk_cert_chain (ksba_cert_t start, ksba_cert_t *r_next);
|
int gpgsm_walk_cert_chain (ksba_cert_t start, ksba_cert_t *r_next);
|
||||||
int gpgsm_is_root_cert (ksba_cert_t cert);
|
int gpgsm_is_root_cert (ksba_cert_t cert);
|
||||||
int gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert,
|
int gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert,
|
||||||
|
ksba_isotime_t checktime,
|
||||||
ksba_isotime_t r_exptime,
|
ksba_isotime_t r_exptime,
|
||||||
int listmode, estream_t listfp,
|
int listmode, estream_t listfp,
|
||||||
unsigned int flags);
|
unsigned int flags, unsigned int *retflags);
|
||||||
int gpgsm_basic_cert_check (ksba_cert_t cert);
|
int gpgsm_basic_cert_check (ksba_cert_t cert);
|
||||||
|
|
||||||
/*-- certlist.c --*/
|
/*-- certlist.c --*/
|
||||||
|
@ -173,7 +173,7 @@ check_and_store (ctrl_t ctrl, struct stats_s *stats,
|
|||||||
*/
|
*/
|
||||||
rc = gpgsm_basic_cert_check (cert);
|
rc = gpgsm_basic_cert_check (cert);
|
||||||
if (!rc && ctrl->with_validation)
|
if (!rc && ctrl->with_validation)
|
||||||
rc = gpgsm_validate_chain (ctrl, cert, NULL, 0, NULL, 0);
|
rc = gpgsm_validate_chain (ctrl, cert, "", NULL, 0, NULL, 0, NULL);
|
||||||
if (!rc || (!ctrl->with_validation
|
if (!rc || (!ctrl->with_validation
|
||||||
&& gpg_err_code (rc) == GPG_ERR_MISSING_CERT) )
|
&& gpg_err_code (rc) == GPG_ERR_MISSING_CERT) )
|
||||||
{
|
{
|
||||||
|
36
sm/keylist.c
36
sm/keylist.c
@ -176,6 +176,9 @@ static struct
|
|||||||
/* GnuPG extensions */
|
/* GnuPG extensions */
|
||||||
{ "1.3.6.1.4.1.11591.2.1.1", "pkaAddress" },
|
{ "1.3.6.1.4.1.11591.2.1.1", "pkaAddress" },
|
||||||
|
|
||||||
|
/* Extensions used by the Bundesnetzagentur. */
|
||||||
|
{ "1.3.6.1.4.1.8301.3.5", "validityModel" },
|
||||||
|
|
||||||
{ NULL }
|
{ NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -345,9 +348,10 @@ list_cert_colon (ctrl_t ctrl, ksba_cert_t cert, unsigned int validity,
|
|||||||
const char *chain_id;
|
const char *chain_id;
|
||||||
char *chain_id_buffer = NULL;
|
char *chain_id_buffer = NULL;
|
||||||
int is_root = 0;
|
int is_root = 0;
|
||||||
|
char *kludge_uid;
|
||||||
|
|
||||||
if (ctrl->with_validation)
|
if (ctrl->with_validation)
|
||||||
valerr = gpgsm_validate_chain (ctrl, cert, NULL, 1, NULL, 0);
|
valerr = gpgsm_validate_chain (ctrl, cert, "", NULL, 1, NULL, 0, NULL);
|
||||||
else
|
else
|
||||||
valerr = 0;
|
valerr = 0;
|
||||||
|
|
||||||
@ -484,8 +488,15 @@ list_cert_colon (ctrl_t ctrl, ksba_cert_t cert, unsigned int validity,
|
|||||||
print_key_data (cert, fp);
|
print_key_data (cert, fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
kludge_uid = NULL;
|
||||||
for (idx=0; (p = ksba_cert_get_subject (cert,idx)); idx++)
|
for (idx=0; (p = ksba_cert_get_subject (cert,idx)); idx++)
|
||||||
{
|
{
|
||||||
|
/* In the case that the same email address is in the subecj DN
|
||||||
|
as weel as in an alternate subject name we avoid printing it
|
||||||
|
a second time. */
|
||||||
|
if (kludge_uid && !strcmp (kludge_uid, p))
|
||||||
|
continue;
|
||||||
|
|
||||||
es_fprintf (fp, "uid:%s::::::::", truststring);
|
es_fprintf (fp, "uid:%s::::::::", truststring);
|
||||||
es_write_sanitized (fp, p, strlen (p), ":", NULL);
|
es_write_sanitized (fp, p, strlen (p), ":", NULL);
|
||||||
es_putc (':', fp);
|
es_putc (':', fp);
|
||||||
@ -497,19 +508,20 @@ list_cert_colon (ctrl_t ctrl, ksba_cert_t cert, unsigned int validity,
|
|||||||
the keydb. But as long as we don't have a way to pass
|
the keydb. But as long as we don't have a way to pass
|
||||||
the meta data back, we just check it the same way as the
|
the meta data back, we just check it the same way as the
|
||||||
code used to create the keybox meta data does */
|
code used to create the keybox meta data does */
|
||||||
char *pp = email_kludge (p);
|
kludge_uid = email_kludge (p);
|
||||||
if (pp)
|
if (kludge_uid)
|
||||||
{
|
{
|
||||||
es_fprintf (fp, "uid:%s::::::::", truststring);
|
es_fprintf (fp, "uid:%s::::::::", truststring);
|
||||||
es_write_sanitized (fp, pp, strlen (pp), ":", NULL);
|
es_write_sanitized (fp, kludge_uid, strlen (kludge_uid),
|
||||||
|
":", NULL);
|
||||||
es_putc (':', fp);
|
es_putc (':', fp);
|
||||||
es_putc (':', fp);
|
es_putc (':', fp);
|
||||||
es_putc ('\n', fp);
|
es_putc ('\n', fp);
|
||||||
xfree (pp);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
xfree (p);
|
xfree (p);
|
||||||
}
|
}
|
||||||
|
xfree (kludge_uid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -570,8 +582,11 @@ list_cert_raw (ctrl_t ctrl, KEYDB_HANDLE hd,
|
|||||||
ksba_name_t name, name2;
|
ksba_name_t name, name2;
|
||||||
unsigned int reason;
|
unsigned int reason;
|
||||||
|
|
||||||
|
es_fprintf (fp, " ID: 0x%08lX\n",
|
||||||
|
gpgsm_get_short_fingerprint (cert));
|
||||||
|
|
||||||
sexp = ksba_cert_get_serial (cert);
|
sexp = ksba_cert_get_serial (cert);
|
||||||
es_fputs ("Serial number: ", fp);
|
es_fputs (" S/N: ", fp);
|
||||||
gpgsm_print_serial (fp, sexp);
|
gpgsm_print_serial (fp, sexp);
|
||||||
ksba_free (sexp);
|
ksba_free (sexp);
|
||||||
es_putc ('\n', fp);
|
es_putc ('\n', fp);
|
||||||
@ -887,7 +902,7 @@ list_cert_raw (ctrl_t ctrl, KEYDB_HANDLE hd,
|
|||||||
|
|
||||||
if (with_validation)
|
if (with_validation)
|
||||||
{
|
{
|
||||||
err = gpgsm_validate_chain (ctrl, cert, NULL, 1, fp, 0);
|
err = gpgsm_validate_chain (ctrl, cert, "", NULL, 1, fp, 0, NULL);
|
||||||
if (!err)
|
if (!err)
|
||||||
es_fprintf (fp, " [certificate is good]\n");
|
es_fprintf (fp, " [certificate is good]\n");
|
||||||
else
|
else
|
||||||
@ -924,8 +939,11 @@ list_cert_std (ctrl_t ctrl, ksba_cert_t cert, estream_t fp, int have_secret,
|
|||||||
unsigned int kusage;
|
unsigned int kusage;
|
||||||
char *string, *p, *pend;
|
char *string, *p, *pend;
|
||||||
|
|
||||||
|
es_fprintf (fp, " ID: 0x%08lX\n",
|
||||||
|
gpgsm_get_short_fingerprint (cert));
|
||||||
|
|
||||||
sexp = ksba_cert_get_serial (cert);
|
sexp = ksba_cert_get_serial (cert);
|
||||||
es_fputs ("Serial number: ", fp);
|
es_fputs (" S/N: ", fp);
|
||||||
gpgsm_print_serial (fp, sexp);
|
gpgsm_print_serial (fp, sexp);
|
||||||
ksba_free (sexp);
|
ksba_free (sexp);
|
||||||
es_putc ('\n', fp);
|
es_putc ('\n', fp);
|
||||||
@ -1088,7 +1106,7 @@ list_cert_std (ctrl_t ctrl, ksba_cert_t cert, estream_t fp, int have_secret,
|
|||||||
size_t buflen;
|
size_t buflen;
|
||||||
char buffer[1];
|
char buffer[1];
|
||||||
|
|
||||||
err = gpgsm_validate_chain (ctrl, cert, NULL, 1, fp, 0);
|
err = gpgsm_validate_chain (ctrl, cert, "", NULL, 1, fp, 0, NULL);
|
||||||
tmperr = ksba_cert_get_user_data (cert, "is_qualified",
|
tmperr = ksba_cert_get_user_data (cert, "is_qualified",
|
||||||
&buffer, sizeof (buffer), &buflen);
|
&buffer, sizeof (buffer), &buflen);
|
||||||
if (!tmperr && buflen)
|
if (!tmperr && buflen)
|
||||||
|
@ -244,6 +244,14 @@ option_handler (assuan_context_t ctx, const char *key, const char *value)
|
|||||||
int i = *value? atoi (value) : 0;
|
int i = *value? atoi (value) : 0;
|
||||||
ctrl->with_validation = i;
|
ctrl->with_validation = i;
|
||||||
}
|
}
|
||||||
|
else if (!strcmp (key, "validation-model"))
|
||||||
|
{
|
||||||
|
int i = gpgsm_parse_validation_model (value);
|
||||||
|
if ( i >= 0 && i <= 1 )
|
||||||
|
ctrl->validation_model = i;
|
||||||
|
else
|
||||||
|
return gpg_error (GPG_ERR_ASS_PARAMETER);
|
||||||
|
}
|
||||||
else if (!strcmp (key, "with-key-data"))
|
else if (!strcmp (key, "with-key-data"))
|
||||||
{
|
{
|
||||||
opt.with_key_data = 1;
|
opt.with_key_data = 1;
|
||||||
|
@ -380,7 +380,7 @@ gpgsm_sign (ctrl_t ctrl, certlist_t signerlist,
|
|||||||
check that the signer's certificate is usable and valid. */
|
check that the signer's certificate is usable and valid. */
|
||||||
rc = gpgsm_cert_use_sign_p (cert);
|
rc = gpgsm_cert_use_sign_p (cert);
|
||||||
if (!rc)
|
if (!rc)
|
||||||
rc = gpgsm_validate_chain (ctrl, cert, NULL, 0, NULL, 0);
|
rc = gpgsm_validate_chain (ctrl, cert, "", NULL, 0, NULL, 0, NULL);
|
||||||
if (rc)
|
if (rc)
|
||||||
goto leave;
|
goto leave;
|
||||||
|
|
||||||
|
52
sm/verify.c
52
sm/verify.c
@ -1,5 +1,5 @@
|
|||||||
/* verify.c - Verify a messages signature
|
/* verify.c - Verify a messages signature
|
||||||
* Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
|
* Copyright (C) 2001, 2002, 2003, 2007 Free Software Foundation, Inc.
|
||||||
*
|
*
|
||||||
* This file is part of GnuPG.
|
* This file is part of GnuPG.
|
||||||
*
|
*
|
||||||
@ -246,6 +246,8 @@ gpgsm_verify (ctrl_t ctrl, int in_fd, int data_fd, FILE *out_fp)
|
|||||||
char *msgdigest = NULL;
|
char *msgdigest = NULL;
|
||||||
size_t msgdigestlen;
|
size_t msgdigestlen;
|
||||||
char *ctattr;
|
char *ctattr;
|
||||||
|
int info_pkalgo;
|
||||||
|
unsigned int verifyflags;
|
||||||
|
|
||||||
rc = ksba_cms_get_issuer_serial (cms, signer, &issuer, &serial);
|
rc = ksba_cms_get_issuer_serial (cms, signer, &issuer, &serial);
|
||||||
if (!signer && gpg_err_code (rc) == GPG_ERR_NO_DATA
|
if (!signer && gpg_err_code (rc) == GPG_ERR_NO_DATA
|
||||||
@ -388,7 +390,7 @@ gpgsm_verify (ctrl_t ctrl, int in_fd, int data_fd, FILE *out_fp)
|
|||||||
gpgsm_dump_time (sigtime);
|
gpgsm_dump_time (sigtime);
|
||||||
else
|
else
|
||||||
log_printf (_("[date not given]"));
|
log_printf (_("[date not given]"));
|
||||||
log_printf (_(" using certificate ID %08lX\n"),
|
log_printf (_(" using certificate ID 0x%08lX\n"),
|
||||||
gpgsm_get_short_fingerprint (cert));
|
gpgsm_get_short_fingerprint (cert));
|
||||||
|
|
||||||
|
|
||||||
@ -432,12 +434,14 @@ gpgsm_verify (ctrl_t ctrl, int in_fd, int data_fd, FILE *out_fp)
|
|||||||
gcry_md_close (md);
|
gcry_md_close (md);
|
||||||
goto next_signer;
|
goto next_signer;
|
||||||
}
|
}
|
||||||
rc = gpgsm_check_cms_signature (cert, sigval, md, algo);
|
rc = gpgsm_check_cms_signature (cert, sigval, md, algo,
|
||||||
|
&info_pkalgo);
|
||||||
gcry_md_close (md);
|
gcry_md_close (md);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
rc = gpgsm_check_cms_signature (cert, sigval, data_md, algo);
|
rc = gpgsm_check_cms_signature (cert, sigval, data_md, algo,
|
||||||
|
&info_pkalgo);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rc)
|
if (rc)
|
||||||
@ -460,7 +464,10 @@ gpgsm_verify (ctrl_t ctrl, int in_fd, int data_fd, FILE *out_fp)
|
|||||||
|
|
||||||
if (DBG_X509)
|
if (DBG_X509)
|
||||||
log_debug ("signature okay - checking certs\n");
|
log_debug ("signature okay - checking certs\n");
|
||||||
rc = gpgsm_validate_chain (ctrl, cert, keyexptime, 0, NULL, 0);
|
rc = gpgsm_validate_chain (ctrl, cert,
|
||||||
|
*sigtime? sigtime : "19700101T000000",
|
||||||
|
keyexptime, 0,
|
||||||
|
NULL, 0, &verifyflags);
|
||||||
{
|
{
|
||||||
char *fpr, *buf, *tstr;
|
char *fpr, *buf, *tstr;
|
||||||
|
|
||||||
@ -477,10 +484,10 @@ gpgsm_verify (ctrl_t ctrl, int in_fd, int data_fd, FILE *out_fp)
|
|||||||
|
|
||||||
fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
|
fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
|
||||||
tstr = strtimestamp_r (sigtime);
|
tstr = strtimestamp_r (sigtime);
|
||||||
buf = xmalloc ( strlen(fpr) + strlen (tstr) + 120);
|
buf = xasprintf ("%s %s %s %s 0 0 %d %d 00", fpr, tstr,
|
||||||
sprintf (buf, "%s %s %s %s", fpr, tstr,
|
*sigtime? sigtime : "0",
|
||||||
*sigtime? sigtime : "0",
|
*keyexptime? keyexptime : "0",
|
||||||
*keyexptime? keyexptime : "0" );
|
info_pkalgo, algo);
|
||||||
xfree (tstr);
|
xfree (tstr);
|
||||||
xfree (fpr);
|
xfree (fpr);
|
||||||
gpgsm_status (ctrl, STATUS_VALIDSIG, buf);
|
gpgsm_status (ctrl, STATUS_VALIDSIG, buf);
|
||||||
@ -512,7 +519,32 @@ gpgsm_verify (ctrl_t ctrl, int in_fd, int data_fd, FILE *out_fp)
|
|||||||
ksba_free (p);
|
ksba_free (p);
|
||||||
}
|
}
|
||||||
|
|
||||||
gpgsm_status (ctrl, STATUS_TRUST_FULLY, NULL);
|
/* Print a note if this is a qualified signature. */
|
||||||
|
{
|
||||||
|
size_t qualbuflen;
|
||||||
|
char qualbuffer[1];
|
||||||
|
|
||||||
|
rc = ksba_cert_get_user_data (cert, "is_qualified", &qualbuffer,
|
||||||
|
sizeof (qualbuffer), &qualbuflen);
|
||||||
|
if (!rc && qualbuflen)
|
||||||
|
{
|
||||||
|
if (*qualbuffer)
|
||||||
|
{
|
||||||
|
log_info (_("This is a qualified signature\n"));
|
||||||
|
if (!opt.qualsig_approval)
|
||||||
|
log_info
|
||||||
|
(_("Note, that this software is not officially approved "
|
||||||
|
"to create or verify such signatures.\n"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (gpg_err_code (rc) != GPG_ERR_NOT_FOUND)
|
||||||
|
log_error ("get_user_data(is_qualified) failed: %s\n",
|
||||||
|
gpg_strerror (rc));
|
||||||
|
}
|
||||||
|
|
||||||
|
gpgsm_status (ctrl, STATUS_TRUST_FULLY,
|
||||||
|
(verifyflags & VALIDATE_FLAG_CHAIN_MODEL)?
|
||||||
|
"0 chain": "0 shell");
|
||||||
|
|
||||||
|
|
||||||
next_signer:
|
next_signer:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user