Page Menu
Home
GnuPG
Search
Configure Global Search
Log In
Files
F26446407
key-check.c
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Size
23 KB
Subscribers
None
key-check.c
View Options
/* key-check.c - Detect and fix various problems with keys
* Copyright (C) 1998-2010 Free Software Foundation, Inc.
* Copyright (C) 1998-2017 Werner Koch
* Copyright (C) 2015-2018 g10 Code GmbH
*
* This file is part of GnuPG.
*
* GnuPG is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* GnuPG is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#include
<config.h>
#include
"gpg.h"
#include
"options.h"
#include
"packet.h"
#include
"keydb.h"
#include
"main.h"
#include
"../common/ttyio.h"
#include
"../common/i18n.h"
#include
"keyedit.h"
#include
"key-check.h"
/* Print PREFIX followed by TEXT. With mode > 0 use log_info, with
* mode < 0 use ttyio, else print to stdout. If TEXT is not NULL, it
* may be modified by this function. */
static
void
print_info
(
int
mode
,
const
char
*
prefix
,
char
*
text
)
{
char
*
p
;
if
(
!
text
)
text
=
""
;
else
if
((
p
=
strchr
(
text
,
'\n'
)))
*
p
=
0
;
/* Strip LF. */
if
(
mode
>
0
)
log_info
(
"%s %s
\n
"
,
prefix
,
text
);
else
tty_fprintf
(
mode
?
NULL
:
es_stdout
,
"%s %s
\n
"
,
prefix
,
text
);
}
/* Order two signatures. The actual ordering isn't important. Our
* goal is to ensure that identical signatures occur together. */
static
int
sig_comparison
(
const
void
*
av
,
const
void
*
bv
)
{
const
KBNODE
an
=
*
(
const
KBNODE
*
)
av
;
const
KBNODE
bn
=
*
(
const
KBNODE
*
)
bv
;
const
PKT_signature
*
a
;
const
PKT_signature
*
b
;
int
ndataa
;
int
ndatab
;
int
i
;
log_assert
(
an
->
pkt
->
pkttype
==
PKT_SIGNATURE
);
log_assert
(
bn
->
pkt
->
pkttype
==
PKT_SIGNATURE
);
a
=
an
->
pkt
->
pkt
.
signature
;
b
=
bn
->
pkt
->
pkt
.
signature
;
/* Signatures with a different help counter are not identical for
* our purpose. */
if
(
a
->
help_counter
<
b
->
help_counter
)
return
-1
;
if
(
a
->
help_counter
>
b
->
help_counter
)
return
1
;
if
(
a
->
digest_algo
<
b
->
digest_algo
)
return
-1
;
if
(
a
->
digest_algo
>
b
->
digest_algo
)
return
1
;
ndataa
=
pubkey_get_nsig
(
a
->
pubkey_algo
);
ndatab
=
pubkey_get_nsig
(
b
->
pubkey_algo
);
if
(
ndataa
!=
ndatab
)
return
(
ndataa
<
ndatab
)
?
-1
:
1
;
for
(
i
=
0
;
i
<
ndataa
;
i
++
)
{
int
c
=
gcry_mpi_cmp
(
a
->
data
[
i
],
b
->
data
[
i
]);
if
(
c
!=
0
)
return
c
;
}
/* Okay, they are equal. */
return
0
;
}
static
gpg_error_t
remove_duplicate_sigs
(
kbnode_t
kb
,
int
*
dups
,
int
*
modified
)
{
gpg_error_t
err
;
kbnode_t
n
;
int
nsigs
;
kbnode_t
*
sigs
;
/* Allocated array with the signature packet. */
int
i
;
int
last_i
;
int
block
;
PKT_signature
*
sig
;
/* Count the sigs. */
for
(
nsigs
=
0
,
n
=
kb
;
n
;
n
=
n
->
next
)
{
if
(
is_deleted_kbnode
(
n
))
continue
;
else
if
(
n
->
pkt
->
pkttype
==
PKT_SIGNATURE
)
nsigs
++
;
}
if
(
!
nsigs
)
return
0
;
/* No signatures at all. */
/* Add them all to the SIGS array. */
sigs
=
xtrycalloc
(
nsigs
,
sizeof
*
sigs
);
if
(
!
sigs
)
{
err
=
gpg_error_from_syserror
();
log_error
(
_
(
"error allocating memory: %s
\n
"
),
gpg_strerror
(
err
));
return
err
;
}
block
=
0
;
i
=
0
;
for
(
n
=
kb
;
n
;
n
=
n
->
next
)
{
if
(
is_deleted_kbnode
(
n
))
continue
;
if
(
n
->
pkt
->
pkttype
!=
PKT_SIGNATURE
)
{
switch
(
n
->
pkt
->
pkttype
)
{
case
PKT_PUBLIC_SUBKEY
:
case
PKT_SECRET_SUBKEY
:
case
PKT_USER_ID
:
case
PKT_ATTRIBUTE
:
/* Bump the block number so that we only consider
* signatures below the same object as duplicates. */
block
++
;
break
;
default
:
break
;
}
continue
;
}
sig
=
n
->
pkt
->
pkt
.
signature
;
sig
->
help_counter
=
block
;
sigs
[
i
++
]
=
n
;
}
log_assert
(
i
==
nsigs
);
qsort
(
sigs
,
nsigs
,
sizeof
(
sigs
[
0
]),
sig_comparison
);
last_i
=
0
;
for
(
i
=
1
;
i
<
nsigs
;
i
++
)
{
log_assert
(
sigs
[
last_i
]);
log_assert
(
sigs
[
last_i
]
->
pkt
->
pkttype
==
PKT_SIGNATURE
);
log_assert
(
sigs
[
i
]);
log_assert
(
sigs
[
i
]
->
pkt
->
pkttype
==
PKT_SIGNATURE
);
if
(
sig_comparison
(
&
sigs
[
last_i
],
&
sigs
[
i
])
==
0
)
{
/* They are the same. Kill the latter. */
if
(
DBG_PACKET
)
{
sig
=
sigs
[
i
]
->
pkt
->
pkt
.
signature
;
log_debug
(
"Signature appears multiple times, "
"deleting duplicate:
\n
"
);
log_debug
(
" sig: class 0x%x, issuer: %s,"
" timestamp: %s (%lld), digest: %02x %02x
\n
"
,
sig
->
sig_class
,
keystr
(
sig
->
keyid
),
isotimestamp
(
sig
->
timestamp
),
(
long
long
)
sig
->
timestamp
,
sig
->
digest_start
[
0
],
sig
->
digest_start
[
1
]);
}
/* Remove sigs[i] from the keyblock. */
{
kbnode_t
z
,
*
prevp
;
int
to_kill
=
last_i
;
last_i
=
i
;
for
(
prevp
=
&
kb
,
z
=
kb
;
z
;
prevp
=
&
z
->
next
,
z
=
z
->
next
)
if
(
z
==
sigs
[
to_kill
])
break
;
*
prevp
=
sigs
[
to_kill
]
->
next
;
sigs
[
to_kill
]
->
next
=
NULL
;
release_kbnode
(
sigs
[
to_kill
]);
sigs
[
to_kill
]
=
NULL
;
++*
dups
;
*
modified
=
1
;
}
}
else
last_i
=
i
;
}
xfree
(
sigs
);
return
0
;
}
/* Perform a few sanity checks on a keyblock is okay and possibly
* repair some damage. Concretely:
*
* - Detect duplicate signatures and remove them.
*
* - Detect out of order signatures and relocate them (e.g., a sig
* over user id X located under subkey Y).
*
* Note: this function does not remove signatures that don't belong or
* components that are not signed! (Although it would be trivial to
* do so.)
*
* If ONLY_SELFSIGS is true, then this function only reorders self
* signatures (it still checks all signatures for duplicates,
* however).
*
* Allowed values for MODE are:
* -1 - print to the TTY
* 0 - print to stdout
* 1 - use log_info.
*
* Returns true if the keyblock was modified. */
int
key_check_all_keysigs
(
ctrl_t
ctrl
,
int
mode
,
kbnode_t
kb
,
int
only_selected
,
int
only_selfsigs
)
{
gpg_error_t
err
;
PKT_public_key
*
pk
;
KBNODE
n
,
n_next
,
*
n_prevp
,
n2
;
char
*
pending_desc
=
NULL
;
PKT_public_key
*
issuer
;
KBNODE
last_printed_component
;
KBNODE
current_component
=
NULL
;
int
dups
=
0
;
int
missing_issuer
=
0
;
int
reordered
=
0
;
int
bad_signature
=
0
;
int
missing_selfsig
=
0
;
int
modified
=
0
;
PKT_signature
*
sig
;
log_assert
(
kb
->
pkt
->
pkttype
==
PKT_PUBLIC_KEY
);
pk
=
kb
->
pkt
->
pkt
.
public_key
;
/* First we look for duplicates. */
if
(
remove_duplicate_sigs
(
kb
,
&
dups
,
&
modified
))
goto
leave
;
/* Error */
/* Now make sure the sigs occur after the component (aka block)
* (public key, subkey, user id) that they sign. */
issuer
=
NULL
;
last_printed_component
=
NULL
;
for
(
n_prevp
=
&
kb
,
n
=
kb
;
n
;
/* If we moved n, then n_prevp is need valid. */
n_prevp
=
(
n
->
next
==
n_next
?
&
n
->
next
:
n_prevp
),
n
=
n_next
)
{
PACKET
*
p
;
int
processed_current_component
;
int
rc
;
int
dump_sig_params
=
0
;
n_next
=
n
->
next
;
if
(
is_deleted_kbnode
(
n
))
continue
;
p
=
n
->
pkt
;
if
(
issuer
&&
issuer
!=
pk
)
{
free_public_key
(
issuer
);
issuer
=
NULL
;
}
xfree
(
pending_desc
);
pending_desc
=
NULL
;
switch
(
p
->
pkttype
)
{
case
PKT_PUBLIC_KEY
:
log_assert
(
p
->
pkt
.
public_key
==
pk
);
if
(
only_selected
&&
!
(
n
->
flag
&
NODFLG_SELKEY
))
{
current_component
=
NULL
;
break
;
}
if
(
DBG_PACKET
)
log_debug
(
"public key %s: timestamp: %s (%lld)
\n
"
,
pk_keyid_str
(
pk
),
isotimestamp
(
pk
->
timestamp
),
(
long
long
)
pk
->
timestamp
);
current_component
=
n
;
break
;
case
PKT_PUBLIC_SUBKEY
:
if
(
only_selected
&&
!
(
n
->
flag
&
NODFLG_SELKEY
))
{
current_component
=
NULL
;
break
;
}
if
(
DBG_PACKET
)
log_debug
(
"subkey %s: timestamp: %s (%lld)
\n
"
,
pk_keyid_str
(
p
->
pkt
.
public_key
),
isotimestamp
(
p
->
pkt
.
public_key
->
timestamp
),
(
long
long
)
p
->
pkt
.
public_key
->
timestamp
);
current_component
=
n
;
break
;
case
PKT_USER_ID
:
if
(
only_selected
&&
!
(
n
->
flag
&
NODFLG_SELUID
))
{
current_component
=
NULL
;
break
;
}
if
(
DBG_PACKET
)
log_debug
(
"user id: %s
\n
"
,
p
->
pkt
.
user_id
->
attrib_data
?
"[ photo id ]"
:
p
->
pkt
.
user_id
->
name
);
current_component
=
n
;
break
;
case
PKT_SIGNATURE
:
if
(
!
current_component
)
/* The current component is not selected, don't check the
sigs under it. */
break
;
sig
=
n
->
pkt
->
pkt
.
signature
;
pending_desc
=
xasprintf
(
" sig: class: 0x%x, issuer: %s,"
" timestamp: %s (%lld), digest: %02x %02x"
,
sig
->
sig_class
,
keystr
(
sig
->
keyid
),
isotimestamp
(
sig
->
timestamp
),
(
long
long
)
sig
->
timestamp
,
sig
->
digest_start
[
0
],
sig
->
digest_start
[
1
]);
if
(
keyid_cmp
(
pk_keyid
(
pk
),
sig
->
keyid
)
==
0
)
issuer
=
pk
;
else
/* Issuer is a different key. */
{
if
(
only_selfsigs
)
continue
;
issuer
=
xtrycalloc
(
1
,
sizeof
*
issuer
);
if
(
!
issuer
)
err
=
gpg_error_from_syserror
();
else
err
=
get_pubkey
(
ctrl
,
issuer
,
sig
->
keyid
);
if
(
err
)
{
xfree
(
issuer
);
issuer
=
NULL
;
if
(
DBG_PACKET
)
{
if
(
pending_desc
)
log_debug
(
"%s"
,
pending_desc
);
log_debug
(
" Can't check signature allegedly"
" issued by %s: %s
\n
"
,
keystr
(
sig
->
keyid
),
gpg_strerror
(
err
));
}
missing_issuer
++
;
break
;
}
}
if
((
err
=
openpgp_pk_test_algo
(
sig
->
pubkey_algo
)))
{
if
(
DBG_PACKET
&&
pending_desc
)
log_debug
(
"%s"
,
pending_desc
);
log_info
(
_
(
"can't check signature with unsupported"
" public-key algorithm (%d): %s.
\n
"
),
sig
->
pubkey_algo
,
gpg_strerror
(
err
));
break
;
}
if
((
err
=
openpgp_md_test_algo
(
sig
->
digest_algo
)))
{
if
(
DBG_PACKET
&&
pending_desc
)
log_debug
(
"%s"
,
pending_desc
);
log_info
(
_
(
"can't check signature with unsupported"
" message-digest algorithm %d: %s.
\n
"
),
sig
->
digest_algo
,
gpg_strerror
(
err
));
break
;
}
/* We iterate over the keyblock. Most likely, the matching
component is the current component so always try that
first. */
processed_current_component
=
0
;
for
(
n2
=
current_component
;
n2
;
n2
=
(
processed_current_component
?
n2
->
next
:
kb
),
processed_current_component
=
1
)
if
(
is_deleted_kbnode
(
n2
))
continue
;
else
if
(
processed_current_component
&&
n2
==
current_component
)
/* Don't process it twice. */
continue
;
else
{
err
=
check_signature_over_key_or_uid
(
ctrl
,
issuer
,
sig
,
kb
,
n2
->
pkt
,
NULL
,
NULL
);
if
(
!
err
)
break
;
}
/* n/sig is a signature and n2 is the component (public key,
subkey or user id) that it signs, if any.
current_component is that component that it appears to
apply to (according to the ordering). */
if
(
current_component
==
n2
)
{
if
(
DBG_PACKET
)
{
log_debug
(
"%s"
,
pending_desc
);
log_debug
(
" Good signature over last key or uid!
\n
"
);
}
rc
=
0
;
}
else
if
(
n2
)
{
log_assert
(
n2
->
pkt
->
pkttype
==
PKT_USER_ID
||
n2
->
pkt
->
pkttype
==
PKT_PUBLIC_KEY
||
n2
->
pkt
->
pkttype
==
PKT_PUBLIC_SUBKEY
);
if
(
DBG_PACKET
)
{
log_debug
(
"%s"
,
pending_desc
);
log_debug
(
" Good signature out of order!"
" (Over %s (%d) '%s')
\n
"
,
n2
->
pkt
->
pkttype
==
PKT_USER_ID
?
"user id"
:
n2
->
pkt
->
pkttype
==
PKT_PUBLIC_SUBKEY
?
"subkey"
:
"primary key"
,
n2
->
pkt
->
pkttype
,
n2
->
pkt
->
pkttype
==
PKT_USER_ID
?
n2
->
pkt
->
pkt
.
user_id
->
name
:
pk_keyid_str
(
n2
->
pkt
->
pkt
.
public_key
));
}
/* Reorder the packets: move the signature n to be just
after n2. */
/* Unlink the signature. */
log_assert
(
n_prevp
);
*
n_prevp
=
n
->
next
;
/* Insert the sig immediately after the component. */
n
->
next
=
n2
->
next
;
n2
->
next
=
n
;
reordered
++
;
modified
=
1
;
rc
=
0
;
}
else
{
if
(
DBG_PACKET
)
{
log_debug
(
"%s"
,
pending_desc
);
log_debug
(
" Bad signature.
\n
"
);
}
if
(
DBG_PACKET
)
dump_sig_params
=
1
;
bad_signature
++
;
rc
=
GPG_ERR_BAD_SIGNATURE
;
}
/* We don't cache the result here, because we haven't
completely checked that the signature is legitimate. For
instance, if we have a revocation certificate on Alice's
key signed by Bob, the signature may be good, but we
haven't checked that Bob is a designated revoker. */
/* cache_sig_result (sig, rc); */
{
int
has_selfsig
=
0
;
if
(
!
rc
&&
issuer
==
pk
)
{
if
(
n2
->
pkt
->
pkttype
==
PKT_PUBLIC_KEY
&&
(
/* Direct key signature. */
sig
->
sig_class
==
0x1f
/* Key revocation signature. */
||
sig
->
sig_class
==
0x20
))
has_selfsig
=
1
;
if
(
n2
->
pkt
->
pkttype
==
PKT_PUBLIC_SUBKEY
&&
(
/* Subkey binding sig. */
sig
->
sig_class
==
0x18
/* Subkey revocation sig. */
||
sig
->
sig_class
==
0x28
))
has_selfsig
=
1
;
if
(
n2
->
pkt
->
pkttype
==
PKT_USER_ID
&&
(
/* Certification sigs. */
sig
->
sig_class
==
0x10
||
sig
->
sig_class
==
0x11
||
sig
->
sig_class
==
0x12
||
sig
->
sig_class
==
0x13
/* Certification revocation sig. */
||
sig
->
sig_class
==
0x30
))
has_selfsig
=
1
;
}
if
(
DBG_PACKET
&&
((
n2
&&
n2
!=
last_printed_component
)
||
(
!
n2
&&
last_printed_component
!=
current_component
)))
{
int
is_reordered
=
n2
&&
n2
!=
current_component
;
if
(
n2
)
last_printed_component
=
n2
;
else
last_printed_component
=
current_component
;
if
(
!
modified
)
;
else
if
(
last_printed_component
->
pkt
->
pkttype
==
PKT_USER_ID
)
{
log_debug
(
"uid "
);
print_utf8_buffer
(
log_get_stream
(),
last_printed_component
->
pkt
->
pkt
.
user_id
->
name
,
last_printed_component
->
pkt
->
pkt
.
user_id
->
len
);
log_flush
();
}
else
if
(
last_printed_component
->
pkt
->
pkttype
==
PKT_PUBLIC_KEY
)
log_debug
(
"pub %s
\n
"
,
pk_keyid_str
(
last_printed_component
->
pkt
->
pkt
.
public_key
));
else
log_debug
(
"sub %s
\n
"
,
pk_keyid_str
(
last_printed_component
->
pkt
->
pkt
.
public_key
));
if
(
modified
)
{
if
(
is_reordered
)
log_debug
(
"%s
\n
"
,
_
(
" (reordered signatures follow)"
));
}
}
if
(
DBG_PACKET
&&
modified
)
keyedit_print_one_sig
(
ctrl
,
log_get_stream
(),
rc
,
kb
,
n
,
NULL
,
NULL
,
NULL
,
has_selfsig
,
0
,
only_selfsigs
);
}
if
(
dump_sig_params
)
{
int
i
;
for
(
i
=
0
;
i
<
pubkey_get_nsig
(
sig
->
pubkey_algo
);
i
++
)
{
char
buffer
[
1024
];
size_t
len
;
char
*
printable
;
gcry_mpi_print
(
GCRYMPI_FMT_USG
,
buffer
,
sizeof
(
buffer
),
&
len
,
sig
->
data
[
i
]);
printable
=
bin2hex
(
buffer
,
len
,
NULL
);
log_debug
(
" %d: %s
\n
"
,
i
,
printable
);
xfree
(
printable
);
}
}
break
;
default
:
if
(
DBG_PACKET
)
log_debug
(
"unhandled packet: %d
\n
"
,
p
->
pkttype
);
break
;
}
}
xfree
(
pending_desc
);
pending_desc
=
NULL
;
if
(
issuer
!=
pk
)
free_public_key
(
issuer
);
issuer
=
NULL
;
/* If we reordered signatures we need to de-duplicate again because
* a signature can now be a duplicate in another block. */
if
(
reordered
)
{
if
(
remove_duplicate_sigs
(
kb
,
&
dups
,
&
modified
))
goto
leave
;
}
/* Identify keys / uids that don't have a self-sig. */
{
int
has_selfsig
=
0
;
PACKET
*
p
;
current_component
=
NULL
;
for
(
n
=
kb
;
n
;
n
=
n
->
next
)
{
if
(
is_deleted_kbnode
(
n
))
continue
;
p
=
n
->
pkt
;
switch
(
p
->
pkttype
)
{
case
PKT_PUBLIC_KEY
:
case
PKT_PUBLIC_SUBKEY
:
case
PKT_USER_ID
:
if
(
current_component
&&
!
has_selfsig
)
missing_selfsig
++
;
current_component
=
n
;
has_selfsig
=
0
;
break
;
case
PKT_SIGNATURE
:
if
(
!
current_component
||
has_selfsig
)
break
;
sig
=
n
->
pkt
->
pkt
.
signature
;
if
(
!
(
sig
->
flags
.
checked
&&
sig
->
flags
.
valid
))
break
;
if
(
keyid_cmp
(
pk_keyid
(
pk
),
sig
->
keyid
)
!=
0
)
/* Different issuer, couldn't be a self-sig. */
break
;
if
(
current_component
->
pkt
->
pkttype
==
PKT_PUBLIC_KEY
&&
(
/* Direct key signature. */
sig
->
sig_class
==
0x1f
/* Key revocation signature. */
||
sig
->
sig_class
==
0x20
))
has_selfsig
=
1
;
if
(
current_component
->
pkt
->
pkttype
==
PKT_PUBLIC_SUBKEY
&&
(
/* Subkey binding sig. */
sig
->
sig_class
==
0x18
/* Subkey revocation sig. */
||
sig
->
sig_class
==
0x28
))
has_selfsig
=
1
;
if
(
current_component
->
pkt
->
pkttype
==
PKT_USER_ID
&&
(
/* Certification sigs. */
sig
->
sig_class
==
0x10
||
sig
->
sig_class
==
0x11
||
sig
->
sig_class
==
0x12
||
sig
->
sig_class
==
0x13
/* Certification revocation sig. */
||
sig
->
sig_class
==
0x30
))
has_selfsig
=
1
;
break
;
default
:
if
(
current_component
&&
!
has_selfsig
)
missing_selfsig
++
;
current_component
=
NULL
;
}
}
}
leave
:
if
(
!
opt
.
quiet
)
{
char
prefix
[
100
];
char
*
p
;
/* To avoid string changes in 2.2 we strip the LF here. */
snprintf
(
prefix
,
sizeof
prefix
,
_
(
"key %s:
\n
"
),
pk_keyid_str
(
pk
));
p
=
strrchr
(
prefix
,
'\n'
);
if
(
p
)
*
p
=
0
;
if
(
dups
)
{
p
=
xtryasprintf
(
ngettext
(
"%d duplicate signature removed
\n
"
,
"%d duplicate signatures removed
\n
"
,
dups
),
dups
);
print_info
(
mode
,
prefix
,
p
);
xfree
(
p
);
}
if
(
missing_issuer
)
{
p
=
xtryasprintf
(
ngettext
(
"%d signature not checked due to a missing key
\n
"
,
"%d signatures not checked due to missing keys
\n
"
,
missing_issuer
),
missing_issuer
);
print_info
(
mode
,
prefix
,
p
);
xfree
(
p
);
}
if
(
bad_signature
)
{
p
=
xtryasprintf
(
ngettext
(
"%d bad signature
\n
"
,
"%d bad signatures
\n
"
,
bad_signature
),
bad_signature
);
print_info
(
mode
,
prefix
,
p
);
xfree
(
p
);
}
if
(
reordered
)
{
p
=
xtryasprintf
(
ngettext
(
"%d signature reordered
\n
"
,
"%d signatures reordered
\n
"
,
reordered
),
reordered
);
print_info
(
mode
,
prefix
,
p
);
xfree
(
p
);
}
if
(
only_selfsigs
&&
(
bad_signature
||
reordered
))
{
p
=
xtryasprintf
(
_
(
"Warning: errors found and only checked self-signatures,"
" run '%s' to check all signatures.
\n
"
),
"check"
);
print_info
(
mode
,
prefix
,
p
);
xfree
(
p
);
}
}
return
modified
;
}
File Metadata
Details
Attached
Mime Type
text/x-c
Expires
Thu, Jul 17, 12:59 AM (1 d, 18 h)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
1c/77/bec6c5e555add1dc7b47987a87d1
Attached To
rG GnuPG
Event Timeline
Log In to Comment