mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-22 10:19:57 +01:00
Update head to match stable 1.0
This commit is contained in:
parent
151ee2f47b
commit
3f51f7db3d
3765
g10/ChangeLog
3765
g10/ChangeLog
File diff suppressed because it is too large
Load Diff
139
g10/Makefile.am
139
g10/Makefile.am
@ -1,84 +1,104 @@
|
||||
# Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is part of GnuPG.
|
||||
#
|
||||
# GnuPG is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# GnuPG is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
|
||||
## Process this file with automake to produce Makefile.in
|
||||
|
||||
INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/intl
|
||||
EXTRA_DIST = OPTIONS pubring.asc options.skel
|
||||
OMIT_DEPENDENCIES = zlib.h zconf.h
|
||||
LDFLAGS = @LDFLAGS@ $(LIBGCRYPT_LIBS)
|
||||
# we need to add libutil.la a second time because we have to resolve
|
||||
# gpg_log_ in some libjnlib modules. - very ugly - should be removed soon.
|
||||
needed_libs = ../util/libutil.a \
|
||||
../jnlib/libjnlib.a ../util/libutil.a
|
||||
INCLUDES = -I.. -I$(top_srcdir)/include -I$(top_srcdir)/intl
|
||||
EXTRA_DIST = options.skel
|
||||
# it seems that we can't use this with automake 1.5
|
||||
#OMIT_DEPENDENCIES = zlib.h zconf.h
|
||||
LDFLAGS = @LDFLAGS@ @DYNLINK_LDFLAGS@
|
||||
needed_libs = ../cipher/libcipher.a ../mpi/libmpi.a ../util/libutil.a
|
||||
|
||||
#noinst_PROGRAMS = gpgd
|
||||
#bin_PROGRAMS = gpg kbxutil
|
||||
noinst_PROGRAMS = gpg kbxutil
|
||||
bin_PROGRAMS = gpg gpgv
|
||||
|
||||
common_source = \
|
||||
global.h \
|
||||
build-packet.c \
|
||||
compress.c \
|
||||
basicdefs.h \
|
||||
filter.h \
|
||||
free-packet.c \
|
||||
getkey.c \
|
||||
keydb.h \
|
||||
delkey.c \
|
||||
pkclist.c \
|
||||
skclist.c \
|
||||
ringedit.c \
|
||||
keydb.c keydb.h \
|
||||
keyring.c keyring.h \
|
||||
seskey.c \
|
||||
kbnode.c \
|
||||
kbx.h \
|
||||
kbxblob.c \
|
||||
kbxio.c \
|
||||
kbxfile.c \
|
||||
main.h \
|
||||
mainproc.c \
|
||||
armor.c \
|
||||
mdfilter.c \
|
||||
textfilter.c \
|
||||
cipher.c \
|
||||
misc.c \
|
||||
options.h \
|
||||
openfile.c \
|
||||
keyid.c \
|
||||
packet.h \
|
||||
parse-packet.c \
|
||||
comment.c \
|
||||
status.c \
|
||||
status.h \
|
||||
plaintext.c \
|
||||
sig-check.c \
|
||||
keylist.c \
|
||||
signal.c
|
||||
|
||||
gpg_SOURCES = g10.c \
|
||||
$(common_source) \
|
||||
pkclist.c \
|
||||
skclist.c \
|
||||
pubkey-enc.c \
|
||||
passphrase.c \
|
||||
seckey-cert.c \
|
||||
encr-data.c \
|
||||
cipher.c \
|
||||
encode.c \
|
||||
sign.c \
|
||||
verify.c \
|
||||
revoke.c \
|
||||
decrypt.c \
|
||||
keyedit.c \
|
||||
dearmor.c \
|
||||
import.c \
|
||||
export.c \
|
||||
hkp.h \
|
||||
hkp.c \
|
||||
trustdb.c \
|
||||
trustdb.h \
|
||||
tdbdump.c \
|
||||
tdbio.c \
|
||||
tdbio.h \
|
||||
hkp.h \
|
||||
hkp.c \
|
||||
packet.h \
|
||||
parse-packet.c \
|
||||
passphrase.c \
|
||||
pubkey-enc.c \
|
||||
seckey-cert.c \
|
||||
seskey.c \
|
||||
import.c \
|
||||
export.c \
|
||||
comment.c \
|
||||
status.c \
|
||||
status.h \
|
||||
sign.c \
|
||||
plaintext.c \
|
||||
encr-data.c \
|
||||
encode.c \
|
||||
revoke.c \
|
||||
keylist.c \
|
||||
sig-check.c \
|
||||
signal.c \
|
||||
helptext.c
|
||||
delkey.c \
|
||||
keygen.c \
|
||||
pipemode.c \
|
||||
helptext.c \
|
||||
keyserver.c \
|
||||
keyserver-internal.h \
|
||||
photoid.c photoid.h \
|
||||
exec.c exec.h
|
||||
|
||||
|
||||
|
||||
gpgv_SOURCES = gpgv.c \
|
||||
$(common_source) \
|
||||
verify.c
|
||||
|
||||
gpg_SOURCES = gpg.c \
|
||||
$(common_source) \
|
||||
verify.c \
|
||||
decrypt.c \
|
||||
keyedit.c \
|
||||
dearmor.c \
|
||||
keygen.c
|
||||
|
||||
# fixme: remove unused sources from kbxutil
|
||||
kbxutil_SOURCES = kbxutil.c \
|
||||
$(common_source)
|
||||
|
||||
|
||||
#gpgd_SOURCES = gpgd.c \
|
||||
@ -88,15 +108,18 @@ kbxutil_SOURCES = kbxutil.c \
|
||||
# ks-db.h \
|
||||
# $(common_source)
|
||||
|
||||
|
||||
LDADD = $(needed_libs) @ZLIBS@ @INTLLIBS@
|
||||
|
||||
LDADD = $(needed_libs) @ZLIBS@ @INTLLIBS@
|
||||
# gpg gets LIBOBJS to add in mkdtemp if the platform doesn't have it
|
||||
gpg_LDADD = @LIBOBJS@ $(LDADD) @NETLIBS@
|
||||
|
||||
$(PROGRAMS): $(needed_libs)
|
||||
|
||||
|
||||
install-data-local:
|
||||
$(mkinstalldirs) $(DESTDIR)$(pkgdatadir)
|
||||
$(INSTALL_DATA) $(srcdir)/options.skel \
|
||||
$(DESTDIR)$(pkgdatadir)/options.skel
|
||||
|
||||
@set -e;\
|
||||
if test -f $(DESTDIR)$(bindir)/gpgm ; then \
|
||||
echo "removing obsolete gpgm binary" ; \
|
||||
rm $(DESTDIR)$(bindir)/gpgm ; \
|
||||
fi
|
||||
|
378
g10/armor.c
378
g10/armor.c
@ -1,5 +1,5 @@
|
||||
/* armor.c - Armor flter
|
||||
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
|
||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
@ -28,7 +28,7 @@
|
||||
|
||||
#include "errors.h"
|
||||
#include "iobuf.h"
|
||||
#include <gcrypt.h>
|
||||
#include "memory.h"
|
||||
#include "util.h"
|
||||
#include "filter.h"
|
||||
#include "packet.h"
|
||||
@ -151,8 +151,9 @@ initialize(void)
|
||||
}
|
||||
|
||||
/****************
|
||||
* Check whether this is an armored file or not
|
||||
* See also parse-packet.c for details on this code
|
||||
* Check whether this is an armored file or not See also
|
||||
* parse-packet.c for details on this code For unknown historic
|
||||
* reasons we use a string here but only the first byte will be used.
|
||||
* Returns: True if it seems to be armored
|
||||
*/
|
||||
static int
|
||||
@ -195,6 +196,7 @@ use_armor_filter( IOBUF a )
|
||||
byte buf[1];
|
||||
int n;
|
||||
|
||||
/* fixme: there might be a problem with iobuf_peek */
|
||||
n = iobuf_peek(a, buf, 1 );
|
||||
if( n == -1 )
|
||||
return 0; /* EOF, doesn't matter whether armored or not */
|
||||
@ -210,7 +212,7 @@ static void
|
||||
invalid_armor(void)
|
||||
{
|
||||
write_status(STATUS_BADARMOR);
|
||||
gpg_exit(1); /* stop here */
|
||||
g10_exit(1); /* stop here */
|
||||
}
|
||||
|
||||
|
||||
@ -245,7 +247,9 @@ parse_hash_header( const char *line )
|
||||
found |= 2;
|
||||
else if( !strncmp( s, "MD5", s2-s ) )
|
||||
found |= 4;
|
||||
else if( !strncmp( s, "TIGER", s2-s ) )
|
||||
else if( !strncmp( s, "TIGER192", s2-s ) )
|
||||
found |= 8;
|
||||
else if( !strncmp( s, "TIGER", s2-s ) ) /* used by old versions */
|
||||
found |= 8;
|
||||
else
|
||||
return 0;
|
||||
@ -283,6 +287,14 @@ is_armor_header( byte *line, unsigned len )
|
||||
return -1;
|
||||
save_p = p;
|
||||
p += 5;
|
||||
|
||||
/* Some mail programs on Windows seem to add spaces to the end of
|
||||
the line. This becomes strict if --openpgp is set. */
|
||||
|
||||
if(!opt.rfc2440)
|
||||
while(*p==' ')
|
||||
p++;
|
||||
|
||||
if( *p == '\r' )
|
||||
p++;
|
||||
if( *p == '\n' )
|
||||
@ -312,19 +324,19 @@ is_armor_header( byte *line, unsigned len )
|
||||
* >0: Good header line
|
||||
*/
|
||||
static int
|
||||
parse_header_line( armor_filter_context_t *afx, byte *line, unsigned len )
|
||||
parse_header_line( armor_filter_context_t *afx, byte *line, unsigned int len )
|
||||
{
|
||||
byte *p;
|
||||
int hashes=0;
|
||||
unsigned int len2;
|
||||
|
||||
/* fixme: why this double check? I think the original code w/o the
|
||||
* second check for an empty line was done from an early draft of
|
||||
* of OpenPGP - or simply very stupid code */
|
||||
if( *line == '\n' || ( len && (*line == '\r' && line[1]=='\n') ) )
|
||||
return 0; /* empty line */
|
||||
len = trim_trailing_ws( line, len );
|
||||
if( !len )
|
||||
return 0; /* WS only same as empty line */
|
||||
len2 = check_trailing_ws( line, len );
|
||||
if( !len2 ) {
|
||||
afx->buffer_pos = len2; /* (it is not the fine way to do it here) */
|
||||
return 0; /* WS only: same as empty line */
|
||||
}
|
||||
len = len2;
|
||||
line[len2] = 0;
|
||||
|
||||
p = strchr( line, ':');
|
||||
if( !p || !p[1] ) {
|
||||
@ -399,7 +411,7 @@ check_input( armor_filter_context_t *afx, IOBUF a )
|
||||
if( hdr_line == BEGIN_SIGNED_MSG_IDX ) {
|
||||
if( afx->in_cleartext ) {
|
||||
log_error(_("nested clear text signatures\n"));
|
||||
rc = GPGERR_INVALID_ARMOR;
|
||||
rc = G10ERR_INVALID_ARMOR;
|
||||
}
|
||||
afx->in_cleartext = 1;
|
||||
}
|
||||
@ -429,7 +441,7 @@ check_input( armor_filter_context_t *afx, IOBUF a )
|
||||
i = parse_header_line( afx, line, len );
|
||||
if( i <= 0 ) {
|
||||
if( i )
|
||||
rc = GPGERR_INVALID_ARMOR;
|
||||
rc = G10ERR_INVALID_ARMOR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -502,7 +514,7 @@ fake_packet( armor_filter_context_t *afx, IOBUF a,
|
||||
/* the buffer is always allocated with enough space to append
|
||||
* the removed [CR], LF and a Nul
|
||||
* The reason for this complicated procedure is to keep at least
|
||||
* the original tupe of lineending - handling of the removed
|
||||
* the original type of lineending - handling of the removed
|
||||
* trailing spaces seems to be impossible in our method
|
||||
* of faking a packet; either we have to use a temporary file
|
||||
* or calculate the hash here in this module and somehow find
|
||||
@ -590,6 +602,15 @@ fake_packet( armor_filter_context_t *afx, IOBUF a,
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
invalid_crc(void)
|
||||
{
|
||||
if ( opt.ignore_crc_error )
|
||||
return 0;
|
||||
log_inc_errorcount();
|
||||
return G10ERR_INVALID_ARMOR;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
radix64_read( armor_filter_context_t *afx, IOBUF a, size_t *retn,
|
||||
@ -636,9 +657,9 @@ radix64_read( armor_filter_context_t *afx, IOBUF a, size_t *retn,
|
||||
if( isxdigit(cc1) && isxdigit(cc2)
|
||||
&& strchr( "=\n\r\t ", cc3 )) {
|
||||
/* well it seems to be the case - adjust */
|
||||
c = isdigit(cc1)? (cc1 - '0'): (toupper(cc1)-'A'+10);
|
||||
c = isdigit(cc1)? (cc1 - '0'): (ascii_toupper(cc1)-'A'+10);
|
||||
c <<= 4;
|
||||
c |= isdigit(cc2)? (cc2 - '0'): (toupper(cc2)-'A'+10);
|
||||
c |= isdigit(cc2)? (cc2 - '0'): (ascii_toupper(cc2)-'A'+10);
|
||||
afx->buffer_pos += 2;
|
||||
afx->qp_detected = 1;
|
||||
goto again;
|
||||
@ -728,20 +749,23 @@ radix64_read( armor_filter_context_t *afx, IOBUF a, size_t *retn,
|
||||
break; /* eof */
|
||||
} while( ++idx < 4 );
|
||||
if( c == -1 ) {
|
||||
log_error(_("premature eof (in CRC)\n"));
|
||||
rc = GPGERR_INVALID_ARMOR;
|
||||
}
|
||||
log_info(_("premature eof (in CRC)\n"));
|
||||
rc = invalid_crc();
|
||||
}
|
||||
else if( idx != 4 ) {
|
||||
log_error(_("malformed CRC\n"));
|
||||
rc = GPGERR_INVALID_ARMOR;
|
||||
log_info(_("malformed CRC\n"));
|
||||
rc = invalid_crc();
|
||||
}
|
||||
else if( mycrc != afx->crc ) {
|
||||
log_error(_("CRC error; %06lx - %06lx\n"),
|
||||
log_info (_("CRC error; %06lx - %06lx\n"),
|
||||
(ulong)afx->crc, (ulong)mycrc);
|
||||
rc = GPGERR_INVALID_ARMOR;
|
||||
rc = invalid_crc();
|
||||
}
|
||||
else {
|
||||
rc = 0;
|
||||
/* FIXME: Here we should emit another control packet,
|
||||
* so that we know in mainproc that we are processing
|
||||
* a clearsign message */
|
||||
#if 0
|
||||
for(rc=0;!rc;) {
|
||||
rc = 0 /*check_trailer( &fhdr, c )*/;
|
||||
@ -754,11 +778,11 @@ radix64_read( armor_filter_context_t *afx, IOBUF a, size_t *retn,
|
||||
rc = 0;
|
||||
else if( rc == 2 ) {
|
||||
log_error(_("premature eof (in Trailer)\n"));
|
||||
rc = GPGERR_INVALID_ARMOR;
|
||||
rc = G10ERR_INVALID_ARMOR;
|
||||
}
|
||||
else {
|
||||
log_error(_("error in trailer line\n"));
|
||||
rc = GPGERR_INVALID_ARMOR;
|
||||
rc = G10ERR_INVALID_ARMOR;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@ -815,7 +839,9 @@ armor_filter( void *opaque, int control,
|
||||
*ret_len = n;
|
||||
}
|
||||
else if( control == IOBUFCTRL_UNDERFLOW ) {
|
||||
if( size < 15+(4*15) ) /* need space for up to 4 onepass_sigs */
|
||||
/* We need some space for the faked packet. The minmum required
|
||||
* size is ~18 + length of the session marker */
|
||||
if( size < 50 )
|
||||
BUG(); /* supplied buffer too short */
|
||||
|
||||
if( afx->faked )
|
||||
@ -831,7 +857,14 @@ armor_filter( void *opaque, int control,
|
||||
rc = -1;
|
||||
}
|
||||
else if( afx->faked ) {
|
||||
unsigned hashes = afx->hashes;
|
||||
unsigned int hashes = afx->hashes;
|
||||
const byte *sesmark;
|
||||
size_t sesmarklen;
|
||||
|
||||
sesmark = get_session_marker( &sesmarklen );
|
||||
if ( sesmarklen > 20 )
|
||||
BUG();
|
||||
|
||||
/* the buffer is at least 15+n*15 bytes long, so it
|
||||
* is easy to construct the packets */
|
||||
|
||||
@ -842,36 +875,21 @@ armor_filter( void *opaque, int control,
|
||||
afx->pgp2mode = 1;
|
||||
}
|
||||
n=0;
|
||||
do {
|
||||
/* first some onepass signature packets */
|
||||
buf[n++] = 0x90; /* old format, type 4, 1 length byte */
|
||||
buf[n++] = 13; /* length */
|
||||
buf[n++] = 3; /* version */
|
||||
buf[n++] = afx->not_dash_escaped? 0:1; /* sigclass */
|
||||
if( hashes & 1 ) {
|
||||
hashes &= ~1;
|
||||
buf[n++] = GCRY_MD_RMD160;
|
||||
}
|
||||
else if( hashes & 2 ) {
|
||||
hashes &= ~2;
|
||||
buf[n++] = GCRY_MD_SHA1;
|
||||
}
|
||||
else if( hashes & 4 ) {
|
||||
hashes &= ~4;
|
||||
buf[n++] = GCRY_MD_MD5;
|
||||
}
|
||||
else if( hashes & 8 ) {
|
||||
hashes &= ~8;
|
||||
buf[n++] = GCRY_MD_TIGER;
|
||||
}
|
||||
else
|
||||
buf[n++] = 0; /* (don't know) */
|
||||
|
||||
buf[n++] = 0; /* public key algo (don't know) */
|
||||
memset(buf+n, 0, 8); /* don't know the keyid */
|
||||
n += 8;
|
||||
buf[n++] = !hashes; /* last one */
|
||||
} while( hashes );
|
||||
/* first a gpg control packet */
|
||||
buf[n++] = 0xff; /* new format, type 63, 1 length byte */
|
||||
n++; /* see below */
|
||||
memcpy(buf+n, sesmark, sesmarklen ); n+= sesmarklen;
|
||||
buf[n++] = CTRLPKT_CLEARSIGN_START;
|
||||
buf[n++] = afx->not_dash_escaped? 0:1; /* sigclass */
|
||||
if( hashes & 1 )
|
||||
buf[n++] = DIGEST_ALGO_RMD160;
|
||||
if( hashes & 2 )
|
||||
buf[n++] = DIGEST_ALGO_SHA1;
|
||||
if( hashes & 4 )
|
||||
buf[n++] = DIGEST_ALGO_MD5;
|
||||
if( hashes & 8 )
|
||||
buf[n++] = DIGEST_ALGO_TIGER;
|
||||
buf[1] = n - 2;
|
||||
|
||||
/* followed by a plaintext packet */
|
||||
buf[n++] = 0xaf; /* old packet format, type 11, var length */
|
||||
@ -908,9 +926,8 @@ armor_filter( void *opaque, int control,
|
||||
PRINTABLE_OS_NAME ")" LF );
|
||||
|
||||
/* write the comment string or a default one */
|
||||
s = opt.comment_string ? opt.comment_string
|
||||
: _("For info see http://www.gnupg.org");
|
||||
if( *s ) {
|
||||
s = opt.comment_string;
|
||||
if( s && *s ) {
|
||||
iobuf_writestr(a, "Comment: " );
|
||||
for( ; *s; s++ ) {
|
||||
if( *s == '\n' )
|
||||
@ -925,8 +942,15 @@ armor_filter( void *opaque, int control,
|
||||
iobuf_writestr(a, LF );
|
||||
}
|
||||
|
||||
if( afx->hdrlines )
|
||||
iobuf_writestr(a, afx->hdrlines);
|
||||
if ( afx->hdrlines ) {
|
||||
for ( s = afx->hdrlines; *s; s++ ) {
|
||||
#ifdef HAVE_DOSISH_SYSTEM
|
||||
if ( *s == '\n' )
|
||||
iobuf_put( a, '\r');
|
||||
#endif
|
||||
iobuf_put(a, *s );
|
||||
}
|
||||
}
|
||||
iobuf_writestr(a, LF );
|
||||
afx->status++;
|
||||
afx->idx = 0;
|
||||
@ -1041,7 +1065,7 @@ armor_filter( void *opaque, int control,
|
||||
if( afx->qp_detected )
|
||||
log_error(_("quoted printable character in armor - "
|
||||
"probably a buggy MTA has been used\n") );
|
||||
gcry_free( afx->buffer );
|
||||
m_free( afx->buffer );
|
||||
afx->buffer = NULL;
|
||||
}
|
||||
else if( control == IOBUFCTRL_DESC )
|
||||
@ -1058,7 +1082,7 @@ make_radix64_string( const byte *data, size_t len )
|
||||
{
|
||||
char *buffer, *p;
|
||||
|
||||
buffer = p = gcry_xmalloc( (len+2)/3*4 + 1 );
|
||||
buffer = p = m_alloc( (len+2)/3*4 + 1 );
|
||||
for( ; len >= 3 ; len -= 3, data += 3 ) {
|
||||
*p++ = bintoasc[(data[0] >> 2) & 077];
|
||||
*p++ = bintoasc[(((data[0] <<4)&060)|((data[1] >> 4)&017))&077];
|
||||
@ -1078,3 +1102,221 @@ make_radix64_string( const byte *data, size_t len )
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************
|
||||
* For the pipemode command we can't use the armor filter for various
|
||||
* reasons, so we use this new unarmor_pump stuff to remove the armor
|
||||
*/
|
||||
|
||||
enum unarmor_state_e {
|
||||
STA_init = 0,
|
||||
STA_bypass,
|
||||
STA_wait_newline,
|
||||
STA_wait_dash,
|
||||
STA_first_dash,
|
||||
STA_compare_header,
|
||||
STA_found_header_wait_newline,
|
||||
STA_skip_header_lines,
|
||||
STA_skip_header_lines_non_ws,
|
||||
STA_read_data,
|
||||
STA_wait_crc,
|
||||
STA_read_crc,
|
||||
STA_ready
|
||||
};
|
||||
|
||||
struct unarmor_pump_s {
|
||||
enum unarmor_state_e state;
|
||||
byte val;
|
||||
int checkcrc;
|
||||
int pos; /* counts from 0..3 */
|
||||
u32 crc;
|
||||
u32 mycrc; /* the one store in the data */
|
||||
};
|
||||
|
||||
|
||||
|
||||
UnarmorPump
|
||||
unarmor_pump_new (void)
|
||||
{
|
||||
UnarmorPump x;
|
||||
|
||||
if( !is_initialized )
|
||||
initialize();
|
||||
x = m_alloc_clear (sizeof *x);
|
||||
return x;
|
||||
}
|
||||
|
||||
void
|
||||
unarmor_pump_release (UnarmorPump x)
|
||||
{
|
||||
m_free (x);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the next character from the ascii armor taken from the IOBUF
|
||||
* created earlier by unarmor_pump_new().
|
||||
* Return: c = Character
|
||||
* 256 = ignore this value
|
||||
* -1 = End of current armor
|
||||
* -2 = Premature EOF (not used)
|
||||
* -3 = Invalid armor
|
||||
*/
|
||||
int
|
||||
unarmor_pump (UnarmorPump x, int c)
|
||||
{
|
||||
int rval = 256; /* default is to ignore the return value */
|
||||
|
||||
switch (x->state) {
|
||||
case STA_init:
|
||||
{
|
||||
byte tmp[1];
|
||||
tmp[0] = c;
|
||||
if ( is_armored (tmp) )
|
||||
x->state = c == '-'? STA_first_dash : STA_wait_newline;
|
||||
else {
|
||||
x->state = STA_bypass;
|
||||
return c;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case STA_bypass:
|
||||
return c; /* return here to avoid crc calculation */
|
||||
case STA_wait_newline:
|
||||
if (c == '\n')
|
||||
x->state = STA_wait_dash;
|
||||
break;
|
||||
case STA_wait_dash:
|
||||
x->state = c == '-'? STA_first_dash : STA_wait_newline;
|
||||
break;
|
||||
case STA_first_dash: /* just need for initalization */
|
||||
x->pos = 0;
|
||||
x->state = STA_compare_header;
|
||||
case STA_compare_header:
|
||||
if ( "-----BEGIN PGP SIGNATURE-----"[++x->pos] == c ) {
|
||||
if ( x->pos == 28 )
|
||||
x->state = STA_found_header_wait_newline;
|
||||
}
|
||||
else
|
||||
x->state = c == '\n'? STA_wait_dash : STA_wait_newline;
|
||||
break;
|
||||
case STA_found_header_wait_newline:
|
||||
/* to make CR,LF issues easier we simply allow for white space
|
||||
behind the 5 dashes */
|
||||
if ( c == '\n' )
|
||||
x->state = STA_skip_header_lines;
|
||||
else if ( c != '\r' && c != ' ' && c != '\t' )
|
||||
x->state = STA_wait_dash; /* garbage after the header line */
|
||||
break;
|
||||
case STA_skip_header_lines:
|
||||
/* i.e. wait for one empty line */
|
||||
if ( c == '\n' ) {
|
||||
x->state = STA_read_data;
|
||||
x->crc = CRCINIT;
|
||||
x->val = 0;
|
||||
x->pos = 0;
|
||||
}
|
||||
else if ( c != '\r' && c != ' ' && c != '\t' )
|
||||
x->state = STA_skip_header_lines_non_ws;
|
||||
break;
|
||||
case STA_skip_header_lines_non_ws:
|
||||
/* like above but we already encountered non white space */
|
||||
if ( c == '\n' )
|
||||
x->state = STA_skip_header_lines;
|
||||
break;
|
||||
case STA_read_data:
|
||||
/* fixme: we don't check for the trailing dash lines but rely
|
||||
* on the armor stop characters */
|
||||
if( c == '\n' || c == ' ' || c == '\r' || c == '\t' )
|
||||
break; /* skip all kind of white space */
|
||||
|
||||
if( c == '=' ) { /* pad character: stop */
|
||||
if( x->pos == 1 ) /* in this case val has some value */
|
||||
rval = x->val;
|
||||
x->state = STA_wait_crc;
|
||||
break;
|
||||
}
|
||||
|
||||
{
|
||||
int c2;
|
||||
if( (c = asctobin[(c2=c)]) == 255 ) {
|
||||
log_error(_("invalid radix64 character %02x skipped\n"), c2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch(x->pos) {
|
||||
case 0:
|
||||
x->val = c << 2;
|
||||
break;
|
||||
case 1:
|
||||
x->val |= (c>>4)&3;
|
||||
rval = x->val;
|
||||
x->val = (c<<4)&0xf0;
|
||||
break;
|
||||
case 2:
|
||||
x->val |= (c>>2)&15;
|
||||
rval = x->val;
|
||||
x->val = (c<<6)&0xc0;
|
||||
break;
|
||||
case 3:
|
||||
x->val |= c&0x3f;
|
||||
rval = x->val;
|
||||
break;
|
||||
}
|
||||
x->pos = (x->pos+1) % 4;
|
||||
break;
|
||||
case STA_wait_crc:
|
||||
if( c == '\n' || c == ' ' || c == '\r' || c == '\t' || c == '=' )
|
||||
break; /* skip ws and pad characters */
|
||||
/* assume that we are at the next line */
|
||||
x->state = STA_read_crc;
|
||||
x->pos = 0;
|
||||
x->mycrc = 0;
|
||||
case STA_read_crc:
|
||||
if( (c = asctobin[c]) == 255 ) {
|
||||
rval = -1; /* ready */
|
||||
if( x->crc != x->mycrc ) {
|
||||
log_info (_("CRC error; %06lx - %06lx\n"),
|
||||
(ulong)x->crc, (ulong)x->mycrc);
|
||||
if ( invalid_crc() )
|
||||
rval = -3;
|
||||
}
|
||||
x->state = STA_ready; /* not sure whether this is correct */
|
||||
break;
|
||||
}
|
||||
|
||||
switch(x->pos) {
|
||||
case 0:
|
||||
x->val = c << 2;
|
||||
break;
|
||||
case 1:
|
||||
x->val |= (c>>4)&3;
|
||||
x->mycrc |= x->val << 16;
|
||||
x->val = (c<<4)&0xf0;
|
||||
break;
|
||||
case 2:
|
||||
x->val |= (c>>2)&15;
|
||||
x->mycrc |= x->val << 8;
|
||||
x->val = (c<<6)&0xc0;
|
||||
break;
|
||||
case 3:
|
||||
x->val |= c&0x3f;
|
||||
x->mycrc |= x->val;
|
||||
break;
|
||||
}
|
||||
x->pos = (x->pos+1) % 4;
|
||||
break;
|
||||
case STA_ready:
|
||||
rval = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
if ( !(rval & ~255) ) { /* compute the CRC */
|
||||
x->crc = (x->crc << 8) ^ crc_table[((x->crc >> 16)&0xff) ^ rval];
|
||||
x->crc &= 0x00ffffff;
|
||||
}
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* build-packet.c - assemble packets and write them
|
||||
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
|
||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
@ -24,13 +24,14 @@
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <gcrypt.h>
|
||||
#include "packet.h"
|
||||
#include "errors.h"
|
||||
#include "iobuf.h"
|
||||
#include "mpi.h"
|
||||
#include "util.h"
|
||||
#include "cipher.h"
|
||||
#include "memory.h"
|
||||
#include "options.h"
|
||||
#include "main.h"
|
||||
|
||||
|
||||
static int do_comment( IOBUF out, int ctb, PKT_comment *rem );
|
||||
@ -80,8 +81,8 @@ build_packet( IOBUF out, PACKET *pkt )
|
||||
case PKT_ENCRYPTED_MDC: new_ctb = pkt->pkt.encrypted->new_ctb; break;
|
||||
case PKT_COMPRESSED:new_ctb = pkt->pkt.compressed->new_ctb; break;
|
||||
case PKT_USER_ID:
|
||||
if( pkt->pkt.user_id->photo )
|
||||
pkttype = PKT_PHOTO_ID;
|
||||
if( pkt->pkt.user_id->attrib_data )
|
||||
pkttype = PKT_ATTRIBUTE;
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
@ -91,7 +92,7 @@ build_packet( IOBUF out, PACKET *pkt )
|
||||
else
|
||||
ctb = 0x80 | ((pkttype & 15)<<2);
|
||||
switch( pkttype ) {
|
||||
case PKT_PHOTO_ID:
|
||||
case PKT_ATTRIBUTE:
|
||||
case PKT_USER_ID:
|
||||
rc = do_user_id( out, ctb, pkt->pkt.user_id );
|
||||
break;
|
||||
@ -134,7 +135,7 @@ build_packet( IOBUF out, PACKET *pkt )
|
||||
rc = do_onepass_sig( out, ctb, pkt->pkt.onepass_sig );
|
||||
break;
|
||||
case PKT_RING_TRUST:
|
||||
break; /* ignore it */
|
||||
break; /* ignore it (keyring.c does write it directly)*/
|
||||
default:
|
||||
log_bug("invalid packet type in build_packet()\n");
|
||||
break;
|
||||
@ -158,7 +159,7 @@ calc_packet_length( PACKET *pkt )
|
||||
n = calc_plaintext( pkt->pkt.plaintext );
|
||||
new_ctb = pkt->pkt.plaintext->new_ctb;
|
||||
break;
|
||||
case PKT_PHOTO_ID:
|
||||
case PKT_ATTRIBUTE:
|
||||
case PKT_USER_ID:
|
||||
case PKT_COMMENT:
|
||||
case PKT_PUBLIC_KEY:
|
||||
@ -195,10 +196,10 @@ write_fake_data( IOBUF out, MPI a )
|
||||
static int
|
||||
do_comment( IOBUF out, int ctb, PKT_comment *rem )
|
||||
{
|
||||
if( !opt.no_comment ) {
|
||||
if( opt.sk_comments ) {
|
||||
write_header(out, ctb, rem->len);
|
||||
if( iobuf_write( out, rem->data, rem->len ) )
|
||||
return GPGERR_WRITE_FILE;
|
||||
return G10ERR_WRITE_FILE;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -206,19 +207,15 @@ do_comment( IOBUF out, int ctb, PKT_comment *rem )
|
||||
static int
|
||||
do_user_id( IOBUF out, int ctb, PKT_user_id *uid )
|
||||
{
|
||||
if( uid->photo ) {
|
||||
write_header(out, ctb, uid->photolen);
|
||||
uid->stored_at = iobuf_get_temp_length ( out ); /* what a hack ... */
|
||||
/* ... and it does only work when used with a temp iobuf */
|
||||
if( iobuf_write( out, uid->photo, uid->photolen ) )
|
||||
return GPGERR_WRITE_FILE;
|
||||
if( uid->attrib_data ) {
|
||||
write_header(out, ctb, uid->attrib_len);
|
||||
if( iobuf_write( out, uid->attrib_data, uid->attrib_len ) )
|
||||
return G10ERR_WRITE_FILE;
|
||||
}
|
||||
else {
|
||||
write_header(out, ctb, uid->len);
|
||||
uid->stored_at = iobuf_get_temp_length ( out ); /* what a hack ... */
|
||||
/* ... and it does only work when used with a temp iobuf */
|
||||
if( iobuf_write( out, uid->name, uid->len ) )
|
||||
return GPGERR_WRITE_FILE;
|
||||
return G10ERR_WRITE_FILE;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -252,7 +249,7 @@ do_public_key( IOBUF out, int ctb, PKT_public_key *pk )
|
||||
|
||||
write_header2(out, ctb, iobuf_get_temp_length(a), pk->hdrbytes, 1 );
|
||||
if( iobuf_write_temp( out, a ) )
|
||||
rc = GPGERR_WRITE_FILE;
|
||||
rc = G10ERR_WRITE_FILE;
|
||||
|
||||
iobuf_close(a);
|
||||
return rc;
|
||||
@ -263,7 +260,7 @@ do_public_key( IOBUF out, int ctb, PKT_public_key *pk )
|
||||
* Make a hash value from the public key certificate
|
||||
*/
|
||||
void
|
||||
hash_public_key( GCRY_MD_HD md, PKT_public_key *pk )
|
||||
hash_public_key( MD_HANDLE md, PKT_public_key *pk )
|
||||
{
|
||||
PACKET pkt;
|
||||
int rc = 0;
|
||||
@ -283,7 +280,7 @@ hash_public_key( GCRY_MD_HD md, PKT_public_key *pk )
|
||||
pkt.pkttype = PKT_PUBLIC_KEY;
|
||||
pkt.pkt.public_key = pk;
|
||||
if( (rc = build_packet( a, &pkt )) )
|
||||
log_fatal("build public_key for hashing failed: %s\n", gpg_errstr(rc));
|
||||
log_fatal("build public_key for hashing failed: %s\n", g10_errstr(rc));
|
||||
|
||||
if( !(pk->version == 3 && pk->pubkey_algo == 16) ) {
|
||||
/* skip the constructed header but don't do this for our very old
|
||||
@ -314,10 +311,10 @@ hash_public_key( GCRY_MD_HD md, PKT_public_key *pk )
|
||||
}
|
||||
}
|
||||
/* hash a header */
|
||||
gcry_md_putc( md, 0x99 );
|
||||
md_putc( md, 0x99 );
|
||||
pktlen &= 0xffff; /* can't handle longer packets */
|
||||
gcry_md_putc( md, pktlen >> 8 );
|
||||
gcry_md_putc( md, pktlen & 0xff );
|
||||
md_putc( md, pktlen >> 8 );
|
||||
md_putc( md, pktlen & 0xff );
|
||||
}
|
||||
/* hash the packet body */
|
||||
while( (c=iobuf_get(a)) != -1 ) {
|
||||
@ -328,7 +325,7 @@ hash_public_key( GCRY_MD_HD md, PKT_public_key *pk )
|
||||
i=0;
|
||||
}
|
||||
#endif
|
||||
gcry_md_putc( md, c );
|
||||
md_putc( md, c );
|
||||
}
|
||||
#if 0
|
||||
putc('\n', fp);
|
||||
@ -343,43 +340,64 @@ do_secret_key( IOBUF out, int ctb, PKT_secret_key *sk )
|
||||
{
|
||||
int rc = 0;
|
||||
int i, nskey, npkey;
|
||||
IOBUF a = iobuf_temp();
|
||||
IOBUF a = iobuf_temp(); /* build in a self-enlarging buffer */
|
||||
|
||||
/* Write the version number - if none is specified, use 3 */
|
||||
if( !sk->version )
|
||||
iobuf_put( a, 3 );
|
||||
else
|
||||
iobuf_put( a, sk->version );
|
||||
write_32(a, sk->timestamp );
|
||||
|
||||
/* v3 needs the expiration time */
|
||||
if( sk->version < 4 ) {
|
||||
u16 ndays;
|
||||
if( sk->expiredate )
|
||||
ndays = (u16)((sk->expiredate - sk->timestamp) / 86400L);
|
||||
else
|
||||
ndays = 0;
|
||||
write_16(a, 0 );
|
||||
write_16(a, ndays);
|
||||
}
|
||||
|
||||
iobuf_put(a, sk->pubkey_algo );
|
||||
|
||||
/* get number of secret and public parameters. They are held in
|
||||
one array first the public ones, then the secret ones */
|
||||
nskey = pubkey_get_nskey( sk->pubkey_algo );
|
||||
npkey = pubkey_get_npkey( sk->pubkey_algo );
|
||||
|
||||
/* If we don't have any public parameters - which is the case if
|
||||
we don't know the algorithm used - the parameters are stored as
|
||||
one blob in a faked (opaque) MPI */
|
||||
if( !npkey ) {
|
||||
write_fake_data( a, sk->skey[0] );
|
||||
goto leave;
|
||||
}
|
||||
assert( npkey < nskey );
|
||||
|
||||
/* Writing the public parameters is easy */
|
||||
for(i=0; i < npkey; i++ )
|
||||
mpi_write(a, sk->skey[i] );
|
||||
|
||||
/* build the header for protected (encrypted) secret parameters */
|
||||
if( sk->is_protected ) {
|
||||
if( is_RSA(sk->pubkey_algo) && sk->version < 4
|
||||
&& !sk->protect.s2k.mode ) {
|
||||
/* the simple rfc1991 (v3) way */
|
||||
iobuf_put(a, sk->protect.algo );
|
||||
iobuf_write(a, sk->protect.iv, sk->protect.ivlen );
|
||||
}
|
||||
else {
|
||||
iobuf_put(a, 0xff );
|
||||
/* OpenPGP protection according to rfc2440 */
|
||||
iobuf_put(a, sk->protect.sha1chk? 0xfe : 0xff );
|
||||
iobuf_put(a, sk->protect.algo );
|
||||
if( sk->protect.s2k.mode >= 1000 ) {
|
||||
iobuf_put(a, 101 );
|
||||
/* These modes are not possible in OpenPGP, we use them
|
||||
to implement our extesnsions, 101 can ve views as a
|
||||
private/experimental extension (this is not
|
||||
specified in rfc2440 but the same scheme is used
|
||||
for all other algorithm identifiers) */
|
||||
iobuf_put(a, 101 );
|
||||
iobuf_put(a, sk->protect.s2k.hash_algo );
|
||||
iobuf_write(a, "GNU", 3 );
|
||||
iobuf_put(a, sk->protect.s2k.mode - 1000 );
|
||||
@ -392,34 +410,41 @@ do_secret_key( IOBUF out, int ctb, PKT_secret_key *sk )
|
||||
|| sk->protect.s2k.mode == 3 )
|
||||
iobuf_write(a, sk->protect.s2k.salt, 8 );
|
||||
if( sk->protect.s2k.mode == 3 )
|
||||
iobuf_put(a, sk->protect.s2k.count );
|
||||
iobuf_put(a, sk->protect.s2k.count );
|
||||
|
||||
/* For out special mode 1001 we do not need an IV */
|
||||
if( sk->protect.s2k.mode != 1001 )
|
||||
iobuf_write(a, sk->protect.iv, sk->protect.ivlen );
|
||||
}
|
||||
}
|
||||
else
|
||||
iobuf_put(a, 0 );
|
||||
|
||||
if( sk->protect.s2k.mode == 1001 )
|
||||
;
|
||||
; /* GnuPG extension - don't write a secret key at all */
|
||||
else if( sk->is_protected && sk->version >= 4 ) {
|
||||
/* The secret key is protected - write it out as it is */
|
||||
byte *p;
|
||||
size_t n;
|
||||
assert( gcry_mpi_get_flag( sk->skey[i], GCRYMPI_FLAG_OPAQUE ) );
|
||||
p = gcry_mpi_get_opaque( sk->skey[i], &n );
|
||||
iobuf_write(a, p, (n+7)/8 );
|
||||
assert( mpi_is_opaque( sk->skey[npkey] ) );
|
||||
p = mpi_get_opaque( sk->skey[npkey], &i );
|
||||
iobuf_write(a, p, i );
|
||||
}
|
||||
else {
|
||||
/* v3 way - same code for protected and non- protected key */
|
||||
for( ; i < nskey; i++ )
|
||||
mpi_write(a, sk->skey[i] );
|
||||
write_16(a, sk->csum );
|
||||
}
|
||||
|
||||
leave:
|
||||
/* Build the header of the packet - which we must do after writing all
|
||||
the other stuff, so that we know the length of the packet */
|
||||
write_header2(out, ctb, iobuf_get_temp_length(a), sk->hdrbytes, 1 );
|
||||
/* And finally write it out the real stream */
|
||||
if( iobuf_write_temp( out, a ) )
|
||||
rc = GPGERR_WRITE_FILE;
|
||||
rc = G10ERR_WRITE_FILE;
|
||||
|
||||
iobuf_close(a);
|
||||
iobuf_close(a); /* close the remporary buffer */
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -448,7 +473,7 @@ do_symkey_enc( IOBUF out, int ctb, PKT_symkey_enc *enc )
|
||||
|
||||
write_header(out, ctb, iobuf_get_temp_length(a) );
|
||||
if( iobuf_write_temp( out, a ) )
|
||||
rc = GPGERR_WRITE_FILE;
|
||||
rc = G10ERR_WRITE_FILE;
|
||||
|
||||
iobuf_close(a);
|
||||
return rc;
|
||||
@ -482,7 +507,7 @@ do_pubkey_enc( IOBUF out, int ctb, PKT_pubkey_enc *enc )
|
||||
|
||||
write_header(out, ctb, iobuf_get_temp_length(a) );
|
||||
if( iobuf_write_temp( out, a ) )
|
||||
rc = GPGERR_WRITE_FILE;
|
||||
rc = G10ERR_WRITE_FILE;
|
||||
|
||||
iobuf_close(a);
|
||||
return rc;
|
||||
@ -511,12 +536,12 @@ do_plaintext( IOBUF out, int ctb, PKT_plaintext *pt )
|
||||
for(i=0; i < pt->namelen; i++ )
|
||||
iobuf_put(out, pt->name[i] );
|
||||
if( write_32(out, pt->timestamp ) )
|
||||
rc = GPGERR_WRITE_FILE;
|
||||
rc = G10ERR_WRITE_FILE;
|
||||
|
||||
n = 0;
|
||||
while( (nbytes=iobuf_read(pt->buf, buf, 1000)) != -1 ) {
|
||||
if( iobuf_write(out, buf, nbytes) == -1 ) {
|
||||
rc = GPGERR_WRITE_FILE;
|
||||
rc = G10ERR_WRITE_FILE;
|
||||
break;
|
||||
}
|
||||
n += nbytes;
|
||||
@ -539,7 +564,7 @@ do_encrypted( IOBUF out, int ctb, PKT_encrypted *ed )
|
||||
int rc = 0;
|
||||
u32 n;
|
||||
|
||||
n = ed->len ? (ed->len + 10) : 0;
|
||||
n = ed->len ? (ed->len + ed->extralen) : 0;
|
||||
write_header(out, ctb, n );
|
||||
|
||||
/* This is all. The caller has to write the real data */
|
||||
@ -555,7 +580,7 @@ do_encrypted_mdc( IOBUF out, int ctb, PKT_encrypted *ed )
|
||||
|
||||
assert( ed->mdc_method );
|
||||
|
||||
n = ed->len ? (ed->len + 10) : 0;
|
||||
n = ed->len ? (ed->len + ed->extralen) : 0;
|
||||
write_header(out, ctb, n );
|
||||
iobuf_put(out, 1 ); /* version */
|
||||
|
||||
@ -572,7 +597,7 @@ do_mdc( IOBUF out, PKT_mdc *mdc )
|
||||
iobuf_put( out, 0xd3 ); /* packet ID and 1 byte length */
|
||||
iobuf_put( out, 0x14 ); /* length = 20 */
|
||||
if( iobuf_write( out, mdc->hash, sizeof(mdc->hash) ) )
|
||||
return GPGERR_WRITE_FILE;
|
||||
return G10ERR_WRITE_FILE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -591,36 +616,36 @@ do_compressed( IOBUF out, int ctb, PKT_compressed *cd )
|
||||
}
|
||||
|
||||
|
||||
|
||||
/****************
|
||||
* Find a subpacket of type REQTYPE in BUFFER and a return a pointer
|
||||
* to the first byte of that subpacket data.
|
||||
* And return the length of the packet in RET_N and the number of
|
||||
* header bytes in RET_HLEN (length header and type byte).
|
||||
* Delete all subpackets of type REQTYPE and return a bool whether a packet
|
||||
* was deleted.
|
||||
*/
|
||||
byte *
|
||||
find_subpkt( byte *buffer, sigsubpkttype_t reqtype,
|
||||
size_t *ret_hlen, size_t *ret_n )
|
||||
int
|
||||
delete_sig_subpkt (subpktarea_t *area, sigsubpkttype_t reqtype )
|
||||
{
|
||||
int buflen;
|
||||
sigsubpkttype_t type;
|
||||
byte *bufstart;
|
||||
byte *buffer, *bufstart;
|
||||
size_t n;
|
||||
size_t unused = 0;
|
||||
int okay = 0;
|
||||
|
||||
if( !buffer )
|
||||
return NULL;
|
||||
buflen = (*buffer << 8) | buffer[1];
|
||||
buffer += 2;
|
||||
if( !area )
|
||||
return 0;
|
||||
buflen = area->len;
|
||||
buffer = area->data;
|
||||
for(;;) {
|
||||
if( !buflen )
|
||||
return NULL; /* end of packets; not found */
|
||||
if( !buflen ) {
|
||||
okay = 1;
|
||||
break;
|
||||
}
|
||||
bufstart = buffer;
|
||||
n = *buffer++; buflen--;
|
||||
if( n == 255 ) {
|
||||
if( buflen < 4 )
|
||||
break;
|
||||
n = (buffer[0] << 24) | (buffer[1] << 16)
|
||||
| (buffer[2] << 8) | buffer[3];
|
||||
| (buffer[2] << 8) | buffer[3];
|
||||
buffer += 4;
|
||||
buflen -= 4;
|
||||
}
|
||||
@ -633,137 +658,175 @@ find_subpkt( byte *buffer, sigsubpkttype_t reqtype,
|
||||
}
|
||||
if( buflen < n )
|
||||
break;
|
||||
|
||||
type = *buffer & 0x7f;
|
||||
if( type == reqtype ) {
|
||||
buffer++;
|
||||
buflen--;
|
||||
n--;
|
||||
if( n > buflen )
|
||||
break;
|
||||
if( ret_hlen )
|
||||
*ret_hlen = buffer - bufstart;
|
||||
if( ret_n )
|
||||
*ret_n = n;
|
||||
return buffer;
|
||||
buffer += n; /* point to next subpkt */
|
||||
buflen -= n;
|
||||
memmove (bufstart, buffer, buflen); /* shift */
|
||||
unused += buffer - bufstart;
|
||||
buffer = bufstart;
|
||||
}
|
||||
buffer += n; buflen -=n;
|
||||
else {
|
||||
buffer += n; buflen -=n;
|
||||
}
|
||||
}
|
||||
|
||||
log_error("find_subpkt: buffer shorter than subpacket\n");
|
||||
return NULL;
|
||||
if (!okay)
|
||||
log_error ("delete_subpkt: buffer shorter than subpacket\n");
|
||||
assert (unused <= area->len);
|
||||
area->len -= unused;
|
||||
return !!unused;
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
* Create or update a signature subpacket for SIG of TYPE.
|
||||
* This functions knows where to put the data (hashed or unhashed).
|
||||
* The function may move data from the unhased part to the hashed one.
|
||||
* Note: All pointers into sig->[un]hashed are not valid after a call
|
||||
* to this function. The data to but into the subpaket should be
|
||||
* in buffer with a length of buflen.
|
||||
* Create or update a signature subpacket for SIG of TYPE. This
|
||||
* functions knows where to put the data (hashed or unhashed). The
|
||||
* function may move data from the unhashed part to the hashed one.
|
||||
* Note: All pointers into sig->[un]hashed (e.g. returned by
|
||||
* parse_sig_subpkt) are not valid after a call to this function. The
|
||||
* data to put into the subpaket should be in a buffer with a length
|
||||
* of buflen.
|
||||
*/
|
||||
void
|
||||
build_sig_subpkt( PKT_signature *sig, sigsubpkttype_t type,
|
||||
build_sig_subpkt (PKT_signature *sig, sigsubpkttype_t type,
|
||||
const byte *buffer, size_t buflen )
|
||||
{
|
||||
byte *data;
|
||||
size_t hlen, dlen, nlen;
|
||||
int found=0;
|
||||
int critical, hashed, realloced;
|
||||
size_t n, n0;
|
||||
byte *p;
|
||||
int critical, hashed;
|
||||
subpktarea_t *oldarea, *newarea;
|
||||
size_t nlen, n, n0;
|
||||
|
||||
critical = (type & SIGSUBPKT_FLAG_CRITICAL);
|
||||
type &= ~SIGSUBPKT_FLAG_CRITICAL;
|
||||
|
||||
if( type == SIGSUBPKT_NOTATION )
|
||||
; /* we allow multiple packets */
|
||||
else if( (data = find_subpkt( sig->hashed_data, type, &hlen, &dlen )) )
|
||||
found = 1;
|
||||
else if( (data = find_subpkt( sig->unhashed_data, type, &hlen, &dlen )))
|
||||
found = 2;
|
||||
/* Sanity check buffer sizes */
|
||||
if(parse_one_sig_subpkt(buffer,buflen,type)<0)
|
||||
BUG();
|
||||
|
||||
if( found )
|
||||
log_bug("build_sig_packet: update nyi\n");
|
||||
if( (buflen+1) >= 8384 )
|
||||
nlen = 5;
|
||||
else if( (buflen+1) >= 192 )
|
||||
nlen = 2;
|
||||
else
|
||||
nlen = 1;
|
||||
|
||||
switch( type ) {
|
||||
case SIGSUBPKT_SIG_CREATED:
|
||||
case SIGSUBPKT_PRIV_ADD_SIG:
|
||||
case SIGSUBPKT_PREF_SYM:
|
||||
case SIGSUBPKT_PREF_HASH:
|
||||
case SIGSUBPKT_PREF_COMPR:
|
||||
case SIGSUBPKT_KS_FLAGS:
|
||||
case SIGSUBPKT_KEY_EXPIRE:
|
||||
switch(type)
|
||||
{
|
||||
case SIGSUBPKT_NOTATION:
|
||||
case SIGSUBPKT_POLICY:
|
||||
case SIGSUBPKT_REVOC_REASON:
|
||||
case SIGSUBPKT_KEY_FLAGS:
|
||||
case SIGSUBPKT_FEATURES:
|
||||
hashed = 1; break;
|
||||
default: hashed = 0; break;
|
||||
}
|
||||
case SIGSUBPKT_REV_KEY:
|
||||
/* we do allow multiple subpackets */
|
||||
break;
|
||||
|
||||
if( hashed ) {
|
||||
n0 = sig->hashed_data ? ((*sig->hashed_data << 8)
|
||||
| sig->hashed_data[1]) : 0;
|
||||
n = n0 + nlen + 1 + buflen; /* length, type, buffer */
|
||||
realloced = !!sig->hashed_data;
|
||||
data = sig->hashed_data ? gcry_xrealloc( sig->hashed_data, n+2 )
|
||||
: gcry_xmalloc( n+2 );
|
||||
}
|
||||
else {
|
||||
n0 = sig->unhashed_data ? ((*sig->unhashed_data << 8)
|
||||
| sig->unhashed_data[1]) : 0;
|
||||
n = n0 + nlen + 1 + buflen; /* length, type, buffer */
|
||||
realloced = !!sig->unhashed_data;
|
||||
data = sig->unhashed_data ? gcry_xrealloc( sig->unhashed_data, n+2 )
|
||||
: gcry_xmalloc( n+2 );
|
||||
default:
|
||||
/* we don't allow multiple subpackets */
|
||||
delete_sig_subpkt(sig->hashed,type);
|
||||
delete_sig_subpkt(sig->unhashed,type);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Any special magic that needs to be done for this type so the
|
||||
packet doesn't need to be reparsed? */
|
||||
switch(type)
|
||||
{
|
||||
case SIGSUBPKT_NOTATION:
|
||||
sig->flags.notation=1;
|
||||
break;
|
||||
|
||||
case SIGSUBPKT_POLICY:
|
||||
sig->flags.policy_url=1;
|
||||
break;
|
||||
|
||||
case SIGSUBPKT_EXPORTABLE:
|
||||
if(buffer[0])
|
||||
sig->flags.exportable=1;
|
||||
else
|
||||
sig->flags.exportable=0;
|
||||
break;
|
||||
|
||||
case SIGSUBPKT_REVOCABLE:
|
||||
if(buffer[0])
|
||||
sig->flags.revocable=1;
|
||||
else
|
||||
sig->flags.revocable=0;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if( (buflen+1) >= 8384 )
|
||||
nlen = 5; /* write 5 byte length header */
|
||||
else if( (buflen+1) >= 192 )
|
||||
nlen = 2; /* write 2 byte length header */
|
||||
else
|
||||
nlen = 1; /* just a 1 byte length header */
|
||||
|
||||
switch( type ) {
|
||||
case SIGSUBPKT_ISSUER:
|
||||
case SIGSUBPKT_PRIV_VERIFY_CACHE: /*(obsolete)*/
|
||||
hashed = 0;
|
||||
break;
|
||||
default:
|
||||
hashed = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if( critical )
|
||||
type |= SIGSUBPKT_FLAG_CRITICAL;
|
||||
|
||||
data[0] = (n >> 8) & 0xff;
|
||||
data[1] = n & 0xff;
|
||||
if( nlen == 5 ) {
|
||||
data[n0+2] = 255;
|
||||
data[n0+3] = (buflen+1) >> 24;
|
||||
data[n0+4] = (buflen+1) >> 16;
|
||||
data[n0+5] = (buflen+1) >> 8;
|
||||
data[n0+6] = (buflen+1);
|
||||
data[n0+7] = type;
|
||||
memcpy(data+n0+8, buffer, buflen );
|
||||
oldarea = hashed? sig->hashed : sig->unhashed;
|
||||
|
||||
/* Calculate new size of the area and allocate */
|
||||
n0 = oldarea? oldarea->len : 0;
|
||||
n = n0 + nlen + 1 + buflen; /* length, type, buffer */
|
||||
if (oldarea && n <= oldarea->size) { /* fits into the unused space */
|
||||
newarea = oldarea;
|
||||
/*log_debug ("updating area for type %d\n", type );*/
|
||||
}
|
||||
else if( nlen == 2 ) {
|
||||
data[n0+2] = (buflen+1-192) / 256 + 192;
|
||||
data[n0+3] = (buflen+1-192) & 256;
|
||||
data[n0+4] = type;
|
||||
memcpy(data+n0+5, buffer, buflen );
|
||||
else if (oldarea) {
|
||||
newarea = m_realloc (oldarea, sizeof (*newarea) + n - 1);
|
||||
newarea->size = n;
|
||||
/*log_debug ("reallocating area for type %d\n", type );*/
|
||||
}
|
||||
else {
|
||||
data[n0+2] = buflen+1;
|
||||
data[n0+3] = type;
|
||||
memcpy(data+n0+4, buffer, buflen );
|
||||
newarea = m_alloc (sizeof (*newarea) + n - 1);
|
||||
newarea->size = n;
|
||||
/*log_debug ("allocating area for type %d\n", type );*/
|
||||
}
|
||||
newarea->len = n;
|
||||
|
||||
p = newarea->data + n0;
|
||||
if (nlen == 5) {
|
||||
*p++ = 255;
|
||||
*p++ = (buflen+1) >> 24;
|
||||
*p++ = (buflen+1) >> 16;
|
||||
*p++ = (buflen+1) >> 8;
|
||||
*p++ = (buflen+1);
|
||||
*p++ = type;
|
||||
memcpy (p, buffer, buflen);
|
||||
}
|
||||
else if (nlen == 2) {
|
||||
*p++ = (buflen+1-192) / 256 + 192;
|
||||
*p++ = (buflen+1-192) % 256;
|
||||
*p++ = type;
|
||||
memcpy (p, buffer, buflen);
|
||||
}
|
||||
else {
|
||||
*p++ = buflen+1;
|
||||
*p++ = type;
|
||||
memcpy (p, buffer, buflen);
|
||||
}
|
||||
|
||||
if( hashed ) {
|
||||
if( !realloced )
|
||||
gcry_free(sig->hashed_data);
|
||||
sig->hashed_data = data;
|
||||
}
|
||||
else {
|
||||
if( !realloced )
|
||||
gcry_free(sig->unhashed_data);
|
||||
sig->unhashed_data = data;
|
||||
}
|
||||
if (hashed)
|
||||
sig->hashed = newarea;
|
||||
else
|
||||
sig->unhashed = newarea;
|
||||
}
|
||||
|
||||
/****************
|
||||
* Put all the required stuff from SIG into subpackets of sig.
|
||||
* Hmmm, should we delete those subpackets which are in a wrong area?
|
||||
*/
|
||||
void
|
||||
build_sig_subpkt_from_sig( PKT_signature *sig )
|
||||
@ -789,8 +852,70 @@ build_sig_subpkt_from_sig( PKT_signature *sig )
|
||||
buf[2] = (u >> 8) & 0xff;
|
||||
buf[3] = u & 0xff;
|
||||
build_sig_subpkt( sig, SIGSUBPKT_SIG_CREATED, buf, 4 );
|
||||
|
||||
if(sig->expiredate)
|
||||
{
|
||||
u = sig->expiredate-sig->timestamp;
|
||||
buf[0] = (u >> 24) & 0xff;
|
||||
buf[1] = (u >> 16) & 0xff;
|
||||
buf[2] = (u >> 8) & 0xff;
|
||||
buf[3] = u & 0xff;
|
||||
|
||||
/* Mark this CRITICAL, so if any implementation doesn't
|
||||
understand sigs that can expire, it'll just disregard this
|
||||
sig altogether. */
|
||||
|
||||
build_sig_subpkt( sig, SIGSUBPKT_SIG_EXPIRE | SIGSUBPKT_FLAG_CRITICAL,
|
||||
buf, 4 );
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
build_attribute_subpkt(PKT_user_id *uid,byte type,
|
||||
const void *buf,int buflen,
|
||||
const void *header,int headerlen)
|
||||
{
|
||||
byte *attrib;
|
||||
int idx;
|
||||
|
||||
if(1+headerlen+buflen>8383)
|
||||
idx=5;
|
||||
else if(1+headerlen+buflen>191)
|
||||
idx=2;
|
||||
else
|
||||
idx=1;
|
||||
|
||||
/* realloc uid->attrib_data to the right size */
|
||||
|
||||
uid->attrib_data=m_realloc(uid->attrib_data,
|
||||
uid->attrib_len+idx+1+headerlen+buflen);
|
||||
|
||||
attrib=&uid->attrib_data[uid->attrib_len];
|
||||
|
||||
if(idx==5)
|
||||
{
|
||||
attrib[0]=255;
|
||||
attrib[1]=(1+headerlen+buflen) >> 24;
|
||||
attrib[2]=(1+headerlen+buflen) >> 16;
|
||||
attrib[3]=(1+headerlen+buflen) >> 8;
|
||||
attrib[4]=1+headerlen+buflen;
|
||||
}
|
||||
else if(idx==2)
|
||||
{
|
||||
attrib[0]=(1+headerlen+buflen-192) / 256 + 192;
|
||||
attrib[1]=(1+headerlen+buflen-192) % 256;
|
||||
}
|
||||
else
|
||||
attrib[0]=1+headerlen+buflen; /* Good luck finding a JPEG this small! */
|
||||
|
||||
attrib[idx++]=type;
|
||||
|
||||
/* Tack on our data at the end */
|
||||
|
||||
memcpy(&attrib[idx],header,headerlen);
|
||||
memcpy(&attrib[idx+headerlen],buf,buflen);
|
||||
uid->attrib_len+=idx+headerlen+buflen;
|
||||
}
|
||||
|
||||
static int
|
||||
do_signature( IOBUF out, int ctb, PKT_signature *sig )
|
||||
@ -818,16 +943,14 @@ do_signature( IOBUF out, int ctb, PKT_signature *sig )
|
||||
/* timestamp and keyid must have been packed into the
|
||||
* subpackets prior to the call of this function, because
|
||||
* these subpackets are hashed */
|
||||
nn = sig->hashed_data?((sig->hashed_data[0]<<8)
|
||||
|sig->hashed_data[1]) :0;
|
||||
nn = sig->hashed? sig->hashed->len : 0;
|
||||
write_16(a, nn);
|
||||
if( nn )
|
||||
iobuf_write( a, sig->hashed_data+2, nn );
|
||||
nn = sig->unhashed_data?((sig->unhashed_data[0]<<8)
|
||||
|sig->unhashed_data[1]) :0;
|
||||
iobuf_write( a, sig->hashed->data, nn );
|
||||
nn = sig->unhashed? sig->unhashed->len : 0;
|
||||
write_16(a, nn);
|
||||
if( nn )
|
||||
iobuf_write( a, sig->unhashed_data+2, nn );
|
||||
iobuf_write( a, sig->unhashed->data, nn );
|
||||
}
|
||||
iobuf_put(a, sig->digest_start[0] );
|
||||
iobuf_put(a, sig->digest_start[1] );
|
||||
@ -842,7 +965,7 @@ do_signature( IOBUF out, int ctb, PKT_signature *sig )
|
||||
else
|
||||
write_header(out, ctb, iobuf_get_temp_length(a) );
|
||||
if( iobuf_write_temp( out, a ) )
|
||||
rc = GPGERR_WRITE_FILE;
|
||||
rc = G10ERR_WRITE_FILE;
|
||||
|
||||
iobuf_close(a);
|
||||
return rc;
|
||||
@ -865,7 +988,7 @@ do_onepass_sig( IOBUF out, int ctb, PKT_onepass_sig *ops )
|
||||
|
||||
write_header(out, ctb, iobuf_get_temp_length(a) );
|
||||
if( iobuf_write_temp( out, a ) )
|
||||
rc = GPGERR_WRITE_FILE;
|
||||
rc = G10ERR_WRITE_FILE;
|
||||
|
||||
iobuf_close(a);
|
||||
return rc;
|
||||
|
109
g10/cipher.c
109
g10/cipher.c
@ -1,5 +1,5 @@
|
||||
/* cipher.c - En-/De-ciphering filter
|
||||
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
|
||||
* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
@ -25,9 +25,9 @@
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <gcrypt.h>
|
||||
#include "errors.h"
|
||||
#include "iobuf.h"
|
||||
#include "memory.h"
|
||||
#include "util.h"
|
||||
#include "filter.h"
|
||||
#include "packet.h"
|
||||
@ -45,69 +45,69 @@ write_header( cipher_filter_context_t *cfx, IOBUF a )
|
||||
PACKET pkt;
|
||||
PKT_encrypted ed;
|
||||
byte temp[18];
|
||||
unsigned int blocksize;
|
||||
unsigned int nprefix;
|
||||
int rc;
|
||||
int use_mdc = opt.force_mdc;
|
||||
unsigned blocksize;
|
||||
unsigned nprefix;
|
||||
int use_mdc;
|
||||
|
||||
blocksize = gcry_cipher_get_algo_blklen( cfx->dek->algo );
|
||||
blocksize = cipher_get_blocksize( cfx->dek->algo );
|
||||
if( blocksize < 8 || blocksize > 16 )
|
||||
log_fatal("unsupported blocksize %u\n", blocksize );
|
||||
|
||||
use_mdc = cfx->dek->use_mdc;
|
||||
|
||||
if( blocksize != 8 )
|
||||
use_mdc = 1; /* enable it for all modern ciphers */
|
||||
if( opt.rfc2440 )
|
||||
use_mdc = 1; /* Hack: enable it for all modern ciphers */
|
||||
/* Note: We should remove this hack as soon as a reasonable number of keys
|
||||
are carrying the MDC flag. But always keep the hack for conventional
|
||||
encryption */
|
||||
|
||||
if (opt.force_mdc)
|
||||
use_mdc = 1;
|
||||
|
||||
if( opt.rfc2440 || opt.rfc1991 || opt.disable_mdc )
|
||||
use_mdc = 0; /* override - rfc2440 does not know about MDC */
|
||||
|
||||
memset( &ed, 0, sizeof ed );
|
||||
ed.len = cfx->datalen;
|
||||
ed.extralen = blocksize+2;
|
||||
ed.new_ctb = !ed.len && !opt.rfc1991;
|
||||
if( use_mdc ) {
|
||||
ed.mdc_method = GCRY_MD_SHA1;
|
||||
cfx->mdc_hash = gcry_md_open( GCRY_MD_SHA1, 0 );
|
||||
if( !cfx->mdc_hash )
|
||||
BUG();
|
||||
ed.mdc_method = DIGEST_ALGO_SHA1;
|
||||
cfx->mdc_hash = md_open( DIGEST_ALGO_SHA1, 0 );
|
||||
if ( DBG_HASHING )
|
||||
gcry_md_start_debug( cfx->mdc_hash, "creatmdc" );
|
||||
md_start_debug( cfx->mdc_hash, "creatmdc" );
|
||||
}
|
||||
|
||||
{
|
||||
char buf[20];
|
||||
|
||||
sprintf (buf, "%d %d", ed.mdc_method, cfx->dek->algo);
|
||||
write_status_text (STATUS_BEGIN_ENCRYPTION, buf);
|
||||
}
|
||||
|
||||
init_packet( &pkt );
|
||||
pkt.pkttype = use_mdc? PKT_ENCRYPTED_MDC : PKT_ENCRYPTED;
|
||||
pkt.pkt.encrypted = &ed;
|
||||
if( build_packet( a, &pkt ))
|
||||
log_bug("build_packet(ENCR_DATA) failed\n");
|
||||
nprefix = blocksize;
|
||||
gcry_randomize( temp, nprefix, GCRY_STRONG_RANDOM );
|
||||
randomize_buffer( temp, nprefix, 1 );
|
||||
temp[nprefix] = temp[nprefix-2];
|
||||
temp[nprefix+1] = temp[nprefix-1];
|
||||
print_cipher_algo_note( cfx->dek->algo );
|
||||
if( !(cfx->cipher_hd = gcry_cipher_open( cfx->dek->algo,
|
||||
GCRY_CIPHER_MODE_CFB,
|
||||
GCRY_CIPHER_SECURE
|
||||
| ((use_mdc || cfx->dek->algo >= 100) ?
|
||||
0 : GCRY_CIPHER_ENABLE_SYNC)))
|
||||
) {
|
||||
/* we should never get an error here cause we already checked, that
|
||||
* the algorithm is available. */
|
||||
BUG();
|
||||
}
|
||||
|
||||
|
||||
cfx->cipher_hd = cipher_open( cfx->dek->algo,
|
||||
use_mdc? CIPHER_MODE_CFB
|
||||
: CIPHER_MODE_AUTO_CFB, 1 );
|
||||
/* log_hexdump( "thekey", cfx->dek->key, cfx->dek->keylen );*/
|
||||
rc = gcry_cipher_setkey( cfx->cipher_hd, cfx->dek->key, cfx->dek->keylen );
|
||||
if( !rc )
|
||||
rc = gcry_cipher_setiv( cfx->cipher_hd, NULL, 0 );
|
||||
if( rc )
|
||||
log_fatal("set key or IV failed: %s\n", gcry_strerror(rc) );
|
||||
cipher_setkey( cfx->cipher_hd, cfx->dek->key, cfx->dek->keylen );
|
||||
cipher_setiv( cfx->cipher_hd, NULL, 0 );
|
||||
/* log_hexdump( "prefix", temp, nprefix+2 ); */
|
||||
if( cfx->mdc_hash )
|
||||
gcry_md_write( cfx->mdc_hash, temp, nprefix+2 );
|
||||
rc = gcry_cipher_encrypt( cfx->cipher_hd, temp, nprefix+2, NULL, 0 );
|
||||
if( !rc )
|
||||
rc = gcry_cipher_sync( cfx->cipher_hd );
|
||||
if( rc )
|
||||
log_fatal("encrypt failed: %s\n", gcry_strerror(rc) );
|
||||
if( cfx->mdc_hash ) /* hash the "IV" */
|
||||
md_write( cfx->mdc_hash, temp, nprefix+2 );
|
||||
cipher_encrypt( cfx->cipher_hd, temp, temp, nprefix+2);
|
||||
cipher_sync( cfx->cipher_hd );
|
||||
iobuf_write(a, temp, nprefix+2);
|
||||
cfx->header=1;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -129,46 +129,39 @@ cipher_filter( void *opaque, int control,
|
||||
else if( control == IOBUFCTRL_FLUSH ) { /* encrypt */
|
||||
assert(a);
|
||||
if( !cfx->header ) {
|
||||
write_status( STATUS_BEGIN_ENCRYPTION );
|
||||
write_header( cfx, a );
|
||||
}
|
||||
if( cfx->mdc_hash )
|
||||
gcry_md_write( cfx->mdc_hash, buf, size );
|
||||
rc = gcry_cipher_encrypt( cfx->cipher_hd, buf, size, NULL, 0);
|
||||
if( rc )
|
||||
log_fatal("encrypt failed: %s\n", gcry_strerror(rc) );
|
||||
md_write( cfx->mdc_hash, buf, size );
|
||||
cipher_encrypt( cfx->cipher_hd, buf, buf, size);
|
||||
if( iobuf_write( a, buf, size ) )
|
||||
rc = GPGERR_WRITE_FILE;
|
||||
rc = G10ERR_WRITE_FILE;
|
||||
}
|
||||
else if( control == IOBUFCTRL_FREE ) {
|
||||
if( cfx->mdc_hash ) {
|
||||
byte *hash;
|
||||
int hashlen = gcry_md_get_algo_dlen( gcry_md_get_algo( cfx->mdc_hash ) );
|
||||
int hashlen = md_digest_length( md_get_algo( cfx->mdc_hash ) );
|
||||
byte temp[22];
|
||||
|
||||
assert( hashlen == 20 );
|
||||
/* we must hash the prefix of the MDC packet here */
|
||||
temp[0] = 0xd3;
|
||||
temp[1] = 0x14;
|
||||
gcry_md_putc( cfx->mdc_hash, temp[0] );
|
||||
gcry_md_putc( cfx->mdc_hash, temp[1] );
|
||||
md_putc( cfx->mdc_hash, temp[0] );
|
||||
md_putc( cfx->mdc_hash, temp[1] );
|
||||
|
||||
hash = gcry_md_read( cfx->mdc_hash, 0 );
|
||||
md_final( cfx->mdc_hash );
|
||||
hash = md_read( cfx->mdc_hash, 0 );
|
||||
memcpy(temp+2, hash, 20);
|
||||
rc = gcry_cipher_encrypt( cfx->cipher_hd, temp, 22, NULL, 0 );
|
||||
if( rc )
|
||||
log_fatal("encrypt failed: %s\n", gcry_strerror(rc) );
|
||||
gcry_md_close( cfx->mdc_hash ); cfx->mdc_hash = NULL;
|
||||
cipher_encrypt( cfx->cipher_hd, temp, temp, 22 );
|
||||
md_close( cfx->mdc_hash ); cfx->mdc_hash = NULL;
|
||||
if( iobuf_write( a, temp, 22 ) )
|
||||
log_error("writing MDC packet failed\n" );
|
||||
}
|
||||
gcry_cipher_close(cfx->cipher_hd);
|
||||
write_status( STATUS_END_ENCRYPTION );
|
||||
cipher_close(cfx->cipher_hd);
|
||||
}
|
||||
else if( control == IOBUFCTRL_DESC ) {
|
||||
*(char**)buf = "cipher_filter";
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* comment.c - write comment stuff
|
||||
* Copyright (C) 1998, 2000 Free Software Foundation, Inc.
|
||||
* Copyright (C) 1998 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
@ -29,7 +29,7 @@
|
||||
#include "packet.h"
|
||||
#include "errors.h"
|
||||
#include "iobuf.h"
|
||||
#include <gcrypt.h>
|
||||
#include "memory.h"
|
||||
#include "util.h"
|
||||
#include "main.h"
|
||||
#include "keydb.h"
|
||||
@ -45,41 +45,59 @@ write_comment( IOBUF out, const char *s )
|
||||
|
||||
pkt.pkttype = PKT_COMMENT;
|
||||
if( *s != '#' ) {
|
||||
pkt.pkt.comment = gcry_xmalloc( sizeof *pkt.pkt.comment + n );
|
||||
pkt.pkt.comment = m_alloc( sizeof *pkt.pkt.comment + n );
|
||||
pkt.pkt.comment->len = n+1;
|
||||
*pkt.pkt.comment->data = '#';
|
||||
strcpy(pkt.pkt.comment->data+1, s);
|
||||
}
|
||||
else {
|
||||
pkt.pkt.comment = gcry_xmalloc( sizeof *pkt.pkt.comment + n - 1 );
|
||||
pkt.pkt.comment = m_alloc( sizeof *pkt.pkt.comment + n - 1 );
|
||||
pkt.pkt.comment->len = n;
|
||||
strcpy(pkt.pkt.comment->data, s);
|
||||
}
|
||||
if( (rc = build_packet( out, &pkt )) )
|
||||
log_error("build_packet(comment) failed: %s\n", gpg_errstr(rc) );
|
||||
log_error("build_packet(comment) failed: %s\n", g10_errstr(rc) );
|
||||
free_packet( &pkt );
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
KBNODE
|
||||
make_comment_node_from_buffer( const char *s, size_t n )
|
||||
make_comment_node( const char *s )
|
||||
{
|
||||
PACKET *pkt;
|
||||
size_t n = strlen(s);
|
||||
|
||||
pkt = gcry_xcalloc( 1, sizeof *pkt );
|
||||
pkt = m_alloc_clear( sizeof *pkt );
|
||||
pkt->pkttype = PKT_COMMENT;
|
||||
pkt->pkt.comment = gcry_xmalloc( sizeof *pkt->pkt.comment + n - 1 );
|
||||
pkt->pkt.comment = m_alloc( sizeof *pkt->pkt.comment + n - 1 );
|
||||
pkt->pkt.comment->len = n;
|
||||
strcpy(pkt->pkt.comment->data, s);
|
||||
return new_kbnode( pkt );
|
||||
}
|
||||
|
||||
|
||||
KBNODE
|
||||
make_comment_node( const char *s )
|
||||
make_mpi_comment_node( const char *s, MPI a )
|
||||
{
|
||||
return make_comment_node_from_buffer ( s, strlen (s) );
|
||||
PACKET *pkt;
|
||||
byte *buf, *p, *pp;
|
||||
unsigned n1, nb1;
|
||||
size_t n = strlen(s);
|
||||
|
||||
nb1 = mpi_get_nbits( a );
|
||||
p = buf = mpi_get_buffer( a, &n1, NULL );
|
||||
pkt = m_alloc_clear( sizeof *pkt );
|
||||
pkt->pkttype = PKT_COMMENT;
|
||||
pkt->pkt.comment = m_alloc( sizeof *pkt->pkt.comment + n + 2 + n1 );
|
||||
pkt->pkt.comment->len = n+1+2+n1;
|
||||
pp = pkt->pkt.comment->data;
|
||||
memcpy(pp, s, n+1);
|
||||
pp[n+1] = nb1 >> 8;
|
||||
pp[n+2] = nb1 ;
|
||||
memcpy(pp+n+3, p, n1 );
|
||||
m_free(buf);
|
||||
return new_kbnode( pkt );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* compress.c - compress filter
|
||||
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
|
||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
@ -27,10 +27,11 @@
|
||||
#include <errno.h>
|
||||
#include <zlib.h>
|
||||
|
||||
#include <gcrypt.h>
|
||||
#include "util.h"
|
||||
#include "memory.h"
|
||||
#include "packet.h"
|
||||
#include "filter.h"
|
||||
#include "main.h"
|
||||
#include "options.h"
|
||||
|
||||
|
||||
@ -63,7 +64,7 @@ init_compress( compress_filter_context_t *zfx, z_stream *zs )
|
||||
}
|
||||
|
||||
zfx->outbufsize = 8192;
|
||||
zfx->outbuf = gcry_xmalloc( zfx->outbufsize );
|
||||
zfx->outbuf = m_alloc( zfx->outbufsize );
|
||||
}
|
||||
|
||||
static int
|
||||
@ -73,7 +74,11 @@ do_compress( compress_filter_context_t *zfx, z_stream *zs, int flush, IOBUF a )
|
||||
unsigned n;
|
||||
|
||||
do {
|
||||
#ifndef __riscos__
|
||||
zs->next_out = zfx->outbuf;
|
||||
#else /* __riscos__ */
|
||||
zs->next_out = (Bytef *) zfx->outbuf;
|
||||
#endif /* __riscos__ */
|
||||
zs->avail_out = zfx->outbufsize;
|
||||
if( DBG_FILTER )
|
||||
log_debug("enter deflate: avail_in=%u, avail_out=%u, flush=%d\n",
|
||||
@ -96,7 +101,7 @@ do_compress( compress_filter_context_t *zfx, z_stream *zs, int flush, IOBUF a )
|
||||
|
||||
if( iobuf_write( a, zfx->outbuf, n ) ) {
|
||||
log_debug("deflate: iobuf_write failed\n");
|
||||
return GPGERR_WRITE_FILE;
|
||||
return G10ERR_WRITE_FILE;
|
||||
}
|
||||
} while( zs->avail_in || (flush == Z_FINISH && zrc != Z_STREAM_END) );
|
||||
return 0;
|
||||
@ -121,7 +126,7 @@ init_uncompress( compress_filter_context_t *zfx, z_stream *zs )
|
||||
}
|
||||
|
||||
zfx->inbufsize = 2048;
|
||||
zfx->inbuf = gcry_xmalloc( zfx->inbufsize );
|
||||
zfx->inbuf = m_alloc( zfx->inbufsize );
|
||||
zs->avail_in = 0;
|
||||
}
|
||||
|
||||
@ -143,7 +148,11 @@ do_uncompress( compress_filter_context_t *zfx, z_stream *zs,
|
||||
if( zs->avail_in < zfx->inbufsize && refill ) {
|
||||
n = zs->avail_in;
|
||||
if( !n )
|
||||
#ifndef __riscos__
|
||||
zs->next_in = zfx->inbuf;
|
||||
#else /* __riscos__ */
|
||||
zs->next_in = (Bytef *) zfx->inbuf;
|
||||
#endif /* __riscos__ */
|
||||
count = zfx->inbufsize - n;
|
||||
nread = iobuf_read( a, zfx->inbuf + n, count );
|
||||
if( nread == -1 ) nread = 0;
|
||||
@ -196,12 +205,16 @@ compress_filter( void *opaque, int control,
|
||||
|
||||
if( control == IOBUFCTRL_UNDERFLOW ) {
|
||||
if( !zfx->status ) {
|
||||
zs = zfx->opaque = gcry_xcalloc( 1, sizeof *zs );
|
||||
zs = zfx->opaque = m_alloc_clear( sizeof *zs );
|
||||
init_uncompress( zfx, zs );
|
||||
zfx->status = 1;
|
||||
}
|
||||
|
||||
#ifndef __riscos__
|
||||
zs->next_out = buf;
|
||||
#else /* __riscos__ */
|
||||
zs->next_out = (Bytef *) buf;
|
||||
#endif /* __riscos__ */
|
||||
zs->avail_out = size;
|
||||
zfx->outbufsize = size; /* needed only for calculation */
|
||||
rc = do_uncompress( zfx, zs, a, ret_len );
|
||||
@ -212,7 +225,9 @@ compress_filter( void *opaque, int control,
|
||||
PKT_compressed cd;
|
||||
|
||||
if( !zfx->algo )
|
||||
zfx->algo = opt.def_compress_algo;
|
||||
zfx->algo = DEFAULT_COMPRESS_ALGO;
|
||||
if( zfx->algo != 1 && zfx->algo != 2 )
|
||||
BUG();
|
||||
memset( &cd, 0, sizeof cd );
|
||||
cd.len = 0;
|
||||
cd.algorithm = zfx->algo;
|
||||
@ -221,37 +236,54 @@ compress_filter( void *opaque, int control,
|
||||
pkt.pkt.compressed = &cd;
|
||||
if( build_packet( a, &pkt ))
|
||||
log_bug("build_packet(PKT_COMPRESSED) failed\n");
|
||||
zs = zfx->opaque = gcry_xcalloc( 1, sizeof *zs );
|
||||
zs = zfx->opaque = m_alloc_clear( sizeof *zs );
|
||||
init_compress( zfx, zs );
|
||||
zfx->status = 2;
|
||||
}
|
||||
|
||||
#ifndef __riscos__
|
||||
zs->next_in = buf;
|
||||
#else /* __riscos__ */
|
||||
zs->next_in = (Bytef *) buf;
|
||||
#endif /* __riscos__ */
|
||||
zs->avail_in = size;
|
||||
rc = do_compress( zfx, zs, Z_NO_FLUSH, a );
|
||||
}
|
||||
else if( control == IOBUFCTRL_FREE ) {
|
||||
if( zfx->status == 1 ) {
|
||||
inflateEnd(zs);
|
||||
gcry_free(zs);
|
||||
m_free(zs);
|
||||
zfx->opaque = NULL;
|
||||
gcry_free(zfx->outbuf); zfx->outbuf = NULL;
|
||||
m_free(zfx->outbuf); zfx->outbuf = NULL;
|
||||
}
|
||||
else if( zfx->status == 2 ) {
|
||||
#ifndef __riscos__
|
||||
zs->next_in = buf;
|
||||
#else /* __riscos__ */
|
||||
zs->next_in = (Bytef *) buf;
|
||||
#endif /* __riscos__ */
|
||||
zs->avail_in = 0;
|
||||
do_compress( zfx, zs, Z_FINISH, a );
|
||||
deflateEnd(zs);
|
||||
gcry_free(zs);
|
||||
m_free(zs);
|
||||
zfx->opaque = NULL;
|
||||
gcry_free(zfx->outbuf); zfx->outbuf = NULL;
|
||||
m_free(zfx->outbuf); zfx->outbuf = NULL;
|
||||
}
|
||||
if (zfx->release)
|
||||
zfx->release (zfx);
|
||||
}
|
||||
else if( control == IOBUFCTRL_DESC )
|
||||
*(char**)buf = "compress_filter";
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
release_context (compress_filter_context_t *ctx)
|
||||
{
|
||||
m_free (ctx);
|
||||
}
|
||||
|
||||
/****************
|
||||
* Handle a compressed packet
|
||||
*/
|
||||
@ -259,26 +291,19 @@ int
|
||||
handle_compressed( void *procctx, PKT_compressed *cd,
|
||||
int (*callback)(IOBUF, void *), void *passthru )
|
||||
{
|
||||
compress_filter_context_t cfx;
|
||||
compress_filter_context_t *cfx;
|
||||
int rc;
|
||||
|
||||
memset( &cfx, 0, sizeof cfx );
|
||||
if( cd->algorithm < 1 || cd->algorithm > 2 )
|
||||
return GPGERR_COMPR_ALGO;
|
||||
cfx.algo = cd->algorithm;
|
||||
|
||||
iobuf_push_filter( cd->buf, compress_filter, &cfx );
|
||||
return G10ERR_COMPR_ALGO;
|
||||
cfx = m_alloc_clear (sizeof *cfx);
|
||||
cfx->algo = cd->algorithm;
|
||||
cfx->release = release_context;
|
||||
iobuf_push_filter( cd->buf, compress_filter, cfx );
|
||||
if( callback )
|
||||
rc = callback(cd->buf, passthru );
|
||||
else
|
||||
rc = proc_packets(procctx, cd->buf);
|
||||
#if 0
|
||||
iobuf_pop_filter( cd->buf, compress_filter, &cfx );
|
||||
if( cd->len )
|
||||
iobuf_set_limit( cd->buf, 0 ); /* disable the readlimit */
|
||||
else
|
||||
iobuf_clear_eof( cd->buf );
|
||||
#endif
|
||||
cd->buf = NULL;
|
||||
return rc;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* dearmor.c - Armor utility
|
||||
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
|
||||
* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
@ -25,9 +25,9 @@
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <gcrypt.h>
|
||||
#include "errors.h"
|
||||
#include "iobuf.h"
|
||||
#include "memory.h"
|
||||
#include "util.h"
|
||||
#include "filter.h"
|
||||
#include "packet.h"
|
||||
@ -52,7 +52,7 @@ dearmor_file( const char *fname )
|
||||
if( !(inp = iobuf_open(fname)) ) {
|
||||
log_error("can't open %s: %s\n", fname? fname: "[stdin]",
|
||||
strerror(errno) );
|
||||
rc = GPGERR_OPEN_FILE;
|
||||
rc = G10ERR_OPEN_FILE;
|
||||
goto leave;
|
||||
}
|
||||
|
||||
@ -94,7 +94,7 @@ enarmor_file( const char *fname )
|
||||
if( !(inp = iobuf_open(fname)) ) {
|
||||
log_error("can't open %s: %s\n", fname? fname: "[stdin]",
|
||||
strerror(errno) );
|
||||
rc = GPGERR_OPEN_FILE;
|
||||
rc = G10ERR_OPEN_FILE;
|
||||
goto leave;
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* decrypt.c - verify signed data
|
||||
* Copyright (C) 1998, 2000 Free Software Foundation, Inc.
|
||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
@ -25,14 +25,15 @@
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <gcrypt.h>
|
||||
#include "options.h"
|
||||
#include "packet.h"
|
||||
#include "errors.h"
|
||||
#include "iobuf.h"
|
||||
#include "keydb.h"
|
||||
#include "memory.h"
|
||||
#include "util.h"
|
||||
#include "main.h"
|
||||
#include "status.h"
|
||||
#include "i18n.h"
|
||||
|
||||
|
||||
@ -57,7 +58,7 @@ decrypt_message( const char *filename )
|
||||
fp = iobuf_open(filename);
|
||||
if( !fp ) {
|
||||
log_error(_("can't open `%s'\n"), print_fname_stdin(filename));
|
||||
return GPGERR_OPEN_FILE;
|
||||
return G10ERR_OPEN_FILE;
|
||||
}
|
||||
|
||||
if( !opt.no_armor ) {
|
||||
@ -78,5 +79,60 @@ decrypt_message( const char *filename )
|
||||
return rc;
|
||||
}
|
||||
|
||||
void
|
||||
decrypt_messages(int nfiles, char **files)
|
||||
{
|
||||
IOBUF fp;
|
||||
armor_filter_context_t afx;
|
||||
char *p, *output = NULL;
|
||||
int rc = 0;
|
||||
|
||||
if (opt.outfile)
|
||||
{
|
||||
log_error(_("--output doesn't work for this command\n"));
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
while (nfiles--)
|
||||
{
|
||||
print_file_status(STATUS_FILE_START, *files, 3);
|
||||
output = make_outfile_name(*files);
|
||||
if (!output)
|
||||
continue;
|
||||
fp = iobuf_open(*files);
|
||||
if (!fp)
|
||||
{
|
||||
log_error(_("can't open `%s'\n"), print_fname_stdin(*files));
|
||||
continue;
|
||||
}
|
||||
if (!opt.no_armor)
|
||||
{
|
||||
if (use_armor_filter(fp))
|
||||
{
|
||||
memset(&afx, 0, sizeof afx);
|
||||
iobuf_push_filter(fp, armor_filter, &afx);
|
||||
}
|
||||
}
|
||||
rc = proc_packets(NULL, fp);
|
||||
iobuf_close(fp);
|
||||
if (rc)
|
||||
log_error("%s: decryption failed: %s\n", print_fname_stdin(*files),
|
||||
g10_errstr(rc));
|
||||
p = get_last_passphrase();
|
||||
set_next_passphrase(p);
|
||||
m_free (p);
|
||||
files++;
|
||||
m_free(output);
|
||||
write_status( STATUS_FILE_DONE );
|
||||
}
|
||||
set_next_passphrase(NULL);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
104
g10/delkey.c
104
g10/delkey.c
@ -1,5 +1,5 @@
|
||||
/* delkey.c - delete keys
|
||||
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
|
||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
@ -31,7 +31,7 @@
|
||||
#include "errors.h"
|
||||
#include "iobuf.h"
|
||||
#include "keydb.h"
|
||||
#include <gcrypt.h>
|
||||
#include "memory.h"
|
||||
#include "util.h"
|
||||
#include "main.h"
|
||||
#include "trustdb.h"
|
||||
@ -43,34 +43,46 @@
|
||||
|
||||
/****************
|
||||
* Delete a public or secret key from a keyring.
|
||||
* r_sec_avail will be set if a secret key is available and the public
|
||||
* key can't be deleted for that reason.
|
||||
*/
|
||||
int
|
||||
delete_key( const char *username, int secret )
|
||||
static int
|
||||
do_delete_key( const char *username, int secret, int *r_sec_avail )
|
||||
{
|
||||
int rc = 0;
|
||||
KBNODE keyblock = NULL;
|
||||
KBNODE node;
|
||||
KBPOS kbpos;
|
||||
KEYDB_HANDLE hd = keydb_new (secret);
|
||||
PKT_public_key *pk = NULL;
|
||||
PKT_secret_key *sk = NULL;
|
||||
u32 keyid[2];
|
||||
int okay=0;
|
||||
int yes;
|
||||
KEYDB_SEARCH_DESC desc;
|
||||
|
||||
*r_sec_avail = 0;
|
||||
|
||||
/* search the userid */
|
||||
rc = secret? find_secret_keyblock_byname( &keyblock, username )
|
||||
: find_keyblock_byname( &keyblock, username );
|
||||
if( rc ) {
|
||||
log_error(_("%s: user not found: %s\n"), username, gpg_errstr(rc) );
|
||||
classify_user_id (username, &desc);
|
||||
rc = desc.mode? keydb_search (hd, &desc, 1):G10ERR_INV_USER_ID;
|
||||
if (rc) {
|
||||
log_error (_("key `%s' not found: %s\n"), username, g10_errstr (rc));
|
||||
write_status_text( STATUS_DELETE_PROBLEM, "1" );
|
||||
goto leave;
|
||||
}
|
||||
|
||||
/* read the keyblock */
|
||||
rc = keydb_get_keyblock (hd, &keyblock );
|
||||
if (rc) {
|
||||
log_error (_("error reading keyblock: %s\n"), g10_errstr(rc) );
|
||||
goto leave;
|
||||
}
|
||||
|
||||
/* get the keyid from the keyblock */
|
||||
node = find_kbnode( keyblock, secret? PKT_SECRET_KEY:PKT_PUBLIC_KEY );
|
||||
if( !node ) {
|
||||
log_error("Oops; key not found anymore!\n");
|
||||
rc = GPGERR_GENERAL;
|
||||
rc = G10ERR_GENERAL;
|
||||
goto leave;
|
||||
}
|
||||
|
||||
@ -83,15 +95,12 @@ delete_key( const char *username, int secret )
|
||||
keyid_from_pk( pk, keyid );
|
||||
rc = seckey_available( keyid );
|
||||
if( !rc ) {
|
||||
log_error(_(
|
||||
"there is a secret key for this public key!\n"));
|
||||
log_info(_(
|
||||
"use option \"--delete-secret-key\" to delete it first.\n"));
|
||||
write_status_text( STATUS_DELETE_PROBLEM, "2" );
|
||||
rc = -1;
|
||||
*r_sec_avail = 1;
|
||||
rc = -1;
|
||||
goto leave;
|
||||
}
|
||||
else if( rc != GPGERR_NO_SECKEY ) {
|
||||
log_error("%s: get secret key: %s\n", username, gpg_errstr(rc) );
|
||||
else if( rc != G10ERR_NO_SECKEY ) {
|
||||
log_error("%s: get secret key: %s\n", username, g10_errstr(rc) );
|
||||
}
|
||||
else
|
||||
rc = 0;
|
||||
@ -113,15 +122,15 @@ delete_key( const char *username, int secret )
|
||||
tty_printf("sec %4u%c/%08lX %s ",
|
||||
nbits_from_sk( sk ),
|
||||
pubkey_letter( sk->pubkey_algo ),
|
||||
keyid[1], datestr_from_sk(sk) );
|
||||
(ulong)keyid[1], datestr_from_sk(sk) );
|
||||
else
|
||||
tty_printf("pub %4u%c/%08lX %s ",
|
||||
nbits_from_pk( pk ),
|
||||
pubkey_letter( pk->pubkey_algo ),
|
||||
keyid[1], datestr_from_pk(pk) );
|
||||
(ulong)keyid[1], datestr_from_pk(pk) );
|
||||
p = get_user_id( keyid, &n );
|
||||
tty_print_utf8_string( p, n );
|
||||
gcry_free(p);
|
||||
m_free(p);
|
||||
tty_printf("\n\n");
|
||||
|
||||
yes = cpr_get_answer_is_yes( secret? "delete_key.secret.okay"
|
||||
@ -142,16 +151,59 @@ delete_key( const char *username, int secret )
|
||||
|
||||
|
||||
if( okay ) {
|
||||
#warning MUST FIX THIS!!!
|
||||
rc = delete_keyblock( &kbpos );
|
||||
if( rc ) {
|
||||
log_error("delete_keyblock failed: %s\n", gpg_errstr(rc) );
|
||||
rc = keydb_delete_keyblock (hd);
|
||||
if (rc) {
|
||||
log_error (_("deleting keyblock failed: %s\n"), g10_errstr(rc) );
|
||||
goto leave;
|
||||
}
|
||||
|
||||
/* Note that the ownertrust being cleared will trigger a
|
||||
revalidation_mark(). This makes sense - only deleting keys
|
||||
that have ownertrust set should trigger this. */
|
||||
|
||||
if (!secret && pk && clear_ownertrust (pk)) {
|
||||
if (opt.verbose)
|
||||
log_info (_("ownertrust information cleared\n"));
|
||||
}
|
||||
}
|
||||
|
||||
leave:
|
||||
release_kbnode( keyblock );
|
||||
keydb_release (hd);
|
||||
release_kbnode (keyblock);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/****************
|
||||
* Delete a public or secret key from a keyring.
|
||||
*/
|
||||
int
|
||||
delete_keys( STRLIST names, int secret, int allow_both )
|
||||
{
|
||||
int rc, avail;
|
||||
|
||||
for(;names;names=names->next) {
|
||||
rc = do_delete_key (names->d, secret, &avail );
|
||||
if ( rc && avail ) {
|
||||
if ( allow_both ) {
|
||||
rc = do_delete_key (names->d, 1, &avail );
|
||||
if ( !rc )
|
||||
rc = do_delete_key (names->d, 0, &avail );
|
||||
}
|
||||
else {
|
||||
log_error(_(
|
||||
"there is a secret key for public key \"%s\"!\n"),names->d);
|
||||
log_info(_(
|
||||
"use option \"--delete-secret-keys\" to delete it first.\n"));
|
||||
write_status_text( STATUS_DELETE_PROBLEM, "2" );
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
if(rc) {
|
||||
log_error("%s: delete key failed: %s\n", names->d, g10_errstr(rc) );
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
519
g10/encode.c
519
g10/encode.c
@ -1,5 +1,5 @@
|
||||
/* encode.c - encode data
|
||||
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
|
||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
@ -30,69 +30,18 @@
|
||||
#include "errors.h"
|
||||
#include "iobuf.h"
|
||||
#include "keydb.h"
|
||||
#include <gcrypt.h>
|
||||
#include "memory.h"
|
||||
#include "util.h"
|
||||
#include "main.h"
|
||||
#include "filter.h"
|
||||
#include "trustdb.h"
|
||||
#include "i18n.h"
|
||||
#include "status.h"
|
||||
|
||||
|
||||
static int encode_simple( const char *filename, int mode );
|
||||
static int encode_simple( const char *filename, int mode, int compat );
|
||||
static int write_pubkey_enc_from_list( PK_LIST pk_list, DEK *dek, IOBUF out );
|
||||
|
||||
|
||||
/****************
|
||||
* Emulate our old PK interface here - sometime in the future we might
|
||||
* change the internal design to directly fit to libgcrypt.
|
||||
*/
|
||||
static int
|
||||
pk_encrypt( int algo, MPI *resarr, MPI data, MPI *pkey )
|
||||
{
|
||||
GCRY_SEXP s_ciph, s_data, s_pkey;
|
||||
int rc;
|
||||
|
||||
/* make a sexp from pkey */
|
||||
if( algo == GCRY_PK_ELG || algo == GCRY_PK_ELG_E ) {
|
||||
rc = gcry_sexp_build ( &s_pkey, NULL,
|
||||
"(public-key(elg(p%m)(g%m)(y%m)))",
|
||||
pkey[0], pkey[1], pkey[2] );
|
||||
}
|
||||
else
|
||||
return GPGERR_PUBKEY_ALGO;
|
||||
|
||||
if ( rc )
|
||||
BUG ();
|
||||
|
||||
/* put the data into a simple list */
|
||||
if ( gcry_sexp_build( &s_data, NULL, "%m", data ) )
|
||||
BUG ();
|
||||
|
||||
/* pass it to libgcrypt */
|
||||
rc = gcry_pk_encrypt( &s_ciph, s_data, s_pkey );
|
||||
gcry_sexp_release( s_data );
|
||||
gcry_sexp_release( s_pkey );
|
||||
|
||||
if( rc )
|
||||
;
|
||||
else { /* add better error handling or make gnupg use S-Exp directly */
|
||||
GCRY_SEXP list = gcry_sexp_find_token( s_ciph, "a" , 0 );
|
||||
assert( list );
|
||||
resarr[0] = gcry_sexp_nth_mpi( list, 1, 0 );
|
||||
assert( resarr[0] );
|
||||
gcry_sexp_release ( list );
|
||||
|
||||
list = gcry_sexp_find_token( s_ciph, "b" , 0 );
|
||||
assert( list );
|
||||
resarr[1] = gcry_sexp_nth_mpi( list, 1, 0 );
|
||||
assert( resarr[1] );
|
||||
gcry_sexp_release ( list );
|
||||
}
|
||||
|
||||
gcry_sexp_release( s_ciph );
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
* Encode FILENAME with only the symmetric cipher. Take input from
|
||||
@ -101,7 +50,11 @@ pk_encrypt( int algo, MPI *resarr, MPI data, MPI *pkey )
|
||||
int
|
||||
encode_symmetric( const char *filename )
|
||||
{
|
||||
return encode_simple( filename, 1 );
|
||||
int compat = 1;
|
||||
|
||||
if ( opt.expert )
|
||||
compat = 0; /* PGP knows how to handle this mode. */
|
||||
return encode_simple( filename, 1, compat );
|
||||
}
|
||||
|
||||
/****************
|
||||
@ -111,19 +64,49 @@ encode_symmetric( const char *filename )
|
||||
int
|
||||
encode_store( const char *filename )
|
||||
{
|
||||
return encode_simple( filename, 0 );
|
||||
return encode_simple( filename, 0, 1 );
|
||||
}
|
||||
|
||||
static void
|
||||
encode_sesskey( DEK *dek, DEK **ret_dek, byte *enckey )
|
||||
{
|
||||
CIPHER_HANDLE hd;
|
||||
DEK *c;
|
||||
byte buf[33];
|
||||
|
||||
assert ( dek->keylen < 32 );
|
||||
|
||||
c = m_alloc_clear( sizeof *c );
|
||||
c->keylen = dek->keylen;
|
||||
c->algo = dek->algo;
|
||||
make_session_key( c );
|
||||
/*log_hexdump( "thekey", c->key, c->keylen );*/
|
||||
|
||||
buf[0] = c->algo;
|
||||
memcpy( buf + 1, c->key, c->keylen );
|
||||
|
||||
hd = cipher_open( dek->algo, CIPHER_MODE_CFB, 1 );
|
||||
cipher_setkey( hd, dek->key, dek->keylen );
|
||||
cipher_setiv( hd, NULL, 0 );
|
||||
cipher_encrypt( hd, buf, buf, c->keylen + 1 );
|
||||
cipher_close( hd );
|
||||
|
||||
memcpy( enckey, buf, c->keylen + 1 );
|
||||
memset( buf, 0, sizeof buf ); /* burn key */
|
||||
*ret_dek = c;
|
||||
}
|
||||
|
||||
static int
|
||||
encode_simple( const char *filename, int mode )
|
||||
encode_simple( const char *filename, int mode, int compat )
|
||||
{
|
||||
IOBUF inp, out;
|
||||
PACKET pkt;
|
||||
DEK *dek = NULL;
|
||||
PKT_plaintext *pt = NULL;
|
||||
STRING2KEY *s2k = NULL;
|
||||
byte enckey[33];
|
||||
int rc = 0;
|
||||
int seskeylen = 0;
|
||||
u32 filesize;
|
||||
cipher_filter_context_t cfx;
|
||||
armor_filter_context_t afx;
|
||||
@ -136,40 +119,62 @@ encode_simple( const char *filename, int mode )
|
||||
memset( &zfx, 0, sizeof zfx);
|
||||
memset( &tfx, 0, sizeof tfx);
|
||||
init_packet(&pkt);
|
||||
|
||||
if (opt.compress == -1 && is_file_compressed(filename, &rc))
|
||||
{
|
||||
if (opt.verbose)
|
||||
log_info(_("`%s' already compressed\n"), filename);
|
||||
do_compress = 0;
|
||||
}
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
/* prepare iobufs */
|
||||
if( !(inp = iobuf_open(filename)) ) {
|
||||
log_error(_("%s: can't open: %s\n"), filename? filename: "[stdin]",
|
||||
strerror(errno) );
|
||||
return GPGERR_OPEN_FILE;
|
||||
return G10ERR_OPEN_FILE;
|
||||
}
|
||||
|
||||
if( opt.textmode )
|
||||
iobuf_push_filter( inp, text_filter, &tfx );
|
||||
|
||||
/* Due the the fact that we use don't use an IV to encrypt the
|
||||
session key we can't use the new mode with RFC1991 because
|
||||
it has no S2K salt. RFC1991 always uses simple S2K. */
|
||||
if ( opt.rfc1991 && !compat )
|
||||
compat = 1;
|
||||
|
||||
cfx.dek = NULL;
|
||||
if( mode ) {
|
||||
s2k = gcry_xcalloc( 1, sizeof *s2k );
|
||||
s2k = m_alloc_clear( sizeof *s2k );
|
||||
s2k->mode = opt.rfc1991? 0:opt.s2k_mode;
|
||||
s2k->hash_algo = opt.def_digest_algo ? opt.def_digest_algo
|
||||
: opt.s2k_digest_algo;
|
||||
cfx.dek = passphrase_to_dek( NULL, 0,
|
||||
opt.def_cipher_algo ? opt.def_cipher_algo
|
||||
: opt.s2k_cipher_algo , s2k, 2 );
|
||||
opt.def_cipher_algo ? opt.def_cipher_algo
|
||||
: opt.s2k_cipher_algo , s2k, 2, NULL );
|
||||
if( !cfx.dek || !cfx.dek->keylen ) {
|
||||
rc = GPGERR_PASSPHRASE;
|
||||
gcry_free(cfx.dek);
|
||||
gcry_free(s2k);
|
||||
rc = G10ERR_PASSPHRASE;
|
||||
m_free(cfx.dek);
|
||||
m_free(s2k);
|
||||
iobuf_close(inp);
|
||||
log_error(_("error creating passphrase: %s\n"), gpg_errstr(rc) );
|
||||
log_error(_("error creating passphrase: %s\n"), g10_errstr(rc) );
|
||||
return rc;
|
||||
}
|
||||
if ( !compat ) {
|
||||
seskeylen = cipher_get_keylen( opt.def_cipher_algo ?
|
||||
opt.def_cipher_algo:
|
||||
opt.s2k_cipher_algo ) / 8;
|
||||
encode_sesskey( cfx.dek, &dek, enckey );
|
||||
m_free( cfx.dek ); cfx.dek = dek;
|
||||
}
|
||||
}
|
||||
|
||||
if( (rc = open_outfile( filename, opt.armor? 1:0, &out )) ) {
|
||||
iobuf_cancel(inp);
|
||||
gcry_free(cfx.dek);
|
||||
gcry_free(s2k);
|
||||
m_free(cfx.dek);
|
||||
m_free(s2k);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -184,15 +189,19 @@ encode_simple( const char *filename, int mode )
|
||||
}
|
||||
#endif
|
||||
if( s2k && !opt.rfc1991 ) {
|
||||
PKT_symkey_enc *enc = gcry_xcalloc( 1, sizeof *enc );
|
||||
PKT_symkey_enc *enc = m_alloc_clear( sizeof *enc + seskeylen + 1 );
|
||||
enc->version = 4;
|
||||
enc->cipher_algo = cfx.dek->algo;
|
||||
enc->s2k = *s2k;
|
||||
if ( !compat && seskeylen ) {
|
||||
enc->seskeylen = seskeylen + 1; /* algo id */
|
||||
memcpy( enc->seskey, enckey, seskeylen + 1 );
|
||||
}
|
||||
pkt.pkttype = PKT_SYMKEY_ENC;
|
||||
pkt.pkt.symkey_enc = enc;
|
||||
if( (rc = build_packet( out, &pkt )) )
|
||||
log_error("build symkey packet failed: %s\n", gpg_errstr(rc) );
|
||||
gcry_free(enc);
|
||||
log_error("build symkey packet failed: %s\n", g10_errstr(rc) );
|
||||
m_free(enc);
|
||||
}
|
||||
|
||||
if (!opt.no_literal) {
|
||||
@ -200,30 +209,36 @@ encode_simple( const char *filename, int mode )
|
||||
if( filename || opt.set_filename ) {
|
||||
char *s = make_basename( opt.set_filename ? opt.set_filename
|
||||
: filename );
|
||||
pt = gcry_xmalloc( sizeof *pt + strlen(s) - 1 );
|
||||
pt = m_alloc( sizeof *pt + strlen(s) - 1 );
|
||||
pt->namelen = strlen(s);
|
||||
memcpy(pt->name, s, pt->namelen );
|
||||
gcry_free(s);
|
||||
m_free(s);
|
||||
}
|
||||
else { /* no filename */
|
||||
pt = gcry_xmalloc( sizeof *pt - 1 );
|
||||
pt = m_alloc( sizeof *pt - 1 );
|
||||
pt->namelen = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* pgp5 has problems to decrypt symmetrically encrypted data from
|
||||
* GnuPG if the filelength is in the inner packet. It works
|
||||
* when only partial length headers are use. Until we have
|
||||
* tracked this problem down. We use this temporary fix
|
||||
* (fixme: remove the && !mode )
|
||||
*/
|
||||
if( filename && !opt.textmode && !mode ) {
|
||||
/* Note that PGP 5 has problems decrypting symmetrically encrypted
|
||||
data if the file length is in the inner packet. It works when
|
||||
only partial length headers are use. In the past, we always
|
||||
used partial body length here, but since PGP 2, PGP 6, and PGP
|
||||
7 need the file length, and nobody should be using PGP 5
|
||||
nowadays anyway, this is now set to the file length. Note also
|
||||
that this only applies to the RFC-1991 style symmetric
|
||||
messages, and not the RFC-2440 style. PGP 6 and 7 work with
|
||||
either partial length or fixed length with the new style
|
||||
messages. */
|
||||
|
||||
if( filename && !opt.textmode ) {
|
||||
if( !(filesize = iobuf_get_filelength(inp)) )
|
||||
log_info(_("%s: WARNING: empty file\n"), filename );
|
||||
/* we can't yet encode the length of very large files,
|
||||
* so we switch to partial length encoding in this case */
|
||||
* so we switch to partial lengthn encoding in this case */
|
||||
if ( filesize >= IOBUF_FILELENGTH_LIMIT )
|
||||
filesize = 0;
|
||||
|
||||
}
|
||||
else
|
||||
filesize = opt.set_filesize ? opt.set_filesize : 0; /* stdin */
|
||||
@ -239,7 +254,11 @@ encode_simple( const char *filename, int mode )
|
||||
cfx.datalen = filesize && !do_compress ? calc_packet_length( &pkt ) : 0;
|
||||
}
|
||||
else
|
||||
cfx.datalen = filesize && !do_compress ? filesize : 0;
|
||||
{
|
||||
cfx.datalen = filesize && !do_compress ? filesize : 0;
|
||||
pkt.pkttype = 0;
|
||||
pkt.pkt.generic = NULL;
|
||||
}
|
||||
|
||||
/* register the cipher filter */
|
||||
if( mode )
|
||||
@ -251,7 +270,7 @@ encode_simple( const char *filename, int mode )
|
||||
/* do the work */
|
||||
if (!opt.no_literal) {
|
||||
if( (rc = build_packet( out, &pkt )) )
|
||||
log_error("build_packet failed: %s\n", gpg_errstr(rc) );
|
||||
log_error("build_packet failed: %s\n", g10_errstr(rc) );
|
||||
}
|
||||
else {
|
||||
/* user requested not to create a literal packet,
|
||||
@ -260,8 +279,8 @@ encode_simple( const char *filename, int mode )
|
||||
int bytes_copied;
|
||||
while ((bytes_copied = iobuf_read(inp, copy_buffer, 4096)) != -1)
|
||||
if (iobuf_write(out, copy_buffer, bytes_copied) == -1) {
|
||||
rc = GPGERR_WRITE_FILE;
|
||||
log_error("copying input to output failed: %s\n", gpg_errstr(rc) );
|
||||
rc = G10ERR_WRITE_FILE;
|
||||
log_error("copying input to output failed: %s\n", g10_errstr(rc) );
|
||||
break;
|
||||
}
|
||||
memset(copy_buffer, 0, 4096); /* burn buffer */
|
||||
@ -271,13 +290,16 @@ encode_simple( const char *filename, int mode )
|
||||
iobuf_close(inp);
|
||||
if (rc)
|
||||
iobuf_cancel(out);
|
||||
else
|
||||
else {
|
||||
iobuf_close(out); /* fixme: check returncode */
|
||||
if (mode)
|
||||
write_status( STATUS_END_ENCRYPTION );
|
||||
}
|
||||
if (pt)
|
||||
pt->buf = NULL;
|
||||
free_packet(&pkt);
|
||||
gcry_free(cfx.dek);
|
||||
gcry_free(s2k);
|
||||
m_free(cfx.dek);
|
||||
m_free(s2k);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -291,123 +313,203 @@ encode_crypt( const char *filename, STRLIST remusr )
|
||||
IOBUF inp = NULL, out = NULL;
|
||||
PACKET pkt;
|
||||
PKT_plaintext *pt = NULL;
|
||||
int rc = 0;
|
||||
int rc = 0, rc2 = 0;
|
||||
u32 filesize;
|
||||
cipher_filter_context_t cfx;
|
||||
armor_filter_context_t afx;
|
||||
compress_filter_context_t zfx;
|
||||
text_filter_context_t tfx;
|
||||
encrypt_filter_context_t efx;
|
||||
PK_LIST pk_list;
|
||||
PK_LIST pk_list,work_list;
|
||||
int do_compress = opt.compress && !opt.rfc1991;
|
||||
|
||||
|
||||
memset( &cfx, 0, sizeof cfx);
|
||||
memset( &afx, 0, sizeof afx);
|
||||
memset( &zfx, 0, sizeof zfx);
|
||||
memset( &tfx, 0, sizeof tfx);
|
||||
memset( &efx, 0, sizeof efx);
|
||||
init_packet(&pkt);
|
||||
|
||||
if( (rc=build_pk_list( remusr, &pk_list, GCRY_PK_USAGE_ENCR)) )
|
||||
if( (rc=build_pk_list( remusr, &pk_list, PUBKEY_USAGE_ENC)) )
|
||||
return rc;
|
||||
|
||||
if(opt.pgp2) {
|
||||
for(work_list=pk_list; work_list; work_list=work_list->next)
|
||||
if(!(is_RSA(work_list->pk->pubkey_algo) &&
|
||||
nbits_from_pk(work_list->pk)<=2048))
|
||||
{
|
||||
log_info(_("you can only encrypt to RSA keys of 2048 bits or "
|
||||
"less in --pgp2 mode\n"));
|
||||
log_info(_("this message may not be usable by PGP 2.x\n"));
|
||||
opt.pgp2=0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (opt.compress == -1 && is_file_compressed(filename, &rc2))
|
||||
{
|
||||
if (opt.verbose)
|
||||
log_info(_("`%s' already compressed\n"), filename);
|
||||
do_compress = 0;
|
||||
}
|
||||
if (rc2)
|
||||
{
|
||||
rc = rc2;
|
||||
goto leave;
|
||||
}
|
||||
|
||||
/* prepare iobufs */
|
||||
if( !(inp = iobuf_open(filename)) ) {
|
||||
log_error(_("can't open %s: %s\n"), filename? filename: "[stdin]",
|
||||
strerror(errno) );
|
||||
rc = GPGERR_OPEN_FILE;
|
||||
rc = G10ERR_OPEN_FILE;
|
||||
goto leave;
|
||||
}
|
||||
else if( opt.verbose )
|
||||
log_info(_("reading from `%s'\n"), filename? filename: "[stdin]");
|
||||
|
||||
/* If the user selected textmode, push the text filter onto the input */
|
||||
if( opt.textmode )
|
||||
iobuf_push_filter( inp, text_filter, &tfx );
|
||||
|
||||
/* Now we can create the outputfile */
|
||||
if( (rc = open_outfile( filename, opt.armor? 1:0, &out )) )
|
||||
goto leave;
|
||||
|
||||
/* The first thing we have to push on the output stream
|
||||
* is the armor filter */
|
||||
|
||||
if( opt.armor )
|
||||
iobuf_push_filter( out, armor_filter, &afx );
|
||||
#ifdef ENABLE_COMMENT_PACKETS
|
||||
else {
|
||||
write_comment( out, "#created by GNUPG v" VERSION " ("
|
||||
PRINTABLE_OS_NAME ")");
|
||||
if( opt.comment_string )
|
||||
write_comment( out, opt.comment_string );
|
||||
}
|
||||
#endif
|
||||
/* create a session key */
|
||||
cfx.dek = m_alloc_secure_clear (sizeof *cfx.dek);
|
||||
if( !opt.def_cipher_algo ) { /* try to get it from the prefs */
|
||||
cfx.dek->algo = select_algo_from_prefs(pk_list,PREFTYPE_SYM,-1,NULL);
|
||||
/* The only way select_algo_from_prefs can fail here is when
|
||||
mixing v3 and v4 keys, as v4 keys have an implicit
|
||||
preference entry for 3DES, and the pk_list cannot be empty.
|
||||
In this case, use 3DES anyway as it's the safest choice -
|
||||
perhaps the v3 key is being used in an OpenPGP
|
||||
implementation and we know that the implementation behind
|
||||
any v4 key can handle 3DES. */
|
||||
if( cfx.dek->algo == -1 ) {
|
||||
cfx.dek->algo = CIPHER_ALGO_3DES;
|
||||
|
||||
/* Prepare the plaintext packet */
|
||||
{
|
||||
if (!opt.no_literal) {
|
||||
if( filename || opt.set_filename ) {
|
||||
char *s = make_basename( opt.set_filename ?
|
||||
opt.set_filename : filename );
|
||||
pt = gcry_xmalloc( sizeof *pt + strlen(s) - 1 );
|
||||
pt->namelen = strlen(s);
|
||||
memcpy(pt->name, s, pt->namelen );
|
||||
gcry_free(s);
|
||||
}
|
||||
else { /* no filename */
|
||||
pt = gcry_xmalloc( sizeof *pt - 1 );
|
||||
pt->namelen = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if( filename && !opt.textmode ) {
|
||||
if( !(filesize = iobuf_get_filelength(inp)) )
|
||||
log_info(_("%s: WARNING: empty file\n"), filename );
|
||||
/* we can't yet encode the length of very large files,
|
||||
* so we switch to partial lengthn encoding in this case */
|
||||
if ( filesize >= IOBUF_FILELENGTH_LIMIT )
|
||||
filesize = 0;
|
||||
}
|
||||
else
|
||||
filesize = opt.set_filesize ? opt.set_filesize : 0; /* stdin */
|
||||
|
||||
if (!opt.no_literal) {
|
||||
pt->timestamp = make_timestamp();
|
||||
pt->mode = opt.textmode ? 't' : 'b';
|
||||
pt->len = filesize;
|
||||
pt->new_ctb = !pt->len && !opt.rfc1991;
|
||||
pt->buf = inp;
|
||||
pkt.pkttype = PKT_PLAINTEXT;
|
||||
pkt.pkt.plaintext = pt;
|
||||
efx.cfx.datalen = filesize && !do_compress?
|
||||
calc_packet_length( &pkt ) : 0;
|
||||
}
|
||||
else
|
||||
efx.cfx.datalen = filesize && !do_compress ? filesize : 0;
|
||||
} /* end preparation of plaintext packet */
|
||||
|
||||
/* push in the actual encryption filter */
|
||||
efx.pk_list = pk_list;
|
||||
iobuf_push_filter( out, encrypt_filter, &efx );
|
||||
|
||||
/* register the compress filter (so that it is done before encryption) */
|
||||
if( do_compress ) {
|
||||
int compr_algo = select_algo_from_prefs( pk_list, PREFTYPE_COMPR );
|
||||
if( !compr_algo )
|
||||
; /* don't use compression */
|
||||
else {
|
||||
if( compr_algo == 1 )
|
||||
zfx.algo = 1; /* default is 2 */
|
||||
iobuf_push_filter( out, compress_filter, &zfx );
|
||||
if( opt.pgp2 ) {
|
||||
log_info(_("unable to use the IDEA cipher for all of the keys "
|
||||
"you are encrypting to.\n"));
|
||||
log_info(_("this message may not be usable by PGP 2.x\n"));
|
||||
opt.pgp2=0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(!opt.expert &&
|
||||
select_algo_from_prefs(pk_list,PREFTYPE_SYM,
|
||||
opt.def_cipher_algo,NULL)!=opt.def_cipher_algo)
|
||||
log_info(_("forcing symmetric cipher %s (%d) "
|
||||
"violates recipient preferences\n"),
|
||||
cipher_algo_to_string(opt.def_cipher_algo),
|
||||
opt.def_cipher_algo);
|
||||
|
||||
cfx.dek->algo = opt.def_cipher_algo;
|
||||
}
|
||||
cfx.dek->use_mdc = select_mdc_from_pklist (pk_list);
|
||||
|
||||
make_session_key( cfx.dek );
|
||||
if( DBG_CIPHER )
|
||||
log_hexdump("DEK is: ", cfx.dek->key, cfx.dek->keylen );
|
||||
|
||||
rc = write_pubkey_enc_from_list( pk_list, cfx.dek, out );
|
||||
if( rc )
|
||||
goto leave;
|
||||
|
||||
if (!opt.no_literal) {
|
||||
/* setup the inner packet */
|
||||
if( filename || opt.set_filename ) {
|
||||
char *s = make_basename( opt.set_filename ? opt.set_filename : filename );
|
||||
pt = m_alloc( sizeof *pt + strlen(s) - 1 );
|
||||
pt->namelen = strlen(s);
|
||||
memcpy(pt->name, s, pt->namelen );
|
||||
m_free(s);
|
||||
}
|
||||
else { /* no filename */
|
||||
pt = m_alloc( sizeof *pt - 1 );
|
||||
pt->namelen = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if( filename && !opt.textmode ) {
|
||||
if( !(filesize = iobuf_get_filelength(inp)) )
|
||||
log_info(_("%s: WARNING: empty file\n"), filename );
|
||||
/* we can't yet encode the length of very large files,
|
||||
* so we switch to partial length encoding in this case */
|
||||
if ( filesize >= IOBUF_FILELENGTH_LIMIT )
|
||||
filesize = 0;
|
||||
}
|
||||
else
|
||||
filesize = opt.set_filesize ? opt.set_filesize : 0; /* stdin */
|
||||
|
||||
if (!opt.no_literal) {
|
||||
pt->timestamp = make_timestamp();
|
||||
pt->mode = opt.textmode ? 't' : 'b';
|
||||
pt->len = filesize;
|
||||
pt->new_ctb = !pt->len && !opt.rfc1991;
|
||||
pt->buf = inp;
|
||||
pkt.pkttype = PKT_PLAINTEXT;
|
||||
pkt.pkt.plaintext = pt;
|
||||
cfx.datalen = filesize && !do_compress? calc_packet_length( &pkt ) : 0;
|
||||
}
|
||||
else
|
||||
cfx.datalen = filesize && !do_compress ? filesize : 0;
|
||||
|
||||
/* register the cipher filter */
|
||||
iobuf_push_filter( out, cipher_filter, &cfx );
|
||||
|
||||
/* register the compress filter */
|
||||
if( do_compress ) {
|
||||
int compr_algo = opt.def_compress_algo;
|
||||
|
||||
if(compr_algo==-1)
|
||||
{
|
||||
if((compr_algo=
|
||||
select_algo_from_prefs(pk_list,PREFTYPE_ZIP,-1,NULL))==-1)
|
||||
compr_algo=DEFAULT_COMPRESS_ALGO;
|
||||
}
|
||||
else if(!opt.expert &&
|
||||
select_algo_from_prefs(pk_list,PREFTYPE_ZIP,
|
||||
compr_algo,NULL)!=compr_algo)
|
||||
log_info(_("forcing compression algorithm %s (%d) "
|
||||
"violates recipient preferences\n"),
|
||||
compress_algo_to_string(compr_algo),compr_algo);
|
||||
|
||||
/* algo 0 means no compression */
|
||||
if( compr_algo )
|
||||
{
|
||||
zfx.algo = compr_algo;
|
||||
iobuf_push_filter( out, compress_filter, &zfx );
|
||||
}
|
||||
}
|
||||
|
||||
/* do the work */
|
||||
if (!opt.no_literal) {
|
||||
if( (rc = build_packet( out, &pkt )) )
|
||||
log_error("build_packet failed: %s\n", gpg_errstr(rc) );
|
||||
log_error("build_packet failed: %s\n", g10_errstr(rc) );
|
||||
}
|
||||
else {
|
||||
/* user requested not to create a literal packet,
|
||||
* so we copy the plain data */
|
||||
/* user requested not to create a literal packet, so we copy the plain data */
|
||||
byte copy_buffer[4096];
|
||||
int bytes_copied;
|
||||
while ((bytes_copied = iobuf_read(inp, copy_buffer, 4096)) != -1)
|
||||
if (iobuf_write(out, copy_buffer, bytes_copied) == -1) {
|
||||
rc = GPGERR_WRITE_FILE;
|
||||
log_error("copying input to output failed: %s\n", gpg_errstr(rc) );
|
||||
rc = G10ERR_WRITE_FILE;
|
||||
log_error("copying input to output failed: %s\n", g10_errstr(rc) );
|
||||
break;
|
||||
}
|
||||
memset(copy_buffer, 0, DIM(copy_buffer)); /* burn buffer */
|
||||
memset(copy_buffer, 0, 4096); /* burn buffer */
|
||||
}
|
||||
|
||||
/* finish the stuff */
|
||||
@ -415,13 +517,14 @@ encode_crypt( const char *filename, STRLIST remusr )
|
||||
iobuf_close(inp);
|
||||
if( rc )
|
||||
iobuf_cancel(out);
|
||||
else
|
||||
else {
|
||||
iobuf_close(out); /* fixme: check returncode */
|
||||
write_status( STATUS_END_ENCRYPTION );
|
||||
}
|
||||
if( pt )
|
||||
pt->buf = NULL;
|
||||
free_packet(&pkt);
|
||||
gcry_free(efx.cfx.dek); /* Hmmm, why does the encrypt filter does not
|
||||
* take care about this? */
|
||||
m_free(cfx.dek);
|
||||
release_pk_list( pk_list );
|
||||
return rc;
|
||||
}
|
||||
@ -430,7 +533,7 @@ encode_crypt( const char *filename, STRLIST remusr )
|
||||
|
||||
|
||||
/****************
|
||||
* Filter to handle the entire public key encryption.
|
||||
* Filter to do a complete public key encryption.
|
||||
*/
|
||||
int
|
||||
encrypt_filter( void *opaque, int control,
|
||||
@ -445,16 +548,32 @@ encrypt_filter( void *opaque, int control,
|
||||
}
|
||||
else if( control == IOBUFCTRL_FLUSH ) { /* encrypt */
|
||||
if( !efx->header_okay ) {
|
||||
efx->cfx.dek = gcry_xmalloc_secure( sizeof *efx->cfx.dek );
|
||||
efx->cfx.dek = m_alloc_secure_clear( sizeof *efx->cfx.dek );
|
||||
|
||||
if( !opt.def_cipher_algo ) { /* try to get it from the prefs */
|
||||
efx->cfx.dek->algo =
|
||||
select_algo_from_prefs( efx->pk_list, PREFTYPE_SYM );
|
||||
if( efx->cfx.dek->algo == -1 )
|
||||
select_algo_from_prefs(efx->pk_list,PREFTYPE_SYM,-1,NULL);
|
||||
if( efx->cfx.dek->algo == -1 ) {
|
||||
/* because 3DES is implicitly in the prefs, this can only
|
||||
* happen if we do not have any public keys in the list */
|
||||
efx->cfx.dek->algo = DEFAULT_CIPHER_ALGO;
|
||||
}
|
||||
}
|
||||
else
|
||||
efx->cfx.dek->algo = opt.def_cipher_algo;
|
||||
else {
|
||||
if(!opt.expert &&
|
||||
select_algo_from_prefs(efx->pk_list,PREFTYPE_SYM,
|
||||
opt.def_cipher_algo,
|
||||
NULL)!=opt.def_cipher_algo)
|
||||
log_info(_("forcing symmetric cipher %s (%d) "
|
||||
"violates recipient preferences\n"),
|
||||
cipher_algo_to_string(opt.def_cipher_algo),
|
||||
opt.def_cipher_algo);
|
||||
|
||||
efx->cfx.dek->algo = opt.def_cipher_algo;
|
||||
}
|
||||
|
||||
efx->cfx.dek->use_mdc = select_mdc_from_pklist (efx->pk_list);
|
||||
|
||||
make_session_key( efx->cfx.dek );
|
||||
if( DBG_CIPHER )
|
||||
log_hexdump("DEK is: ",
|
||||
@ -497,7 +616,7 @@ write_pubkey_enc_from_list( PK_LIST pk_list, DEK *dek, IOBUF out )
|
||||
pk = pk_list->pk;
|
||||
|
||||
print_pubkey_algo_note( pk->pubkey_algo );
|
||||
enc = gcry_xcalloc( 1, sizeof *enc );
|
||||
enc = m_alloc_clear( sizeof *enc );
|
||||
enc->pubkey_algo = pk->pubkey_algo;
|
||||
keyid_from_pk( pk, enc->keyid );
|
||||
enc->throw_keyid = opt.throw_keyid;
|
||||
@ -517,17 +636,17 @@ write_pubkey_enc_from_list( PK_LIST pk_list, DEK *dek, IOBUF out )
|
||||
*/
|
||||
frame = encode_session_key( dek, pubkey_nbits( pk->pubkey_algo,
|
||||
pk->pkey ) );
|
||||
rc = pk_encrypt( pk->pubkey_algo, enc->data, frame, pk->pkey );
|
||||
mpi_release( frame );
|
||||
rc = pubkey_encrypt( pk->pubkey_algo, enc->data, frame, pk->pkey );
|
||||
mpi_free( frame );
|
||||
if( rc )
|
||||
log_error("pubkey_encrypt failed: %s\n", gpg_errstr(rc) );
|
||||
log_error("pubkey_encrypt failed: %s\n", g10_errstr(rc) );
|
||||
else {
|
||||
if( opt.verbose ) {
|
||||
char *ustr = get_user_id_string_native( enc->keyid );
|
||||
log_info(_("%s/%s encrypted for: %s\n"),
|
||||
gcry_pk_algo_name(enc->pubkey_algo),
|
||||
gcry_cipher_algo_name(dek->algo), ustr );
|
||||
gcry_free(ustr);
|
||||
pubkey_algo_to_string(enc->pubkey_algo),
|
||||
cipher_algo_to_string(dek->algo), ustr );
|
||||
m_free(ustr);
|
||||
}
|
||||
/* and write it */
|
||||
init_packet(&pkt);
|
||||
@ -535,7 +654,7 @@ write_pubkey_enc_from_list( PK_LIST pk_list, DEK *dek, IOBUF out )
|
||||
pkt.pkt.pubkey_enc = enc;
|
||||
rc = build_packet( out, &pkt );
|
||||
if( rc )
|
||||
log_error("build_packet(pubkey_enc) failed: %s\n", gpg_errstr(rc));
|
||||
log_error("build_packet(pubkey_enc) failed: %s\n", g10_errstr(rc));
|
||||
}
|
||||
free_pubkey_enc(enc);
|
||||
if( rc )
|
||||
@ -544,3 +663,47 @@ write_pubkey_enc_from_list( PK_LIST pk_list, DEK *dek, IOBUF out )
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
encode_crypt_files(int nfiles, char **files, STRLIST remusr)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (opt.outfile)
|
||||
{
|
||||
log_error(_("--output doesn't work for this command\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!nfiles)
|
||||
{
|
||||
char line[2048];
|
||||
unsigned int lno = 0;
|
||||
while ( fgets(line, DIM(line), stdin) )
|
||||
{
|
||||
lno++;
|
||||
if (!*line || line[strlen(line)-1] != '\n')
|
||||
{
|
||||
log_error("input line %u too long or missing LF\n", lno);
|
||||
return;
|
||||
}
|
||||
line[strlen(line)-1] = '\0';
|
||||
print_file_status(STATUS_FILE_START, line, 2);
|
||||
if ( (rc = encode_crypt(line, remusr)) )
|
||||
log_error("%s: encryption failed: %s\n",
|
||||
print_fname_stdin(line), g10_errstr(rc) );
|
||||
write_status( STATUS_FILE_DONE );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (nfiles--)
|
||||
{
|
||||
print_file_status(STATUS_FILE_START, *files, 2);
|
||||
if ( (rc = encode_crypt(*files, remusr)) )
|
||||
log_error("%s: encryption failed: %s\n",
|
||||
print_fname_stdin(*files), g10_errstr(rc) );
|
||||
write_status( STATUS_FILE_DONE );
|
||||
files++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* encr-data.c - process an encrypted data packet
|
||||
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
|
||||
* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
@ -23,10 +23,11 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <gcrypt.h>
|
||||
#include "util.h"
|
||||
#include "memory.h"
|
||||
#include "packet.h"
|
||||
#include "mpi.h"
|
||||
#include "cipher.h"
|
||||
#include "options.h"
|
||||
#include "i18n.h"
|
||||
|
||||
@ -37,8 +38,8 @@ static int decode_filter( void *opaque, int control, IOBUF a,
|
||||
byte *buf, size_t *ret_len);
|
||||
|
||||
typedef struct {
|
||||
GCRY_CIPHER_HD cipher_hd;
|
||||
GCRY_MD_HD mdc_hash;
|
||||
CIPHER_HANDLE cipher_hd;
|
||||
MD_HANDLE mdc_hash;
|
||||
char defer[20];
|
||||
int defer_filled;
|
||||
int eof_seen;
|
||||
@ -55,20 +56,21 @@ decrypt_data( void *procctx, PKT_encrypted *ed, DEK *dek )
|
||||
byte *p;
|
||||
int rc=0, c, i;
|
||||
byte temp[32];
|
||||
unsigned int blocksize;
|
||||
unsigned int nprefix;
|
||||
unsigned blocksize;
|
||||
unsigned nprefix;
|
||||
|
||||
memset( &dfx, 0, sizeof dfx );
|
||||
if( gcry_cipher_test_algo( dek->algo ) ) {
|
||||
if( opt.verbose )
|
||||
if( opt.verbose && !dek->algo_info_printed ) {
|
||||
const char *s = cipher_algo_to_string( dek->algo );
|
||||
if( s )
|
||||
log_info(_("%s encrypted data\n"), s );
|
||||
else
|
||||
log_info(_("encrypted with unknown algorithm %d\n"), dek->algo );
|
||||
rc = GPGERR_CIPHER_ALGO;
|
||||
goto leave;
|
||||
dek->algo_info_printed = 1;
|
||||
}
|
||||
if( opt.verbose )
|
||||
log_info(_("%s encrypted data\n"), gcry_cipher_algo_name( dek->algo ) );
|
||||
|
||||
blocksize = gcry_cipher_get_algo_blklen( dek->algo );
|
||||
if( (rc=check_cipher_algo(dek->algo)) )
|
||||
goto leave;
|
||||
blocksize = cipher_get_blocksize(dek->algo);
|
||||
if( !blocksize || blocksize > 16 )
|
||||
log_fatal("unsupported blocksize %u\n", blocksize );
|
||||
nprefix = blocksize;
|
||||
@ -76,36 +78,28 @@ decrypt_data( void *procctx, PKT_encrypted *ed, DEK *dek )
|
||||
BUG();
|
||||
|
||||
if( ed->mdc_method ) {
|
||||
dfx.mdc_hash = gcry_md_open( ed->mdc_method, 0 );
|
||||
dfx.mdc_hash = md_open( ed->mdc_method, 0 );
|
||||
if ( DBG_HASHING )
|
||||
gcry_md_start_debug(dfx.mdc_hash, "checkmdc");
|
||||
md_start_debug(dfx.mdc_hash, "checkmdc");
|
||||
}
|
||||
if( !(dfx.cipher_hd = gcry_cipher_open( dek->algo,
|
||||
GCRY_CIPHER_MODE_CFB,
|
||||
GCRY_CIPHER_SECURE
|
||||
| ((ed->mdc_method || dek->algo >= 100)?
|
||||
0 : GCRY_CIPHER_ENABLE_SYNC) ))
|
||||
) {
|
||||
/* we should never get an error here cause we already checked, that
|
||||
* the algorithm is available. What about a flag to let the function
|
||||
* die in this case? */
|
||||
BUG();
|
||||
}
|
||||
|
||||
|
||||
dfx.cipher_hd = cipher_open( dek->algo,
|
||||
ed->mdc_method? CIPHER_MODE_CFB
|
||||
: CIPHER_MODE_AUTO_CFB, 1 );
|
||||
/* log_hexdump( "thekey", dek->key, dek->keylen );*/
|
||||
rc = gcry_cipher_setkey( dfx.cipher_hd, dek->key, dek->keylen );
|
||||
if( rc == GCRYERR_WEAK_KEY ) {
|
||||
rc = cipher_setkey( dfx.cipher_hd, dek->key, dek->keylen );
|
||||
if( rc == G10ERR_WEAK_KEY )
|
||||
log_info(_("WARNING: message was encrypted with "
|
||||
"a weak key in the symmetric cipher.\n"));
|
||||
rc = 0;
|
||||
}
|
||||
else if( rc ) {
|
||||
log_error("key setup failed: %s\n", gcry_strerror(rc) );
|
||||
log_error("key setup failed: %s\n", g10_errstr(rc) );
|
||||
goto leave;
|
||||
}
|
||||
if (!ed->buf) {
|
||||
log_error(_("problem handling encrypted packet\n"));
|
||||
goto leave;
|
||||
}
|
||||
|
||||
gcry_cipher_setiv( dfx.cipher_hd, NULL, 0 );
|
||||
cipher_setiv( dfx.cipher_hd, NULL, 0 );
|
||||
|
||||
if( ed->len ) {
|
||||
for(i=0; i < (nprefix+2) && ed->len; i++, ed->len-- ) {
|
||||
@ -122,17 +116,17 @@ decrypt_data( void *procctx, PKT_encrypted *ed, DEK *dek )
|
||||
else
|
||||
temp[i] = c;
|
||||
}
|
||||
gcry_cipher_decrypt( dfx.cipher_hd, temp, nprefix+2, NULL, 0 );
|
||||
gcry_cipher_sync( dfx.cipher_hd );
|
||||
cipher_decrypt( dfx.cipher_hd, temp, temp, nprefix+2);
|
||||
cipher_sync( dfx.cipher_hd );
|
||||
p = temp;
|
||||
/* log_hexdump( "prefix", temp, nprefix+2 ); */
|
||||
if( p[nprefix-2] != p[nprefix] || p[nprefix-1] != p[nprefix+1] ) {
|
||||
rc = GPGERR_BAD_KEY;
|
||||
rc = G10ERR_BAD_KEY;
|
||||
goto leave;
|
||||
}
|
||||
|
||||
if( dfx.mdc_hash )
|
||||
gcry_md_write( dfx.mdc_hash, temp, nprefix+2 );
|
||||
md_write( dfx.mdc_hash, temp, nprefix+2 );
|
||||
|
||||
if( ed->mdc_method )
|
||||
iobuf_push_filter( ed->buf, mdc_decode_filter, &dfx );
|
||||
@ -142,21 +136,23 @@ decrypt_data( void *procctx, PKT_encrypted *ed, DEK *dek )
|
||||
proc_packets( procctx, ed->buf );
|
||||
ed->buf = NULL;
|
||||
if( ed->mdc_method && dfx.eof_seen == 2 )
|
||||
rc = GPGERR_INVALID_PACKET;
|
||||
rc = G10ERR_INVALID_PACKET;
|
||||
else if( ed->mdc_method ) { /* check the mdc */
|
||||
int datalen = gcry_md_get_algo_dlen( ed->mdc_method );
|
||||
int datalen = md_digest_length( ed->mdc_method );
|
||||
|
||||
gcry_cipher_decrypt( dfx.cipher_hd, dfx.defer, 20, NULL, 0);
|
||||
cipher_decrypt( dfx.cipher_hd, dfx.defer, dfx.defer, 20);
|
||||
md_final( dfx.mdc_hash );
|
||||
if( datalen != 20
|
||||
|| memcmp(gcry_md_read( dfx.mdc_hash, 0 ), dfx.defer, datalen) )
|
||||
rc = GPGERR_BAD_SIGN;
|
||||
|| memcmp(md_read( dfx.mdc_hash, 0 ), dfx.defer, datalen) )
|
||||
rc = G10ERR_BAD_SIGN;
|
||||
/*log_hexdump("MDC calculated:", md_read( dfx.mdc_hash, 0), datalen);*/
|
||||
/*log_hexdump("MDC message :", dfx.defer, 20);*/
|
||||
}
|
||||
|
||||
|
||||
leave:
|
||||
gcry_cipher_close(dfx.cipher_hd);
|
||||
gcry_md_close( dfx.mdc_hash );
|
||||
cipher_close(dfx.cipher_hd);
|
||||
md_close( dfx.mdc_hash );
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -222,8 +218,8 @@ mdc_decode_filter( void *opaque, int control, IOBUF a,
|
||||
}
|
||||
|
||||
if( n ) {
|
||||
gcry_cipher_decrypt( dfx->cipher_hd, buf, n, NULL, 0);
|
||||
gcry_md_write( dfx->mdc_hash, buf, n );
|
||||
cipher_decrypt( dfx->cipher_hd, buf, buf, n);
|
||||
md_write( dfx->mdc_hash, buf, n );
|
||||
}
|
||||
else {
|
||||
assert( dfx->eof_seen );
|
||||
@ -249,7 +245,7 @@ decode_filter( void *opaque, int control, IOBUF a, byte *buf, size_t *ret_len)
|
||||
n = iobuf_read( a, buf, size );
|
||||
if( n == -1 ) n = 0;
|
||||
if( n )
|
||||
gcry_cipher_decrypt( fc->cipher_hd, buf, n, NULL, 0 );
|
||||
cipher_decrypt( fc->cipher_hd, buf, buf, n);
|
||||
else
|
||||
rc = -1; /* eof */
|
||||
*ret_len = n;
|
||||
|
579
g10/exec.c
Normal file
579
g10/exec.c
Normal file
@ -0,0 +1,579 @@
|
||||
/* exec.c - generic call-a-program code
|
||||
* Copyright (C) 2001, 2002 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
* GnuPG is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GnuPG is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#ifndef EXEC_TEMPFILE_ONLY
|
||||
#include <sys/wait.h>
|
||||
#endif
|
||||
#ifdef HAVE_DOSISH_SYSTEM
|
||||
#include <windows.h>
|
||||
#endif
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include "options.h"
|
||||
#include "memory.h"
|
||||
#include "i18n.h"
|
||||
#include "iobuf.h"
|
||||
#include "util.h"
|
||||
#include "exec.h"
|
||||
|
||||
#ifdef NO_EXEC
|
||||
int exec_write(struct exec_info **info,const char *program,
|
||||
const char *args_in,const char *name,int writeonly,int binary)
|
||||
{
|
||||
log_error(_("no remote program execution supported\n"));
|
||||
return G10ERR_GENERAL;
|
||||
}
|
||||
|
||||
int exec_read(struct exec_info *info) { return G10ERR_GENERAL; }
|
||||
int exec_finish(struct exec_info *info) { return G10ERR_GENERAL; }
|
||||
|
||||
#else /* ! NO_EXEC */
|
||||
|
||||
#ifndef HAVE_MKDTEMP
|
||||
char *mkdtemp(char *template);
|
||||
#endif
|
||||
|
||||
#if defined (__MINGW32__) || defined (__CYGWIN32__)
|
||||
/* This is a nicer system() for windows that waits for programs to
|
||||
return before returning control to the caller. I hate helpful
|
||||
computers. */
|
||||
static int win_system(const char *command)
|
||||
{
|
||||
PROCESS_INFORMATION pi;
|
||||
STARTUPINFO si;
|
||||
char *string;
|
||||
|
||||
/* We must use a copy of the command as CreateProcess modifies this
|
||||
argument. */
|
||||
string=m_strdup(command);
|
||||
|
||||
memset(&pi,0,sizeof(pi));
|
||||
memset(&si,0,sizeof(si));
|
||||
si.cb=sizeof(si);
|
||||
|
||||
if(!CreateProcess(NULL,string,NULL,NULL,FALSE,0,NULL,NULL,&si,&pi))
|
||||
return -1;
|
||||
|
||||
/* Wait for the child to exit */
|
||||
WaitForSingleObject(pi.hProcess,INFINITE);
|
||||
|
||||
CloseHandle(pi.hProcess);
|
||||
CloseHandle(pi.hThread);
|
||||
m_free(string);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Makes a temp directory and filenames */
|
||||
static int make_tempdir(struct exec_info *info)
|
||||
{
|
||||
char *tmp=opt.temp_dir,*namein=info->name,*nameout;
|
||||
|
||||
if(!namein)
|
||||
namein=info->binary?"tempin" EXTSEP_S "bin":"tempin" EXTSEP_S "txt";
|
||||
|
||||
nameout=info->binary?"tempout" EXTSEP_S "bin":"tempout" EXTSEP_S "txt";
|
||||
|
||||
/* Make up the temp dir and files in case we need them */
|
||||
|
||||
if(tmp==NULL)
|
||||
{
|
||||
#if defined (__MINGW32__) || defined (__CYGWIN32__)
|
||||
tmp=m_alloc(256);
|
||||
if(GetTempPath(256,tmp)==0)
|
||||
strcpy(tmp,"c:\\windows\\temp");
|
||||
else
|
||||
{
|
||||
int len=strlen(tmp);
|
||||
|
||||
/* GetTempPath may return with \ on the end */
|
||||
while(len>0 && tmp[len-1]=='\\')
|
||||
{
|
||||
tmp[len-1]='\0';
|
||||
len--;
|
||||
}
|
||||
}
|
||||
#else /* More unixish systems */
|
||||
tmp=getenv("TMPDIR");
|
||||
if(tmp==NULL)
|
||||
{
|
||||
tmp=getenv("TMP");
|
||||
if(tmp==NULL)
|
||||
{
|
||||
#ifdef __riscos__
|
||||
tmp="<Wimp$ScrapDir>.GnuPG";
|
||||
mkdir(tmp,0700); /* Error checks occur later on */
|
||||
#else
|
||||
tmp="/tmp";
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
info->tempdir=m_alloc(strlen(tmp)+strlen(DIRSEP_S)+10+1);
|
||||
|
||||
sprintf(info->tempdir,"%s" DIRSEP_S "gpg-XXXXXX",tmp);
|
||||
|
||||
#if defined (__MINGW32__) || defined (__CYGWIN32__)
|
||||
m_free(tmp);
|
||||
#endif
|
||||
|
||||
if(mkdtemp(info->tempdir)==NULL)
|
||||
log_error(_("%s: can't create directory: %s\n"),
|
||||
info->tempdir,strerror(errno));
|
||||
else
|
||||
{
|
||||
info->madedir=1;
|
||||
|
||||
info->tempfile_in=m_alloc(strlen(info->tempdir)+
|
||||
strlen(DIRSEP_S)+strlen(namein)+1);
|
||||
sprintf(info->tempfile_in,"%s" DIRSEP_S "%s",info->tempdir,namein);
|
||||
|
||||
if(!info->writeonly)
|
||||
{
|
||||
info->tempfile_out=m_alloc(strlen(info->tempdir)+
|
||||
strlen(DIRSEP_S)+strlen(nameout)+1);
|
||||
sprintf(info->tempfile_out,"%s" DIRSEP_S "%s",info->tempdir,nameout);
|
||||
}
|
||||
}
|
||||
|
||||
return info->madedir?0:G10ERR_GENERAL;
|
||||
}
|
||||
|
||||
/* Expands %i and %o in the args to the full temp files within the
|
||||
temp directory. */
|
||||
static int expand_args(struct exec_info *info,const char *args_in)
|
||||
{
|
||||
const char *ch=args_in;
|
||||
int size,len;
|
||||
|
||||
info->use_temp_files=0;
|
||||
info->keep_temp_files=0;
|
||||
|
||||
if(DBG_EXTPROG)
|
||||
log_debug("expanding string \"%s\"\n",args_in);
|
||||
|
||||
size=100;
|
||||
info->command=m_alloc(size);
|
||||
len=0;
|
||||
info->command[0]='\0';
|
||||
|
||||
while(*ch!='\0')
|
||||
{
|
||||
if(*ch=='%')
|
||||
{
|
||||
char *append=NULL;
|
||||
|
||||
ch++;
|
||||
|
||||
switch(*ch)
|
||||
{
|
||||
case 'O':
|
||||
info->keep_temp_files=1;
|
||||
/* fall through */
|
||||
|
||||
case 'o': /* out */
|
||||
if(!info->madedir)
|
||||
{
|
||||
if(make_tempdir(info))
|
||||
goto fail;
|
||||
}
|
||||
append=info->tempfile_out;
|
||||
info->use_temp_files=1;
|
||||
break;
|
||||
|
||||
case 'I':
|
||||
info->keep_temp_files=1;
|
||||
/* fall through */
|
||||
|
||||
case 'i': /* in */
|
||||
if(!info->madedir)
|
||||
{
|
||||
if(make_tempdir(info))
|
||||
goto fail;
|
||||
}
|
||||
append=info->tempfile_in;
|
||||
info->use_temp_files=1;
|
||||
break;
|
||||
|
||||
case '%':
|
||||
append="%";
|
||||
break;
|
||||
}
|
||||
|
||||
if(append)
|
||||
{
|
||||
while(strlen(append)+len>size-1)
|
||||
{
|
||||
size+=100;
|
||||
info->command=m_realloc(info->command,size);
|
||||
}
|
||||
|
||||
strcat(info->command,append);
|
||||
len+=strlen(append);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(len==size-1) /* leave room for the \0 */
|
||||
{
|
||||
size+=100;
|
||||
info->command=m_realloc(info->command,size);
|
||||
}
|
||||
|
||||
info->command[len++]=*ch;
|
||||
info->command[len]='\0';
|
||||
}
|
||||
|
||||
ch++;
|
||||
}
|
||||
|
||||
if(DBG_EXTPROG)
|
||||
log_debug("args expanded to \"%s\", use %d, keep %d\n",
|
||||
info->command,info->use_temp_files,info->keep_temp_files);
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
|
||||
m_free(info->command);
|
||||
info->command=NULL;
|
||||
|
||||
return G10ERR_GENERAL;
|
||||
}
|
||||
|
||||
/* Either handles the tempfile creation, or the fork/exec. If it
|
||||
returns ok, then info->tochild is a FILE * that can be written to.
|
||||
The rules are: if there are no args, then it's a fork/exec/pipe.
|
||||
If there are args, but no tempfiles, then it's a fork/exec/pipe via
|
||||
shell -c. If there are tempfiles, then it's a system. */
|
||||
|
||||
int exec_write(struct exec_info **info,const char *program,
|
||||
const char *args_in,const char *name,int writeonly,int binary)
|
||||
{
|
||||
int ret=G10ERR_GENERAL;
|
||||
|
||||
if(opt.exec_disable && !opt.no_perm_warn)
|
||||
{
|
||||
log_info(_("external program calls are disabled due to unsafe "
|
||||
"options file permissions\n"));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if defined(HAVE_GETUID) && defined(HAVE_GETEUID)
|
||||
/* There should be no way to get to this spot while still carrying
|
||||
setuid privs. Just in case, bomb out if we are. */
|
||||
if(getuid()!=geteuid())
|
||||
BUG();
|
||||
#endif
|
||||
|
||||
if(program==NULL && args_in==NULL)
|
||||
BUG();
|
||||
|
||||
*info=m_alloc_clear(sizeof(struct exec_info));
|
||||
|
||||
if(name)
|
||||
(*info)->name=m_strdup(name);
|
||||
(*info)->binary=binary;
|
||||
(*info)->writeonly=writeonly;
|
||||
|
||||
/* Expand the args, if any */
|
||||
if(args_in && expand_args(*info,args_in))
|
||||
goto fail;
|
||||
|
||||
#ifdef EXEC_TEMPFILE_ONLY
|
||||
if(!(*info)->use_temp_files)
|
||||
{
|
||||
log_error(_("this platform requires temp files when calling external "
|
||||
"programs\n"));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
#else /* !EXEC_TEMPFILE_ONLY */
|
||||
|
||||
/* If there are no args, or there are args, but no temp files, we
|
||||
can use fork/exec/pipe */
|
||||
if(args_in==NULL || (*info)->use_temp_files==0)
|
||||
{
|
||||
int to[2],from[2];
|
||||
|
||||
if(pipe(to)==-1)
|
||||
goto fail;
|
||||
|
||||
if(pipe(from)==-1)
|
||||
{
|
||||
close(to[0]);
|
||||
close(to[1]);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if(((*info)->child=fork())==-1)
|
||||
{
|
||||
close(to[0]);
|
||||
close(to[1]);
|
||||
close(from[0]);
|
||||
close(from[1]);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if((*info)->child==0)
|
||||
{
|
||||
char *shell=getenv("SHELL");
|
||||
|
||||
if(shell==NULL)
|
||||
shell="/bin/sh";
|
||||
|
||||
/* I'm the child */
|
||||
|
||||
/* If the program isn't going to respond back, they get to
|
||||
keep their stdout/stderr */
|
||||
if(!(*info)->writeonly)
|
||||
{
|
||||
/* implied close of STDERR */
|
||||
if(dup2(STDOUT_FILENO,STDERR_FILENO)==-1)
|
||||
_exit(1);
|
||||
|
||||
/* implied close of STDOUT */
|
||||
close(from[0]);
|
||||
if(dup2(from[1],STDOUT_FILENO)==-1)
|
||||
_exit(1);
|
||||
}
|
||||
|
||||
/* implied close of STDIN */
|
||||
close(to[1]);
|
||||
if(dup2(to[0],STDIN_FILENO)==-1)
|
||||
_exit(1);
|
||||
|
||||
if(args_in==NULL)
|
||||
{
|
||||
if(DBG_EXTPROG)
|
||||
log_debug("execlp: %s\n",program);
|
||||
|
||||
execlp(program,program,NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(DBG_EXTPROG)
|
||||
log_debug("execlp: %s -c %s\n",shell,(*info)->command);
|
||||
|
||||
execlp(shell,shell,"-c",(*info)->command,NULL);
|
||||
}
|
||||
|
||||
/* If we get this far the exec failed. Clean up and return. */
|
||||
|
||||
log_error(_("unable to execute %s \"%s\": %s\n"),
|
||||
args_in==NULL?"program":"shell",
|
||||
args_in==NULL?program:shell,
|
||||
strerror(errno));
|
||||
|
||||
/* This mimics the POSIX sh behavior - 127 means "not found"
|
||||
from the shell. */
|
||||
if(errno==ENOENT)
|
||||
_exit(127);
|
||||
|
||||
_exit(1);
|
||||
}
|
||||
|
||||
/* I'm the parent */
|
||||
|
||||
close(to[0]);
|
||||
|
||||
(*info)->tochild=fdopen(to[1],binary?"wb":"w");
|
||||
if((*info)->tochild==NULL)
|
||||
{
|
||||
close(to[1]);
|
||||
ret=G10ERR_WRITE_FILE;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
close(from[1]);
|
||||
|
||||
(*info)->fromchild=iobuf_fdopen(from[0],"r");
|
||||
if((*info)->fromchild==NULL)
|
||||
{
|
||||
close(from[0]);
|
||||
ret=G10ERR_READ_FILE;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* fd iobufs are cached?! */
|
||||
iobuf_ioctl((*info)->fromchild,3,1,NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* !EXEC_TEMPFILE_ONLY */
|
||||
|
||||
if(DBG_EXTPROG)
|
||||
log_debug("using temp file \"%s\"\n",(*info)->tempfile_in);
|
||||
|
||||
/* It's not fork/exec/pipe, so create a temp file */
|
||||
(*info)->tochild=fopen((*info)->tempfile_in,binary?"wb":"w");
|
||||
if((*info)->tochild==NULL)
|
||||
{
|
||||
log_error(_("%s: can't create: %s\n"),
|
||||
(*info)->tempfile_in,strerror(errno));
|
||||
ret=G10ERR_WRITE_FILE;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ret=0;
|
||||
|
||||
fail:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int exec_read(struct exec_info *info)
|
||||
{
|
||||
int ret=G10ERR_GENERAL;
|
||||
|
||||
fclose(info->tochild);
|
||||
info->tochild=NULL;
|
||||
|
||||
if(info->use_temp_files)
|
||||
{
|
||||
if(DBG_EXTPROG)
|
||||
log_debug("system() command is %s\n",info->command);
|
||||
|
||||
#if defined (__MINGW32__) || defined (__CYGWIN32__)
|
||||
info->progreturn=win_system(info->command);
|
||||
#else
|
||||
info->progreturn=system(info->command);
|
||||
#endif
|
||||
|
||||
if(info->progreturn==-1)
|
||||
{
|
||||
log_error(_("system error while calling external program: %s\n"),
|
||||
strerror(errno));
|
||||
info->progreturn=127;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
#if defined(WIFEXITED) && defined(WEXITSTATUS)
|
||||
if(WIFEXITED(info->progreturn))
|
||||
info->progreturn=WEXITSTATUS(info->progreturn);
|
||||
else
|
||||
{
|
||||
log_error(_("unnatural exit of external program\n"));
|
||||
info->progreturn=127;
|
||||
goto fail;
|
||||
}
|
||||
#else
|
||||
/* If we don't have the macros, do the best we can. */
|
||||
info->progreturn = (info->progreturn & 0xff00) >> 8;
|
||||
#endif
|
||||
|
||||
/* 127 is the magic value returned from system() to indicate
|
||||
that the shell could not be executed, or from /bin/sh to
|
||||
indicate that the program could not be executed. */
|
||||
|
||||
if(info->progreturn==127)
|
||||
{
|
||||
log_error(_("unable to execute external program\n"));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if(!info->writeonly)
|
||||
{
|
||||
info->fromchild=iobuf_open(info->tempfile_out);
|
||||
if(info->fromchild==NULL)
|
||||
{
|
||||
log_error(_("unable to read external program response: %s\n"),
|
||||
strerror(errno));
|
||||
ret=G10ERR_READ_FILE;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Do not cache this iobuf on close */
|
||||
iobuf_ioctl(info->fromchild,3,1,NULL);
|
||||
}
|
||||
}
|
||||
|
||||
ret=0;
|
||||
|
||||
fail:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int exec_finish(struct exec_info *info)
|
||||
{
|
||||
int ret=info->progreturn;
|
||||
|
||||
if(info->fromchild)
|
||||
iobuf_close(info->fromchild);
|
||||
|
||||
if(info->tochild)
|
||||
fclose(info->tochild);
|
||||
|
||||
#ifndef EXEC_TEMPFILE_ONLY
|
||||
if(info->child>0)
|
||||
{
|
||||
if(waitpid(info->child,&info->progreturn,0)!=0 &&
|
||||
WIFEXITED(info->progreturn))
|
||||
ret=WEXITSTATUS(info->progreturn);
|
||||
else
|
||||
{
|
||||
log_error(_("unnatural exit of external program\n"));
|
||||
ret=127;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if(info->madedir && !info->keep_temp_files)
|
||||
{
|
||||
if(info->tempfile_in)
|
||||
{
|
||||
if(unlink(info->tempfile_in)==-1)
|
||||
log_info(_("Warning: unable to remove tempfile (%s) \"%s\": %s\n"),
|
||||
"in",info->tempfile_in,strerror(errno));
|
||||
}
|
||||
|
||||
if(info->tempfile_out)
|
||||
{
|
||||
if(unlink(info->tempfile_out)==-1)
|
||||
log_info(_("Warning: unable to remove tempfile (%s) \"%s\": %s\n"),
|
||||
"out",info->tempfile_out,strerror(errno));
|
||||
}
|
||||
|
||||
if(rmdir(info->tempdir)==-1)
|
||||
log_info(_("Warning: unable to remove temp directory \"%s\": %s\n"),
|
||||
info->tempdir,strerror(errno));
|
||||
}
|
||||
|
||||
m_free(info->command);
|
||||
m_free(info->name);
|
||||
m_free(info->tempdir);
|
||||
m_free(info->tempfile_in);
|
||||
m_free(info->tempfile_out);
|
||||
m_free(info);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif /* ! NO_EXEC */
|
22
g10/exec.h
Normal file
22
g10/exec.h
Normal file
@ -0,0 +1,22 @@
|
||||
#ifndef _EXEC_H_
|
||||
#define _EXEC_H_
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include "iobuf.h"
|
||||
|
||||
struct exec_info
|
||||
{
|
||||
int progreturn,binary,writeonly,madedir,use_temp_files,keep_temp_files;
|
||||
pid_t child;
|
||||
FILE *tochild;
|
||||
IOBUF fromchild;
|
||||
char *command,*name,*tempdir,*tempfile_in,*tempfile_out;
|
||||
};
|
||||
|
||||
int exec_write(struct exec_info **info,const char *program,
|
||||
const char *args_in,const char *name,int writeonly,int binary);
|
||||
int exec_read(struct exec_info *info);
|
||||
int exec_finish(struct exec_info *info);
|
||||
|
||||
#endif /* !_EXEC_H_ */
|
168
g10/export.c
168
g10/export.c
@ -1,5 +1,5 @@
|
||||
/* export.c
|
||||
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
|
||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
@ -25,11 +25,11 @@
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <gcrypt.h>
|
||||
#include "options.h"
|
||||
#include "packet.h"
|
||||
#include "errors.h"
|
||||
#include "keydb.h"
|
||||
#include "memory.h"
|
||||
#include "util.h"
|
||||
#include "main.h"
|
||||
#include "i18n.h"
|
||||
@ -83,8 +83,10 @@ do_export( STRLIST users, int secret, int onlyrfc )
|
||||
IOBUF out = NULL;
|
||||
int any, rc;
|
||||
armor_filter_context_t afx;
|
||||
compress_filter_context_t zfx;
|
||||
|
||||
memset( &afx, 0, sizeof afx);
|
||||
memset( &zfx, 0, sizeof zfx);
|
||||
|
||||
rc = open_outfile( NULL, 0, &out );
|
||||
if( rc )
|
||||
@ -94,6 +96,8 @@ do_export( STRLIST users, int secret, int onlyrfc )
|
||||
afx.what = secret?5:1;
|
||||
iobuf_push_filter( out, armor_filter, &afx );
|
||||
}
|
||||
if( opt.compress_keys && opt.compress )
|
||||
iobuf_push_filter( out, compress_filter, &zfx );
|
||||
rc = do_export_stream( out, users, secret, onlyrfc, &any );
|
||||
|
||||
if( rc || !any )
|
||||
@ -108,54 +112,58 @@ static int
|
||||
do_export_stream( IOBUF out, STRLIST users, int secret, int onlyrfc, int *any )
|
||||
{
|
||||
int rc = 0;
|
||||
compress_filter_context_t zfx;
|
||||
PACKET pkt;
|
||||
KBNODE keyblock = NULL;
|
||||
KBNODE kbctx, node;
|
||||
KBPOS kbpos;
|
||||
int ndesc;
|
||||
KEYDB_SEARCH_DESC *desc = NULL;
|
||||
KEYDB_HANDLE kdbhd;
|
||||
STRLIST sl;
|
||||
int all = !users;
|
||||
|
||||
*any = 0;
|
||||
memset( &zfx, 0, sizeof zfx);
|
||||
init_packet( &pkt );
|
||||
kdbhd = keydb_new (secret);
|
||||
|
||||
if( opt.compress_keys && opt.compress )
|
||||
iobuf_push_filter( out, compress_filter, &zfx );
|
||||
if (!users) {
|
||||
ndesc = 1;
|
||||
desc = m_alloc_clear ( ndesc * sizeof *desc);
|
||||
desc[0].mode = KEYDB_SEARCH_MODE_FIRST;
|
||||
}
|
||||
else {
|
||||
for (ndesc=0, sl=users; sl; sl = sl->next, ndesc++)
|
||||
;
|
||||
desc = m_alloc ( ndesc * sizeof *desc);
|
||||
|
||||
for (ndesc=0, sl=users; sl; sl = sl->next) {
|
||||
if (classify_user_id (sl->d, desc+ndesc))
|
||||
ndesc++;
|
||||
else
|
||||
log_error (_("key `%s' not found: %s\n"),
|
||||
sl->d, g10_errstr (G10ERR_INV_USER_ID));
|
||||
}
|
||||
|
||||
if( all ) {
|
||||
rc = enum_keyblocks_begin( &kbpos, secret );
|
||||
if( rc ) {
|
||||
if( rc != -1 )
|
||||
log_error("enum_keyblocks_begin failed: %s\n", gpg_errstr(rc));
|
||||
goto leave;
|
||||
}
|
||||
all = 2;
|
||||
/* it would be nice to see which of the given users did
|
||||
actually match one in the keyring. To implement this we
|
||||
need to have a found flag for each entry in desc and to set
|
||||
this we must check all those entries after a match to mark
|
||||
all matched one - currently we stop at the first match. To
|
||||
do this we need an extra flag to enable this feature so */
|
||||
}
|
||||
|
||||
/* use the correct sequence. strlist_last,prev do work correctly with
|
||||
* NULL pointers :-) */
|
||||
for( sl=strlist_last(users); sl || all ; sl=strlist_prev( users, sl )) {
|
||||
if( all ) { /* get the next user */
|
||||
rc = enum_keyblocks_next( kbpos, 1, &keyblock );
|
||||
if( rc == -1 ) /* EOF */
|
||||
break;
|
||||
if( rc ) {
|
||||
log_error("enum_keyblocks_next failed: %s\n", gpg_errstr(rc));
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* search the userid */
|
||||
rc = secret? find_secret_keyblock_byname( &keyblock, sl->d )
|
||||
: find_keyblock_byname( &keyblock, sl->d );
|
||||
if( rc ) {
|
||||
log_error(_("%s: user not found: %s\n"), sl->d, gpg_errstr(rc));
|
||||
rc = 0;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
while (!(rc = keydb_search (kdbhd, desc, ndesc))) {
|
||||
int sha1_warned=0;
|
||||
u32 sk_keyid[2];
|
||||
|
||||
if (!users)
|
||||
desc[0].mode = KEYDB_SEARCH_MODE_NEXT;
|
||||
|
||||
/* read the keyblock */
|
||||
rc = keydb_get_keyblock (kdbhd, &keyblock );
|
||||
if( rc ) {
|
||||
log_error (_("error reading keyblock: %s\n"), g10_errstr(rc) );
|
||||
goto leave;
|
||||
}
|
||||
|
||||
/* do not export keys which are incompatible with rfc2440 */
|
||||
if( onlyrfc && (node = find_kbnode( keyblock, PKT_PUBLIC_KEY )) ) {
|
||||
@ -167,15 +175,29 @@ do_export_stream( IOBUF out, STRLIST users, int secret, int onlyrfc, int *any )
|
||||
}
|
||||
}
|
||||
|
||||
/* we can't apply GNU mode 1001 on an unprotected key */
|
||||
if( secret == 2
|
||||
&& (node = find_kbnode( keyblock, PKT_SECRET_KEY ))
|
||||
&& !node->pkt->pkt.secret_key->is_protected )
|
||||
{
|
||||
log_info(_("key %08lX: not protected - skipped\n"),
|
||||
(ulong)keyid_from_sk( node->pkt->pkt.secret_key, NULL) );
|
||||
continue;
|
||||
}
|
||||
node=find_kbnode( keyblock, PKT_SECRET_KEY );
|
||||
if(node)
|
||||
{
|
||||
PKT_secret_key *sk=node->pkt->pkt.secret_key;
|
||||
|
||||
keyid_from_sk(sk,sk_keyid);
|
||||
|
||||
/* we can't apply GNU mode 1001 on an unprotected key */
|
||||
if( secret == 2 && !sk->is_protected )
|
||||
{
|
||||
log_info(_("key %08lX: not protected - skipped\n"),
|
||||
(ulong)sk_keyid[1]);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* no v3 keys with GNU mode 1001 */
|
||||
if( secret == 2 && sk->version == 3 )
|
||||
{
|
||||
log_info(_("key %08lX: PGP 2.x style key - skipped\n"),
|
||||
(ulong)sk_keyid[1]);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* and write it */
|
||||
for( kbctx=NULL; (node = walk_kbnode( keyblock, &kbctx, 0 )); ) {
|
||||
@ -183,13 +205,30 @@ do_export_stream( IOBUF out, STRLIST users, int secret, int onlyrfc, int *any )
|
||||
* secret keyring */
|
||||
if( !secret && node->pkt->pkttype == PKT_COMMENT )
|
||||
continue;
|
||||
/* do not export packets which are marked as not exportable */
|
||||
/* make sure that ring_trust packets never get exported */
|
||||
if (node->pkt->pkttype == PKT_RING_TRUST)
|
||||
continue;
|
||||
|
||||
if( node->pkt->pkttype == PKT_SIGNATURE ) {
|
||||
const char *p;
|
||||
p = parse_sig_subpkt2( node->pkt->pkt.signature,
|
||||
SIGSUBPKT_EXPORTABLE, NULL );
|
||||
if( p && !*p )
|
||||
continue; /* not exportable */
|
||||
/* do not export packets which are marked as not exportable */
|
||||
if( !node->pkt->pkt.signature->flags.exportable )
|
||||
continue; /* not exportable */
|
||||
|
||||
/* do not export packets with a "sensitive" revocation
|
||||
key. This will need revisiting when we start
|
||||
supporting creating revocation keys and not just
|
||||
reading them. */
|
||||
if( node->pkt->pkt.signature->revkey ) {
|
||||
int i;
|
||||
|
||||
for(i=0;i<node->pkt->pkt.signature->numrevkeys;i++)
|
||||
if(node->pkt->pkt.signature->revkey[i]->class & 0x40)
|
||||
continue;
|
||||
}
|
||||
|
||||
/* delete our verification cache */
|
||||
delete_sig_subpkt (node->pkt->pkt.signature->unhashed,
|
||||
SIGSUBPKT_PRIV_VERIFY_CACHE);
|
||||
}
|
||||
|
||||
if( secret == 2 && node->pkt->pkttype == PKT_SECRET_KEY ) {
|
||||
@ -202,13 +241,28 @@ do_export_stream( IOBUF out, STRLIST users, int secret, int onlyrfc, int *any )
|
||||
node->pkt->pkt.secret_key->protect.s2k.mode = save_mode;
|
||||
}
|
||||
else {
|
||||
/* Warn the user if the secret key or any of the secret
|
||||
subkeys are protected with SHA1 and we have
|
||||
simple_sk_checksum set. */
|
||||
if(!sha1_warned && opt.simple_sk_checksum &&
|
||||
(node->pkt->pkttype==PKT_SECRET_KEY ||
|
||||
node->pkt->pkttype==PKT_SECRET_SUBKEY) &&
|
||||
node->pkt->pkt.secret_key->protect.sha1chk)
|
||||
{
|
||||
/* I hope this warning doesn't confuse people. */
|
||||
log_info("Warning: secret key %08lX does not have a "
|
||||
"simple SK checksum\n",(ulong)sk_keyid[1]);
|
||||
|
||||
sha1_warned=1;
|
||||
}
|
||||
|
||||
rc = build_packet( out, node->pkt );
|
||||
}
|
||||
|
||||
if( rc ) {
|
||||
log_error("build_packet(%d) failed: %s\n",
|
||||
node->pkt->pkttype, gpg_errstr(rc) );
|
||||
rc = GPGERR_WRITE_FILE;
|
||||
node->pkt->pkttype, g10_errstr(rc) );
|
||||
rc = G10ERR_WRITE_FILE;
|
||||
goto leave;
|
||||
}
|
||||
}
|
||||
@ -218,8 +272,8 @@ do_export_stream( IOBUF out, STRLIST users, int secret, int onlyrfc, int *any )
|
||||
rc = 0;
|
||||
|
||||
leave:
|
||||
if( all == 2 )
|
||||
enum_keyblocks_end( kbpos );
|
||||
m_free(desc);
|
||||
keydb_release (kdbhd);
|
||||
release_kbnode( keyblock );
|
||||
if( !*any )
|
||||
log_info(_("WARNING: nothing exported\n"));
|
||||
|
47
g10/filter.h
47
g10/filter.h
@ -1,5 +1,5 @@
|
||||
/* filter.h
|
||||
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
|
||||
* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
@ -17,18 +17,15 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifndef GPG_FILTER_H
|
||||
#define GPG_FILTER_H
|
||||
|
||||
#include <gcrypt.h>
|
||||
|
||||
#include "basicdefs.h"
|
||||
#include "iobuf.h"
|
||||
#ifndef G10_FILTER_H
|
||||
#define G10_FILTER_H
|
||||
|
||||
#include "types.h"
|
||||
#include "cipher.h"
|
||||
|
||||
typedef struct {
|
||||
GCRY_MD_HD md; /* catch all */
|
||||
GCRY_MD_HD md2; /* if we want to calculate an alternate hash */
|
||||
MD_HANDLE md; /* catch all */
|
||||
MD_HANDLE md2; /* if we want to calculate an alternate hash */
|
||||
size_t maxbuf_size;
|
||||
} md_filter_context_t;
|
||||
|
||||
@ -67,8 +64,11 @@ typedef struct {
|
||||
int pending_lf; /* used together with faked */
|
||||
} armor_filter_context_t;
|
||||
|
||||
struct unarmor_pump_s;
|
||||
typedef struct unarmor_pump_s *UnarmorPump;
|
||||
|
||||
typedef struct {
|
||||
|
||||
struct compress_filter_context_s {
|
||||
int status;
|
||||
void *opaque; /* (used for z_stream) */
|
||||
byte *inbuf;
|
||||
@ -77,26 +77,22 @@ typedef struct {
|
||||
unsigned outbufsize;
|
||||
int algo; /* compress algo */
|
||||
int algo1hack;
|
||||
} compress_filter_context_t;
|
||||
void (*release)(struct compress_filter_context_s*);
|
||||
};
|
||||
typedef struct compress_filter_context_s compress_filter_context_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
DEK *dek;
|
||||
u32 datalen;
|
||||
GCRY_CIPHER_HD cipher_hd;
|
||||
CIPHER_HANDLE cipher_hd;
|
||||
int header;
|
||||
GCRY_MD_HD mdc_hash;
|
||||
MD_HANDLE mdc_hash;
|
||||
byte enchash[20];
|
||||
int create_mdc; /* flag will be set by the cipher filter */
|
||||
} cipher_filter_context_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
int header_okay;
|
||||
PK_LIST pk_list;
|
||||
cipher_filter_context_t cfx;
|
||||
} encrypt_filter_context_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
byte *buffer; /* malloced buffer */
|
||||
@ -106,12 +102,14 @@ typedef struct {
|
||||
int truncated; /* number of truncated lines */
|
||||
int not_dash_escaped;
|
||||
int escape_from;
|
||||
GCRY_MD_HD md;
|
||||
MD_HANDLE md;
|
||||
int pending_lf;
|
||||
int pending_esc;
|
||||
} text_filter_context_t;
|
||||
|
||||
|
||||
/* encrypt_filter_context_t defined in main.h */
|
||||
|
||||
/*-- mdfilter.c --*/
|
||||
int md_filter( void *opaque, int control, IOBUF a, byte *buf, size_t *ret_len);
|
||||
void free_md_filter_context( md_filter_context_t *mfx );
|
||||
@ -120,6 +118,9 @@ void free_md_filter_context( md_filter_context_t *mfx );
|
||||
int use_armor_filter( IOBUF a );
|
||||
int armor_filter( void *opaque, int control,
|
||||
IOBUF chain, byte *buf, size_t *ret_len);
|
||||
UnarmorPump unarmor_pump_new (void);
|
||||
void unarmor_pump_release (UnarmorPump x);
|
||||
int unarmor_pump (UnarmorPump x, int c);
|
||||
|
||||
/*-- compress.c --*/
|
||||
int compress_filter( void *opaque, int control,
|
||||
@ -132,9 +133,9 @@ int cipher_filter( void *opaque, int control,
|
||||
/*-- textfilter.c --*/
|
||||
int text_filter( void *opaque, int control,
|
||||
IOBUF chain, byte *buf, size_t *ret_len);
|
||||
int copy_clearsig_text( IOBUF out, IOBUF inp, GCRY_MD_HD md,
|
||||
int copy_clearsig_text( IOBUF out, IOBUF inp, MD_HANDLE md,
|
||||
int escape_dash, int escape_from, int pgp2mode );
|
||||
|
||||
|
||||
|
||||
#endif /*GPG_FILTER_H*/
|
||||
#endif /*G10_FILTER_H*/
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* free-packet.c - cleanup stuff for packets
|
||||
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
|
||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
@ -24,17 +24,18 @@
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <gcrypt.h>
|
||||
#include "packet.h"
|
||||
#include "iobuf.h"
|
||||
#include "mpi.h"
|
||||
#include "util.h"
|
||||
#include "cipher.h"
|
||||
#include "memory.h"
|
||||
#include "options.h"
|
||||
#include "main.h"
|
||||
|
||||
void
|
||||
free_symkey_enc( PKT_symkey_enc *enc )
|
||||
{
|
||||
gcry_free(enc);
|
||||
m_free(enc);
|
||||
}
|
||||
|
||||
void
|
||||
@ -43,24 +44,27 @@ free_pubkey_enc( PKT_pubkey_enc *enc )
|
||||
int n, i;
|
||||
n = pubkey_get_nenc( enc->pubkey_algo );
|
||||
if( !n )
|
||||
mpi_release(enc->data[0]);
|
||||
mpi_free(enc->data[0]);
|
||||
for(i=0; i < n; i++ )
|
||||
mpi_release( enc->data[i] );
|
||||
gcry_free(enc);
|
||||
mpi_free( enc->data[i] );
|
||||
m_free(enc);
|
||||
}
|
||||
|
||||
void
|
||||
free_seckey_enc( PKT_signature *sig )
|
||||
{
|
||||
int n, i;
|
||||
n = pubkey_get_nsig( sig->pubkey_algo );
|
||||
if( !n )
|
||||
mpi_release(sig->data[0]);
|
||||
for(i=0; i < n; i++ )
|
||||
mpi_release( sig->data[i] );
|
||||
gcry_free(sig->hashed_data);
|
||||
gcry_free(sig->unhashed_data);
|
||||
gcry_free(sig);
|
||||
int n, i;
|
||||
|
||||
n = pubkey_get_nsig( sig->pubkey_algo );
|
||||
if( !n )
|
||||
mpi_free(sig->data[0]);
|
||||
for(i=0; i < n; i++ )
|
||||
mpi_free( sig->data[i] );
|
||||
|
||||
m_free(sig->revkey);
|
||||
m_free(sig->hashed);
|
||||
m_free(sig->unhashed);
|
||||
m_free(sig);
|
||||
}
|
||||
|
||||
|
||||
@ -71,15 +75,28 @@ release_public_key_parts( PKT_public_key *pk )
|
||||
int n, i;
|
||||
n = pubkey_get_npkey( pk->pubkey_algo );
|
||||
if( !n )
|
||||
mpi_release(pk->pkey[0]);
|
||||
mpi_free(pk->pkey[0]);
|
||||
for(i=0; i < n; i++ ) {
|
||||
mpi_release( pk->pkey[i] );
|
||||
mpi_free( pk->pkey[i] );
|
||||
pk->pkey[i] = NULL;
|
||||
}
|
||||
if (pk->prefs) {
|
||||
m_free (pk->prefs);
|
||||
pk->prefs = NULL;
|
||||
}
|
||||
if( pk->namehash ) {
|
||||
gcry_free(pk->namehash);
|
||||
m_free(pk->namehash);
|
||||
pk->namehash = NULL;
|
||||
}
|
||||
if (pk->user_id) {
|
||||
free_user_id (pk->user_id);
|
||||
pk->user_id = NULL;
|
||||
}
|
||||
if (pk->revkey) {
|
||||
m_free(pk->revkey);
|
||||
pk->revkey=NULL;
|
||||
pk->numrevkeys=0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -87,42 +104,60 @@ void
|
||||
free_public_key( PKT_public_key *pk )
|
||||
{
|
||||
release_public_key_parts( pk );
|
||||
gcry_free(pk);
|
||||
m_free(pk);
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
cp_data_block( byte *s )
|
||||
static subpktarea_t *
|
||||
cp_subpktarea (subpktarea_t *s )
|
||||
{
|
||||
byte *d;
|
||||
u16 len;
|
||||
subpktarea_t *d;
|
||||
|
||||
if( !s )
|
||||
return NULL;
|
||||
len = (s[0] << 8) | s[1];
|
||||
d = gcry_xmalloc( len+2 );
|
||||
memcpy(d, s, len+2);
|
||||
d = m_alloc (sizeof (*d) + s->size - 1 );
|
||||
d->size = s->size;
|
||||
d->len = s->len;
|
||||
memcpy (d->data, s->data, s->len);
|
||||
return d;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return a copy of the preferences
|
||||
*/
|
||||
prefitem_t *
|
||||
copy_prefs (const prefitem_t *prefs)
|
||||
{
|
||||
size_t n;
|
||||
prefitem_t *new;
|
||||
|
||||
if (!prefs)
|
||||
return NULL;
|
||||
|
||||
for (n=0; prefs[n].type; n++)
|
||||
;
|
||||
new = m_alloc ( sizeof (*new) * (n+1));
|
||||
for (n=0; prefs[n].type; n++) {
|
||||
new[n].type = prefs[n].type;
|
||||
new[n].value = prefs[n].value;
|
||||
}
|
||||
new[n].type = PREFTYPE_NONE;
|
||||
new[n].value = 0;
|
||||
|
||||
return new;
|
||||
}
|
||||
|
||||
|
||||
PKT_public_key *
|
||||
copy_public_key_new_namehash( PKT_public_key *d, PKT_public_key *s,
|
||||
const byte *namehash )
|
||||
copy_public_key ( PKT_public_key *d, PKT_public_key *s)
|
||||
{
|
||||
int n, i;
|
||||
|
||||
if( !d )
|
||||
d = gcry_xmalloc(sizeof *d);
|
||||
d = m_alloc(sizeof *d);
|
||||
memcpy( d, s, sizeof *d );
|
||||
if( namehash ) {
|
||||
d->namehash = gcry_xmalloc( 20 );
|
||||
memcpy(d->namehash, namehash, 20 );
|
||||
}
|
||||
else if( s->namehash ) {
|
||||
d->namehash = gcry_xmalloc( 20 );
|
||||
memcpy(d->namehash, s->namehash, 20 );
|
||||
}
|
||||
d->user_id = scopy_user_id (s->user_id);
|
||||
d->prefs = copy_prefs (s->prefs);
|
||||
n = pubkey_get_npkey( s->pubkey_algo );
|
||||
if( !n )
|
||||
d->pkey[0] = mpi_copy(s->pkey[0]);
|
||||
@ -130,16 +165,17 @@ copy_public_key_new_namehash( PKT_public_key *d, PKT_public_key *s,
|
||||
for(i=0; i < n; i++ )
|
||||
d->pkey[i] = mpi_copy( s->pkey[i] );
|
||||
}
|
||||
if( !s->revkey && s->numrevkeys )
|
||||
BUG();
|
||||
if( s->numrevkeys ) {
|
||||
d->revkey = m_alloc(sizeof(struct revocation_key)*s->numrevkeys);
|
||||
memcpy(d->revkey,s->revkey,sizeof(struct revocation_key)*s->numrevkeys);
|
||||
}
|
||||
else
|
||||
d->revkey = NULL;
|
||||
return d;
|
||||
}
|
||||
|
||||
PKT_public_key *
|
||||
copy_public_key( PKT_public_key *d, PKT_public_key *s )
|
||||
{
|
||||
return copy_public_key_new_namehash( d, s, NULL );
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
* Replace all common parts of a sk by the one from the public key.
|
||||
* This is a hack and a better solution will be to just store the real secret
|
||||
@ -151,7 +187,6 @@ copy_public_parts_to_secret_key( PKT_public_key *pk, PKT_secret_key *sk )
|
||||
sk->expiredate = pk->expiredate;
|
||||
sk->pubkey_algo = pk->pubkey_algo;
|
||||
sk->pubkey_usage= pk->pubkey_usage;
|
||||
sk->created = pk->created;
|
||||
sk->req_usage = pk->req_usage;
|
||||
sk->req_algo = pk->req_algo;
|
||||
sk->has_expired = pk->has_expired;
|
||||
@ -163,15 +198,13 @@ copy_public_parts_to_secret_key( PKT_public_key *pk, PKT_secret_key *sk )
|
||||
sk->keyid[1] = pk->keyid[1];
|
||||
}
|
||||
|
||||
|
||||
|
||||
PKT_signature *
|
||||
copy_signature( PKT_signature *d, PKT_signature *s )
|
||||
{
|
||||
int n, i;
|
||||
|
||||
if( !d )
|
||||
d = gcry_xmalloc(sizeof *d);
|
||||
d = m_alloc(sizeof *d);
|
||||
memcpy( d, s, sizeof *d );
|
||||
n = pubkey_get_nsig( s->pubkey_algo );
|
||||
if( !n )
|
||||
@ -180,19 +213,27 @@ copy_signature( PKT_signature *d, PKT_signature *s )
|
||||
for(i=0; i < n; i++ )
|
||||
d->data[i] = mpi_copy( s->data[i] );
|
||||
}
|
||||
d->hashed_data = cp_data_block(s->hashed_data);
|
||||
d->unhashed_data = cp_data_block(s->unhashed_data);
|
||||
d->hashed = cp_subpktarea (s->hashed);
|
||||
d->unhashed = cp_subpktarea (s->unhashed);
|
||||
if(s->numrevkeys)
|
||||
{
|
||||
d->revkey=NULL;
|
||||
d->numrevkeys=0;
|
||||
parse_revkeys(d);
|
||||
}
|
||||
return d;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* shallow copy of the user ID
|
||||
*/
|
||||
PKT_user_id *
|
||||
copy_user_id( PKT_user_id *d, PKT_user_id *s )
|
||||
scopy_user_id (PKT_user_id *s)
|
||||
{
|
||||
if( !d )
|
||||
d = gcry_xmalloc(sizeof *d + s->len - 1 );
|
||||
memcpy( d, s, sizeof *d + s->len - 1 );
|
||||
return d;
|
||||
if (s)
|
||||
s->ref++;
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
@ -204,9 +245,9 @@ release_secret_key_parts( PKT_secret_key *sk )
|
||||
|
||||
n = pubkey_get_nskey( sk->pubkey_algo );
|
||||
if( !n )
|
||||
mpi_release(sk->skey[0]);
|
||||
mpi_free(sk->skey[0]);
|
||||
for(i=0; i < n; i++ ) {
|
||||
mpi_release( sk->skey[i] );
|
||||
mpi_free( sk->skey[i] );
|
||||
sk->skey[i] = NULL;
|
||||
}
|
||||
}
|
||||
@ -215,7 +256,7 @@ void
|
||||
free_secret_key( PKT_secret_key *sk )
|
||||
{
|
||||
release_secret_key_parts( sk );
|
||||
gcry_free(sk);
|
||||
m_free(sk);
|
||||
}
|
||||
|
||||
PKT_secret_key *
|
||||
@ -224,7 +265,7 @@ copy_secret_key( PKT_secret_key *d, PKT_secret_key *s )
|
||||
int n, i;
|
||||
|
||||
if( !d )
|
||||
d = gcry_xmalloc(sizeof *d);
|
||||
d = m_alloc(sizeof *d);
|
||||
memcpy( d, s, sizeof *d );
|
||||
n = pubkey_get_nskey( s->pubkey_algo );
|
||||
if( !n )
|
||||
@ -239,15 +280,32 @@ copy_secret_key( PKT_secret_key *d, PKT_secret_key *s )
|
||||
void
|
||||
free_comment( PKT_comment *rem )
|
||||
{
|
||||
gcry_free(rem);
|
||||
m_free(rem);
|
||||
}
|
||||
|
||||
void
|
||||
free_user_id( PKT_user_id *uid )
|
||||
free_attributes(PKT_user_id *uid)
|
||||
{
|
||||
if( uid->photo )
|
||||
gcry_free( uid->photo );
|
||||
gcry_free(uid);
|
||||
m_free(uid->attribs);
|
||||
m_free(uid->attrib_data);
|
||||
|
||||
uid->attribs=NULL;
|
||||
uid->attrib_data=NULL;
|
||||
uid->attrib_len=0;
|
||||
}
|
||||
|
||||
void
|
||||
free_user_id (PKT_user_id *uid)
|
||||
{
|
||||
assert (uid->ref > 0);
|
||||
if (--uid->ref)
|
||||
return;
|
||||
|
||||
free_attributes(uid);
|
||||
|
||||
if (uid->prefs)
|
||||
m_free (uid->prefs);
|
||||
m_free (uid);
|
||||
}
|
||||
|
||||
void
|
||||
@ -259,7 +317,7 @@ free_compressed( PKT_compressed *zd )
|
||||
while( iobuf_read( zd->buf, NULL, 1<<30 ) != -1 )
|
||||
;
|
||||
}
|
||||
gcry_free(zd);
|
||||
m_free(zd);
|
||||
}
|
||||
|
||||
void
|
||||
@ -280,7 +338,7 @@ free_encrypted( PKT_encrypted *ed )
|
||||
}
|
||||
}
|
||||
}
|
||||
gcry_free(ed);
|
||||
m_free(ed);
|
||||
}
|
||||
|
||||
|
||||
@ -302,7 +360,7 @@ free_plaintext( PKT_plaintext *pt )
|
||||
}
|
||||
}
|
||||
}
|
||||
gcry_free(pt);
|
||||
m_free(pt);
|
||||
}
|
||||
|
||||
/****************
|
||||
@ -345,13 +403,14 @@ free_packet( PACKET *pkt )
|
||||
free_compressed( pkt->pkt.compressed);
|
||||
break;
|
||||
case PKT_ENCRYPTED:
|
||||
case PKT_ENCRYPTED_MDC:
|
||||
free_encrypted( pkt->pkt.encrypted );
|
||||
break;
|
||||
case PKT_PLAINTEXT:
|
||||
free_plaintext( pkt->pkt.plaintext );
|
||||
break;
|
||||
default:
|
||||
gcry_free( pkt->pkt.generic );
|
||||
m_free( pkt->pkt.generic );
|
||||
break;
|
||||
}
|
||||
pkt->pkt.generic = NULL;
|
||||
@ -460,23 +519,29 @@ cmp_signatures( PKT_signature *a, PKT_signature *b )
|
||||
}
|
||||
|
||||
|
||||
|
||||
/****************
|
||||
* Returns: true if the user ids do not match
|
||||
*/
|
||||
int
|
||||
cmp_user_ids( PKT_user_id *a, PKT_user_id *b )
|
||||
{
|
||||
int res;
|
||||
int res=1;
|
||||
|
||||
if( a == b )
|
||||
return 0;
|
||||
|
||||
if( a->attrib_data && b->attrib_data )
|
||||
{
|
||||
res = a->attrib_len - b->attrib_len;
|
||||
if( !res )
|
||||
res = memcmp( a->attrib_data, b->attrib_data, a->attrib_len );
|
||||
}
|
||||
else if( !a->attrib_data && !b->attrib_data )
|
||||
{
|
||||
res = a->len - b->len;
|
||||
if( !res )
|
||||
res = memcmp( a->name, b->name, a->len );
|
||||
}
|
||||
|
||||
res = a->len - b->len;
|
||||
if( !res )
|
||||
res = memcmp( a->name, b->name, a->len );
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
1871
g10/getkey.c
1871
g10/getkey.c
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,5 @@
|
||||
/* basicdefs.h - Some definitions used at many place
|
||||
* Copyright (C) 1999 Free Software Foundation, Inc.
|
||||
/* global.h - Local typedefs and constants
|
||||
* Copyright (C) 2001 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
@ -18,23 +18,12 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
#ifndef GPG_BASICDEFS_H
|
||||
#define GPG_BASICDEFS_H
|
||||
#ifndef GPG_GLOBAL_H
|
||||
#define GPG_GLOBAL_H
|
||||
|
||||
#include "types.h"
|
||||
#define MAX_FINGERPRINT_LEN 20
|
||||
|
||||
typedef struct {
|
||||
int algo;
|
||||
int keylen;
|
||||
byte key[32]; /* this is the largest used keylen (256 bit) */
|
||||
} DEK;
|
||||
typedef struct kbnode_struct *KBNODE;
|
||||
typedef struct keydb_search_desc KEYDB_SEARCH_DESC;
|
||||
|
||||
|
||||
struct pk_list;
|
||||
struct sk_list;
|
||||
typedef struct pk_list *PK_LIST;
|
||||
typedef struct sk_list *SK_LIST;
|
||||
|
||||
|
||||
|
||||
#endif /* GPG_BASICDEFS_H */
|
||||
#endif /*GPG_GLOBAL_H*/
|
24
g10/gpgd.c
24
g10/gpgd.c
@ -1,5 +1,5 @@
|
||||
/* ggpd.c - The GnuPG daemon (keyserver)
|
||||
* Copyright (C) 1998 Free Software Foundation, Inc.
|
||||
/* gpd.c - The GnuPG daemon (keyserver)
|
||||
* Copyright (C) 1998, 1999 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
@ -112,7 +112,7 @@ build_list( const char *text, const char * (*mapf)(int), int (*chkf)(int) )
|
||||
for(i=1; i < 100; i++ )
|
||||
if( !chkf(i) && (s=mapf(i)) )
|
||||
n += strlen(s) + 2;
|
||||
list = gcry_xmalloc( 21 + n ); *list = 0;
|
||||
list = m_alloc( 21 + n ); *list = 0;
|
||||
for(p=NULL, i=1; i < 100; i++ ) {
|
||||
if( !chkf(i) && (s=mapf(i)) ) {
|
||||
if( !p )
|
||||
@ -201,9 +201,9 @@ main( int argc, char **argv )
|
||||
else {
|
||||
log_error("option file `%s': %s\n",
|
||||
configname, strerror(errno) );
|
||||
gpg_exit(1);
|
||||
g10_exit(1);
|
||||
}
|
||||
gcry_free(configname); configname = NULL;
|
||||
m_free(configname); configname = NULL;
|
||||
}
|
||||
if( parse_debug && configname )
|
||||
log_info("reading options from `%s'\n", configname );
|
||||
@ -216,8 +216,8 @@ main( int argc, char **argv )
|
||||
case 'v': opt.verbose++; break;
|
||||
case 501:
|
||||
if( !configfp ) {
|
||||
gcry_free(configname);
|
||||
configname = gcry_xstrdup(pargs.r.ret_str);
|
||||
m_free(configname);
|
||||
configname = m_strdup(pargs.r.ret_str);
|
||||
goto next_pass;
|
||||
}
|
||||
break;
|
||||
@ -230,12 +230,12 @@ main( int argc, char **argv )
|
||||
if( configfp ) {
|
||||
fclose( configfp );
|
||||
configfp = NULL;
|
||||
gcry_free(configname); configname = NULL;
|
||||
m_free(configname); configname = NULL;
|
||||
goto next_pass;
|
||||
}
|
||||
gcry_free( configname ); configname = NULL;
|
||||
m_free( configname ); configname = NULL;
|
||||
if( log_get_errorcount(0) )
|
||||
gpg_exit(2);
|
||||
g10_exit(2);
|
||||
|
||||
fprintf(stderr, "%s %s; %s\n", strusage(11), strusage(13), strusage(14) );
|
||||
fprintf(stderr, "%s\n", strusage(15) );
|
||||
@ -245,13 +245,13 @@ main( int argc, char **argv )
|
||||
become_daemon();
|
||||
|
||||
|
||||
gpg_exit(0);
|
||||
g10_exit(0);
|
||||
return 8; /*NEVER REACHED*/
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
gpg_exit( int rc )
|
||||
g10_exit( int rc )
|
||||
{
|
||||
secmem_term();
|
||||
rc = rc? rc : log_get_errorcount(0)? 2:0;
|
||||
|
372
g10/gpgv.c
Normal file
372
g10/gpgv.c
Normal file
@ -0,0 +1,372 @@
|
||||
/* gpgv.c - The GnuPG signature verify utility
|
||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
* GnuPG is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GnuPG is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <unistd.h>
|
||||
#ifdef HAVE_DOSISH_SYSTEM
|
||||
#include <fcntl.h> /* for setmode() */
|
||||
#endif
|
||||
|
||||
#define INCLUDED_BY_MAIN_MODULE 1
|
||||
#include "packet.h"
|
||||
#include "iobuf.h"
|
||||
#include "memory.h"
|
||||
#include "util.h"
|
||||
#include "main.h"
|
||||
#include "options.h"
|
||||
#include "keydb.h"
|
||||
#include "trustdb.h"
|
||||
#include "mpi.h"
|
||||
#include "cipher.h"
|
||||
#include "filter.h"
|
||||
#include "ttyio.h"
|
||||
#include "i18n.h"
|
||||
#include "status.h"
|
||||
#include "g10defs.h"
|
||||
|
||||
|
||||
enum cmd_and_opt_values { aNull = 0,
|
||||
oQuiet = 'q',
|
||||
oVerbose = 'v',
|
||||
oBatch = 500,
|
||||
oKeyring,
|
||||
oIgnoreTimeConflict,
|
||||
oStatusFD,
|
||||
oLoggerFD,
|
||||
oHomedir,
|
||||
aTest };
|
||||
|
||||
|
||||
static ARGPARSE_OPTS opts[] = {
|
||||
|
||||
{ 301, NULL, 0, N_("@\nOptions:\n ") },
|
||||
|
||||
{ oVerbose, "verbose", 0, N_("verbose") },
|
||||
{ oQuiet, "quiet", 0, N_("be somewhat more quiet") },
|
||||
{ oKeyring, "keyring" ,2, N_("take the keys from this keyring")},
|
||||
{ oIgnoreTimeConflict, "ignore-time-conflict", 0,
|
||||
N_("make timestamp conflicts only a warning") },
|
||||
{ oStatusFD, "status-fd" ,1, N_("|FD|write status info to this FD") },
|
||||
{ oLoggerFD, "logger-fd",1, "@" },
|
||||
{ oHomedir, "homedir", 2, "@" }, /* defaults to "~/.gnupg" */
|
||||
|
||||
{0} };
|
||||
|
||||
|
||||
|
||||
int g10_errors_seen = 0;
|
||||
|
||||
#ifdef __riscos__
|
||||
RISCOS_GLOBAL_STATICS("GnuPG (gpgv) Heap")
|
||||
#endif /* __riscos__ */
|
||||
|
||||
const char *
|
||||
strusage( int level )
|
||||
{
|
||||
const char *p;
|
||||
switch( level ) {
|
||||
case 11: p = "gpgv (GnuPG)";
|
||||
break;
|
||||
case 13: p = VERSION; break;
|
||||
case 17: p = PRINTABLE_OS_NAME; break;
|
||||
case 19: p =
|
||||
_("Please report bugs to <gnupg-bugs@gnu.org>.\n");
|
||||
break;
|
||||
case 1:
|
||||
case 40: p =
|
||||
_("Usage: gpgv [options] [files] (-h for help)");
|
||||
break;
|
||||
case 41: p =
|
||||
_("Syntax: gpg [options] [files]\n"
|
||||
"Check signatures against known trusted keys\n");
|
||||
break;
|
||||
|
||||
default: p = default_strusage(level);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static void
|
||||
i18n_init(void)
|
||||
{
|
||||
#ifdef USE_SIMPLE_GETTEXT
|
||||
set_gettext_file( PACKAGE );
|
||||
#else
|
||||
#ifdef ENABLE_NLS
|
||||
#ifdef HAVE_LC_MESSAGES
|
||||
setlocale( LC_TIME, "" );
|
||||
setlocale( LC_MESSAGES, "" );
|
||||
#else
|
||||
setlocale( LC_ALL, "" );
|
||||
#endif
|
||||
bindtextdomain( PACKAGE, G10_LOCALEDIR );
|
||||
textdomain( PACKAGE );
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main( int argc, char **argv )
|
||||
{
|
||||
ARGPARSE_ARGS pargs;
|
||||
int rc=0;
|
||||
STRLIST sl;
|
||||
STRLIST nrings=NULL;
|
||||
unsigned configlineno;
|
||||
|
||||
#ifdef __riscos__
|
||||
riscos_global_defaults();
|
||||
#endif /* __riscos__ */
|
||||
|
||||
log_set_name("gpgv");
|
||||
init_signals();
|
||||
i18n_init();
|
||||
opt.command_fd = -1; /* no command fd */
|
||||
opt.pgp2_workarounds = 1;
|
||||
opt.keyserver_options.auto_key_retrieve = 1;
|
||||
opt.always_trust = 1;
|
||||
opt.batch = 1;
|
||||
|
||||
#if defined (__MINGW32__) || defined (__CYGWIN32__)
|
||||
opt.homedir = read_w32_registry_string( NULL, "Software\\GNU\\GnuPG", "HomeDir" );
|
||||
#else
|
||||
opt.homedir = getenv("GNUPGHOME");
|
||||
#endif
|
||||
if( !opt.homedir || !*opt.homedir ) {
|
||||
opt.homedir = GNUPG_HOMEDIR;
|
||||
}
|
||||
tty_no_terminal(1);
|
||||
tty_batchmode(1);
|
||||
disable_dotlock();
|
||||
|
||||
pargs.argc = &argc;
|
||||
pargs.argv = &argv;
|
||||
pargs.flags= 1; /* do not remove the args */
|
||||
while( optfile_parse( NULL, NULL, &configlineno, &pargs, opts) ) {
|
||||
switch( pargs.r_opt ) {
|
||||
case oQuiet: opt.quiet = 1; break;
|
||||
case oVerbose: g10_opt_verbose++;
|
||||
opt.verbose++; opt.list_sigs=1; break;
|
||||
case oKeyring: append_to_strlist( &nrings, pargs.r.ret_str); break;
|
||||
case oStatusFD: set_status_fd( pargs.r.ret_int ); break;
|
||||
case oLoggerFD: log_set_logfile( NULL, pargs.r.ret_int ); break;
|
||||
case oHomedir: opt.homedir = pargs.r.ret_str; break;
|
||||
default : pargs.err = 2; break;
|
||||
}
|
||||
}
|
||||
|
||||
if( log_get_errorcount(0) )
|
||||
g10_exit(2);
|
||||
|
||||
g10_opt_homedir = opt.homedir;
|
||||
|
||||
if( opt.verbose > 1 )
|
||||
set_packet_list_mode(1);
|
||||
|
||||
if( !nrings ) /* no keyring given: use default one */
|
||||
keydb_add_resource ("trustedkeys" EXTSEP_S "gpg", 0, 0);
|
||||
for(sl = nrings; sl; sl = sl->next )
|
||||
keydb_add_resource (sl->d, 0, 0 );
|
||||
|
||||
FREE_STRLIST(nrings);
|
||||
|
||||
if( (rc = verify_signatures( argc, argv ) ))
|
||||
log_error("verify signatures failed: %s\n", g10_errstr(rc) );
|
||||
|
||||
/* cleanup */
|
||||
g10_exit(0);
|
||||
return 8; /*NEVER REACHED*/
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
g10_exit( int rc )
|
||||
{
|
||||
rc = rc? rc : log_get_errorcount(0)? 2 :
|
||||
g10_errors_seen? 1 : 0;
|
||||
exit(rc );
|
||||
}
|
||||
|
||||
|
||||
/* Stub:
|
||||
* We have to override the trustcheck from pkclist.c becuase
|
||||
* this utility assumes that all keys in the keyring are trustworthy
|
||||
*/
|
||||
int
|
||||
check_signatures_trust( PKT_signature *sig )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Stub:
|
||||
* We don't have the trustdb , so we have to provide some stub functions
|
||||
* instead
|
||||
*/
|
||||
int
|
||||
get_validity_info (PKT_public_key *pk, const byte *namehash )
|
||||
{
|
||||
return '?';
|
||||
}
|
||||
|
||||
/* Stub: */
|
||||
int
|
||||
get_ownertrust_info (PKT_public_key *pk)
|
||||
{
|
||||
return '?';
|
||||
}
|
||||
|
||||
unsigned int
|
||||
get_ownertrust (PKT_public_key *pk)
|
||||
{
|
||||
return TRUST_UNKNOWN;
|
||||
}
|
||||
|
||||
|
||||
/* Stub:
|
||||
* Because we only work with trusted keys, it does not make sense to
|
||||
* get them from a keyserver
|
||||
*/
|
||||
int
|
||||
keyserver_import_keyid( u32 *keyid, void *dummy )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Stub:
|
||||
* No encryption here but mainproc links to these functions.
|
||||
*/
|
||||
int
|
||||
get_session_key( PKT_pubkey_enc *k, DEK *dek )
|
||||
{
|
||||
return G10ERR_GENERAL;
|
||||
}
|
||||
/* Stub: */
|
||||
int
|
||||
get_override_session_key( DEK *dek, const char *string )
|
||||
{
|
||||
return G10ERR_GENERAL;
|
||||
}
|
||||
/* Stub: */
|
||||
int
|
||||
decrypt_data( void *procctx, PKT_encrypted *ed, DEK *dek )
|
||||
{
|
||||
return G10ERR_GENERAL;
|
||||
}
|
||||
|
||||
|
||||
/* Stub:
|
||||
* No interactive commnds, so we don't need the helptexts
|
||||
*/
|
||||
void
|
||||
display_online_help( const char *keyword )
|
||||
{
|
||||
}
|
||||
|
||||
/* Stub:
|
||||
* We don't use secret keys, but getkey.c links to this
|
||||
*/
|
||||
int
|
||||
check_secret_key( PKT_secret_key *sk, int n )
|
||||
{
|
||||
return G10ERR_GENERAL;
|
||||
}
|
||||
|
||||
/* Stub:
|
||||
* No secret key, so no passphrase needed
|
||||
*/
|
||||
DEK *
|
||||
passphrase_to_dek( u32 *keyid, int pubkey_algo,
|
||||
int cipher_algo, STRING2KEY *s2k, int mode,
|
||||
const char *tmp)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Stubs to avoid linking to photoid.c */
|
||||
void show_photos(const struct user_attribute *attrs,int count,PKT_public_key *pk) {}
|
||||
int parse_image_header(const struct user_attribute *attr,byte *type,u32 *len) {return 0;}
|
||||
char *image_type_to_string(byte type,int string) {return NULL;}
|
||||
|
||||
/* Stubs to void linking to ../cipher/cipher.c */
|
||||
int string_to_cipher_algo( const char *string ) { return 0; }
|
||||
const char *cipher_algo_to_string( int algo ) { return "?";}
|
||||
void disable_cipher_algo( int algo ) {}
|
||||
int check_cipher_algo( int algo ) { return -1;}
|
||||
unsigned int cipher_get_keylen( int algo ) { return 0; }
|
||||
unsigned int cipher_get_blocksize( int algo ) {return 0;}
|
||||
CIPHER_HANDLE cipher_open( int algo, int mode, int secure ) { return NULL;}
|
||||
void cipher_close( CIPHER_HANDLE c ) {}
|
||||
int cipher_setkey( CIPHER_HANDLE c, byte *key, unsigned keylen ) { return -1;}
|
||||
void cipher_setiv( CIPHER_HANDLE c, const byte *iv, unsigned ivlen ){}
|
||||
void cipher_encrypt( CIPHER_HANDLE c, byte *outbuf,
|
||||
byte *inbuf, unsigned nbytes ) {}
|
||||
void cipher_decrypt( CIPHER_HANDLE c, byte *outbuf,
|
||||
byte *inbuf, unsigned nbytes ) {}
|
||||
void cipher_sync( CIPHER_HANDLE c ) {}
|
||||
|
||||
/* Stubs to avoid linking to ../cipher/random.c */
|
||||
void random_dump_stats(void) {}
|
||||
int quick_random_gen( int onoff ) { return -1;}
|
||||
void randomize_buffer( byte *buffer, size_t length, int level ) {}
|
||||
int random_is_faked() { return -1;}
|
||||
byte *get_random_bits( size_t nbits, int level, int secure ) { return NULL;}
|
||||
void set_random_seed_file( const char *name ) {}
|
||||
void update_random_seed_file() {}
|
||||
void fast_random_poll() {}
|
||||
|
||||
/* Stubs to avoid linking of ../cipher/primegen.c */
|
||||
void register_primegen_progress ( void (*cb)( void *, int), void *cb_data ) {}
|
||||
MPI generate_secret_prime( unsigned nbits ) { return NULL;}
|
||||
MPI generate_public_prime( unsigned nbits ) { return NULL;}
|
||||
MPI generate_elg_prime( int mode, unsigned pbits, unsigned qbits,
|
||||
MPI g, MPI **ret_factors ) { return NULL;}
|
||||
|
||||
/* Do not link to ../cipher/rndlinux.c */
|
||||
void rndlinux_constructor(void) {}
|
||||
|
||||
|
||||
/* Stubs to avoid linking to ../util/ttyio.c */
|
||||
int tty_batchmode( int onoff ) { return 0; }
|
||||
void tty_printf( const char *fmt, ... ) { }
|
||||
void tty_print_string( byte *p, size_t n ) { }
|
||||
void tty_print_utf8_string( byte *p, size_t n ) {}
|
||||
void tty_print_utf8_string2( byte *p, size_t n, size_t max_n ) {}
|
||||
char *tty_get( const char *prompt ) { return NULL;}
|
||||
char *tty_get_hidden( const char *prompt ) {return NULL; }
|
||||
void tty_kill_prompt(void) {}
|
||||
int tty_get_answer_is_yes( const char *prompt ) {return 0;}
|
||||
int tty_no_terminal(int onoff) {return 0;}
|
||||
|
||||
/* We do not do any locking, so use these stubs here */
|
||||
void disable_dotlock(void) {}
|
||||
DOTLOCK create_dotlock( const char *file_to_lock ) { return NULL; }
|
||||
int make_dotlock( DOTLOCK h, long timeout ) { return 0;}
|
||||
int release_dotlock( DOTLOCK h ) {return 0;}
|
||||
void remove_lockfiles(void) {}
|
@ -1,5 +1,5 @@
|
||||
/* helptext.c - English help texts
|
||||
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
|
||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
@ -49,6 +49,13 @@ static struct helptexts { const char *key; const char *help; } helptexts[] = {
|
||||
"to do with the (implicitly created) web-of-certificates."
|
||||
)},
|
||||
|
||||
{ "edit_ownertrust.set_ultimate.okay", N_(
|
||||
"To build the Web-of-Trust, GnuPG needs to know which keys are\n"
|
||||
"ultimately trusted - those are usually the keys for which you have\n"
|
||||
"access to the secret key. Answer \"yes\" to set this key to\n"
|
||||
"ultimately trusted\n"
|
||||
)},
|
||||
|
||||
{ "revoked_key.override", N_(
|
||||
"If you want to use this revoked key anyway, answer \"yes\"."
|
||||
)},
|
||||
@ -87,6 +94,12 @@ static struct helptexts { const char *key; const char *help; } helptexts[] = {
|
||||
"with them are quite large and very slow to verify."
|
||||
)},
|
||||
|
||||
{ "keygen.algo.rsa_se", N_(
|
||||
"In general it is not a good idea to use the same key for signing and\n"
|
||||
"encryption. This algorithm should only be used in certain domains.\n"
|
||||
"Please consult your security expert first."
|
||||
)},
|
||||
|
||||
|
||||
{ "keygen.size", N_(
|
||||
"Enter the size of the key"
|
||||
@ -145,6 +158,29 @@ static struct helptexts { const char *key; const char *help; } helptexts[] = {
|
||||
"Answer \"yes\" or \"no\""
|
||||
)},
|
||||
|
||||
{ "sign_uid.class", N_(
|
||||
"When you sign a user ID on a key, you should first verify that the key\n"
|
||||
"belongs to the person named in the user ID. It is useful for others to\n"
|
||||
"know how carefully you verified this.\n\n"
|
||||
"\"0\" means you make no particular claim as to how carefully you verified the\n"
|
||||
" key.\n\n"
|
||||
"\"1\" means you believe the key is owned by the person who claims to own it\n"
|
||||
" but you could not, or did not verify the key at all. This is useful for\n"
|
||||
" a \"persona\" verification, where you sign the key of a pseudonymous user.\n\n"
|
||||
"\"2\" means you did casual verification of the key. For example, this could\n"
|
||||
" mean that you verified the key fingerprint and checked the user ID on the\n"
|
||||
" key against a photo ID.\n\n"
|
||||
"\"3\" means you did extensive verification of the key. For example, this could\n"
|
||||
" mean that you verified the key fingerprint with the owner of the key in\n"
|
||||
" person, and that you checked, by means of a hard to forge document with a\n"
|
||||
" photo ID (such as a passport) that the name of the key owner matches the\n"
|
||||
" name in the user ID on the key, and finally that you verified (by exchange\n"
|
||||
" of email) that the email address on the key belongs to the key owner.\n\n"
|
||||
"Note that the examples given above for levels 2 and 3 are *only* examples.\n"
|
||||
"In the end, it is up to you to decide just what \"casual\" and \"extensive\"\n"
|
||||
"mean to you when you sign other keys.\n\n"
|
||||
"If you don't know what the right answer is, answer \"0\"."
|
||||
)},
|
||||
|
||||
{ "change_passwd.empty.okay", N_(
|
||||
"Answer \"yes\" or \"no\""
|
||||
@ -197,11 +233,16 @@ static struct helptexts { const char *key; const char *help; } helptexts[] = {
|
||||
"a second one is available."
|
||||
)},
|
||||
|
||||
{ "keyedit.updpref.okay", N_(
|
||||
"Change the preferences of all user IDs (or just of the selected ones)\n"
|
||||
"to the current list of preferences. The timestamp of all affected\n"
|
||||
"self-signatures will be advanced by one second.\n"
|
||||
)},
|
||||
|
||||
|
||||
{ "passphrase.enter", N_(
|
||||
""
|
||||
"Please enter the passhrase; this is a secret sentence \n"
|
||||
" Blurb, blurb,.... "
|
||||
)},
|
||||
|
||||
|
||||
@ -231,7 +272,7 @@ static struct helptexts { const char *key; const char *help; } helptexts[] = {
|
||||
" \"Key has been compromised\"\n"
|
||||
" Use this if you have a reason to believe that unauthorized persons\n"
|
||||
" got access to your secret key.\n"
|
||||
" \"Key is superseeded\"\n"
|
||||
" \"Key is superseded\"\n"
|
||||
" Use this if you have replaced this key with a newer one.\n"
|
||||
" \"Key is no longer used\"\n"
|
||||
" Use this if you have retired this key.\n"
|
||||
@ -271,5 +312,3 @@ display_online_help( const char *keyword )
|
||||
}
|
||||
tty_printf("\n");
|
||||
}
|
||||
|
||||
|
||||
|
503
g10/hkp.c
503
g10/hkp.c
@ -1,5 +1,5 @@
|
||||
/* hkp.c - Horrowitz Keyserver Protocol
|
||||
* Copyright (C) 1999 Free Software Foundation, Inc.
|
||||
/* hkp.c - Horowitz Keyserver Protocol
|
||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
@ -34,6 +34,7 @@
|
||||
#include "filter.h"
|
||||
#include "http.h"
|
||||
#include "main.h"
|
||||
#include "keyserver-internal.h"
|
||||
|
||||
static int urlencode_filter( void *opaque, int control,
|
||||
IOBUF a, byte *buf, size_t *ret_len);
|
||||
@ -47,95 +48,72 @@ static int urlencode_filter( void *opaque, int control,
|
||||
* or other error codes.
|
||||
*/
|
||||
int
|
||||
hkp_ask_import( u32 *keyid )
|
||||
hkp_ask_import( KEYDB_SEARCH_DESC *desc, void *stats_handle)
|
||||
{
|
||||
#ifdef HAVE_DOSISH_SYSTEM
|
||||
return -1;
|
||||
#else
|
||||
struct http_context hd;
|
||||
char *request;
|
||||
int rc;
|
||||
unsigned int hflags = opt.honor_http_proxy? HTTP_FLAG_TRY_PROXY : 0;
|
||||
unsigned int hflags = opt.keyserver_options.honor_http_proxy? HTTP_FLAG_TRY_PROXY : 0;
|
||||
u32 key[2];
|
||||
|
||||
if( !opt.keyserver_name )
|
||||
return -1;
|
||||
log_info(_("requesting key %08lX from %s ...\n"), (ulong)keyid[1],
|
||||
opt.keyserver_name );
|
||||
request = gcry_xmalloc( strlen( opt.keyserver_name ) + 100 );
|
||||
if(desc->mode==KEYDB_SEARCH_MODE_FPR20)
|
||||
keyid_from_fingerprint(desc->u.fpr,MAX_FINGERPRINT_LEN,key);
|
||||
else if(desc->mode==KEYDB_SEARCH_MODE_LONG_KID ||
|
||||
desc->mode==KEYDB_SEARCH_MODE_SHORT_KID)
|
||||
{
|
||||
key[0]=desc->u.kid[0];
|
||||
key[1]=desc->u.kid[1];
|
||||
}
|
||||
else
|
||||
return -1; /* HKP does not support v3 fingerprints */
|
||||
|
||||
log_info(_("requesting key %08lX from HKP keyserver %s\n"),
|
||||
(ulong)key[1],opt.keyserver_host );
|
||||
request = m_alloc( strlen( opt.keyserver_host ) + 100 );
|
||||
/* hkp does not accept the long keyid - we should really write a
|
||||
* nicer one :-)
|
||||
* FIXME: request binary mode - need to pass no_armor mode
|
||||
* down to the import function. Marc told that there is such a
|
||||
* binary mode ... how?
|
||||
*/
|
||||
sprintf( request, "x-hkp://%s:11371/pks/lookup?op=get&search=0x%08lX",
|
||||
opt.keyserver_name, (ulong)keyid[1] );
|
||||
|
||||
if(opt.keyserver_options.broken_http_proxy)
|
||||
hflags |= HTTP_FLAG_NO_SHUTDOWN;
|
||||
|
||||
sprintf(request,"x-hkp://%s%s%s/pks/lookup?op=get&search=0x%08lX",
|
||||
opt.keyserver_host,
|
||||
atoi(opt.keyserver_port)>0?":":"",
|
||||
atoi(opt.keyserver_port)>0?opt.keyserver_port:"",
|
||||
(ulong)key[1] );
|
||||
|
||||
if(opt.keyserver_options.verbose>2)
|
||||
log_info("request is \"%s\"\n",request);
|
||||
|
||||
rc = http_open_document( &hd, request, hflags );
|
||||
if( rc ) {
|
||||
log_info(_("can't get key from keyserver: %s\n"),
|
||||
rc == GPGERR_NETWORK? strerror(errno)
|
||||
: gpg_errstr(rc) );
|
||||
rc == G10ERR_NETWORK? strerror(errno)
|
||||
: g10_errstr(rc) );
|
||||
}
|
||||
else {
|
||||
rc = import_keys_stream( hd.fp_read , 0 );
|
||||
rc = import_keys_stream( hd.fp_read, 0, stats_handle);
|
||||
http_close( &hd );
|
||||
}
|
||||
|
||||
gcry_free( request );
|
||||
m_free( request );
|
||||
return rc;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
hkp_import( STRLIST users )
|
||||
{
|
||||
#ifdef HAVE_DOSISH_SYSTEM
|
||||
return -1;
|
||||
#else
|
||||
if( !opt.keyserver_name ) {
|
||||
log_error(_("no keyserver known (use option --keyserver)\n"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
for( ; users; users = users->next ) {
|
||||
u32 kid[2];
|
||||
int type = classify_user_id( users->d, kid, NULL, NULL, NULL );
|
||||
if( type != 10 && type != 11 ) {
|
||||
log_info(_("%s: not a valid key ID\n"), users->d );
|
||||
continue;
|
||||
}
|
||||
/* because the function may use log_info in some situations, the
|
||||
* errorcounter ist not increaed and the program will return
|
||||
* with success - which is not good when this function is used.
|
||||
*/
|
||||
if( hkp_ask_import( kid ) )
|
||||
log_inc_errorcount();
|
||||
}
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
hkp_export( STRLIST users )
|
||||
{
|
||||
#ifdef HAVE_DOSISH_SYSTEM
|
||||
return -1;
|
||||
#else
|
||||
int rc;
|
||||
armor_filter_context_t afx;
|
||||
IOBUF temp = iobuf_temp();
|
||||
struct http_context hd;
|
||||
char *request;
|
||||
unsigned int status;
|
||||
unsigned int hflags = opt.honor_http_proxy? HTTP_FLAG_TRY_PROXY : 0;
|
||||
|
||||
if( !opt.keyserver_name ) {
|
||||
log_error(_("no keyserver known (use option --keyserver)\n"));
|
||||
return -1;
|
||||
}
|
||||
unsigned int hflags = opt.keyserver_options.honor_http_proxy? HTTP_FLAG_TRY_PROXY : 0;
|
||||
|
||||
iobuf_push_filter( temp, urlencode_filter, NULL );
|
||||
|
||||
@ -151,23 +129,34 @@ hkp_export( STRLIST users )
|
||||
|
||||
iobuf_flush_temp( temp );
|
||||
|
||||
request = gcry_xmalloc( strlen( opt.keyserver_name ) + 100 );
|
||||
sprintf( request, "x-hkp://%s:11371/pks/add", opt.keyserver_name );
|
||||
request = m_alloc( strlen( opt.keyserver_host ) + 100 );
|
||||
|
||||
if(opt.keyserver_options.broken_http_proxy)
|
||||
hflags |= HTTP_FLAG_NO_SHUTDOWN;
|
||||
|
||||
sprintf( request, "x-hkp://%s%s%s/pks/add",
|
||||
opt.keyserver_host,
|
||||
atoi(opt.keyserver_port)>0?":":"",
|
||||
atoi(opt.keyserver_port)>0?opt.keyserver_port:"");
|
||||
|
||||
if(opt.keyserver_options.verbose>2)
|
||||
log_info("request is \"%s\"\n",request);
|
||||
|
||||
rc = http_open( &hd, HTTP_REQ_POST, request , hflags );
|
||||
if( rc ) {
|
||||
log_error(_("can't connect to `%s': %s\n"),
|
||||
opt.keyserver_name,
|
||||
rc == GPGERR_NETWORK? strerror(errno)
|
||||
: gpg_errstr(rc) );
|
||||
opt.keyserver_host,
|
||||
rc == G10ERR_NETWORK? strerror(errno)
|
||||
: g10_errstr(rc) );
|
||||
iobuf_close(temp);
|
||||
gcry_free( request );
|
||||
m_free( request );
|
||||
return rc;
|
||||
}
|
||||
|
||||
sprintf( request, "Content-Length: %u\n",
|
||||
(unsigned)iobuf_get_temp_length(temp) + 9 );
|
||||
iobuf_writestr( hd.fp_write, request );
|
||||
gcry_free( request );
|
||||
m_free( request );
|
||||
http_start_data( &hd );
|
||||
|
||||
iobuf_writestr( hd.fp_write, "keytext=" );
|
||||
@ -180,26 +169,28 @@ hkp_export( STRLIST users )
|
||||
rc = http_wait_response( &hd, &status );
|
||||
if( rc ) {
|
||||
log_error(_("error sending to `%s': %s\n"),
|
||||
opt.keyserver_name, gpg_errstr(rc) );
|
||||
opt.keyserver_host, g10_errstr(rc) );
|
||||
}
|
||||
else {
|
||||
#if 1
|
||||
if( opt.verbose ) {
|
||||
int c;
|
||||
while( (c=iobuf_get(hd.fp_read)) != EOF )
|
||||
if ( c >= 32 && c < 127 )
|
||||
putchar( c );
|
||||
else
|
||||
putchar ( '?' );
|
||||
}
|
||||
#endif
|
||||
if( (status/100) == 2 )
|
||||
log_info(_("success sending to `%s' (status=%u)\n"),
|
||||
opt.keyserver_name, status );
|
||||
opt.keyserver_host, status );
|
||||
else
|
||||
log_error(_("failed sending to `%s': status=%u\n"),
|
||||
opt.keyserver_name, status );
|
||||
opt.keyserver_host, status );
|
||||
}
|
||||
http_close( &hd );
|
||||
return rc;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int
|
||||
@ -228,3 +219,373 @@ urlencode_filter( void *opaque, int control,
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int
|
||||
write_quoted(IOBUF a, const char *buf, char delim)
|
||||
{
|
||||
char quoted[5];
|
||||
|
||||
sprintf(quoted,"\\x%02X",delim);
|
||||
|
||||
while(*buf)
|
||||
{
|
||||
if(*buf==delim)
|
||||
{
|
||||
if(iobuf_writestr(a,quoted))
|
||||
return -1;
|
||||
}
|
||||
else if(*buf=='\\')
|
||||
{
|
||||
if(iobuf_writestr(a,"\\x5c"))
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(iobuf_writebyte(a,*buf))
|
||||
return -1;
|
||||
}
|
||||
|
||||
buf++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* pub 2048/<a href="/pks/lookup?op=get&search=0x3CB3B415">3CB3B415</a> 1998/04/03 David M. Shaw <<a href="/pks/lookup?op=get&search=0x3CB3B415">dshaw@jabberwocky.com</a>> */
|
||||
|
||||
/* Luckily enough, both the HKP server and NAI HKP interface to their
|
||||
LDAP server are close enough in output so the same function can
|
||||
parse them both. */
|
||||
|
||||
static int
|
||||
parse_hkp_index(IOBUF buffer,char *line)
|
||||
{
|
||||
static int open=0,revoked=0;
|
||||
static char *key=NULL;
|
||||
#ifdef __riscos__
|
||||
static char *uid=NULL;
|
||||
#else
|
||||
static unsigned char *uid=NULL;
|
||||
#endif
|
||||
static u32 bits,createtime;
|
||||
int ret=0;
|
||||
|
||||
/* printf("Open %d, LINE: %s, uid: %s\n",open,line,uid); */
|
||||
|
||||
/* Try and catch some bastardization of HKP. If we don't have
|
||||
certain unchanging landmarks, we can't reliably parse the
|
||||
response. */
|
||||
if(open && ascii_memcasecmp(line,"</pre>",6)!=0 &&
|
||||
ascii_memcasecmp(line,"pub ",5)!=0 &&
|
||||
ascii_memcasecmp(line," ",5)!=0)
|
||||
{
|
||||
m_free(key);
|
||||
m_free(uid);
|
||||
log_error(_("this keyserver is not fully HKP compatible\n"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* For multiple UIDs */
|
||||
if(open && uid!=NULL)
|
||||
{
|
||||
ret=0;
|
||||
|
||||
if(!(revoked && !opt.keyserver_options.include_revoked))
|
||||
{
|
||||
char intstr[11];
|
||||
|
||||
if(key)
|
||||
write_quoted(buffer,key,':');
|
||||
iobuf_writestr(buffer,":");
|
||||
write_quoted(buffer,uid,':');
|
||||
iobuf_writestr(buffer,":");
|
||||
iobuf_writestr(buffer,revoked?"1:":":");
|
||||
sprintf(intstr,"%u",createtime);
|
||||
write_quoted(buffer,intstr,':');
|
||||
iobuf_writestr(buffer,"::::");
|
||||
sprintf(intstr,"%u",bits);
|
||||
write_quoted(buffer,intstr,':');
|
||||
iobuf_writestr(buffer,"\n");
|
||||
|
||||
ret=1;
|
||||
}
|
||||
|
||||
if(strncmp(line," ",5)!=0)
|
||||
{
|
||||
revoked=0;
|
||||
m_free(key);
|
||||
m_free(uid);
|
||||
uid=NULL;
|
||||
open=0;
|
||||
}
|
||||
}
|
||||
|
||||
if(ascii_memcasecmp(line,"pub ",5)==0)
|
||||
{
|
||||
char *tok,*temp;
|
||||
|
||||
open=1;
|
||||
|
||||
line+=4;
|
||||
|
||||
tok=strsep(&line,"/");
|
||||
if(tok==NULL)
|
||||
return ret;
|
||||
|
||||
bits=atoi(tok);
|
||||
|
||||
tok=strsep(&line,">");
|
||||
if(tok==NULL)
|
||||
return ret;
|
||||
|
||||
tok=strsep(&line,"<");
|
||||
if(tok==NULL)
|
||||
return ret;
|
||||
|
||||
key=m_strdup(tok);
|
||||
|
||||
tok=strsep(&line," ");
|
||||
if(tok==NULL)
|
||||
return ret;
|
||||
|
||||
tok=strsep(&line," ");
|
||||
if(tok==NULL)
|
||||
return ret;
|
||||
|
||||
/* The date parser wants '-' instead of '/', so... */
|
||||
temp=tok;
|
||||
while(*temp!='\0')
|
||||
{
|
||||
if(*temp=='/')
|
||||
*temp='-';
|
||||
|
||||
temp++;
|
||||
}
|
||||
|
||||
createtime=scan_isodatestr(tok);
|
||||
}
|
||||
|
||||
if(open)
|
||||
{
|
||||
int uidindex=0;
|
||||
|
||||
if(line==NULL)
|
||||
{
|
||||
uid=m_strdup("Key index corrupted");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* All that's left is the user name. Strip off anything
|
||||
<between brackets> and de-urlencode it. */
|
||||
|
||||
while(*line==' ' && *line!='\0')
|
||||
line++;
|
||||
|
||||
if(strncmp(line,"*** KEY REVOKED ***",19)==0)
|
||||
{
|
||||
revoked=1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
uid=m_alloc(strlen(line)+1);
|
||||
|
||||
while(*line!='\0')
|
||||
{
|
||||
switch(*line)
|
||||
{
|
||||
case '<':
|
||||
while(*line!='>' && *line!='\0')
|
||||
line++;
|
||||
|
||||
if(*line!='\0')
|
||||
line++;
|
||||
break;
|
||||
|
||||
case '&':
|
||||
if((*(line+1)!='\0' && tolower(*(line+1))=='l') &&
|
||||
(*(line+2)!='\0' && tolower(*(line+2))=='t') &&
|
||||
(*(line+3)!='\0' && *(line+3)==';'))
|
||||
{
|
||||
uid[uidindex++]='<';
|
||||
line+=4;
|
||||
break;
|
||||
}
|
||||
else if((*(line+1)!='\0' && tolower(*(line+1))=='g') &&
|
||||
(*(line+2)!='\0' && tolower(*(line+2))=='t') &&
|
||||
(*(line+3)!='\0' && *(line+3)==';'))
|
||||
{
|
||||
uid[uidindex++]='>';
|
||||
line+=4;
|
||||
break;
|
||||
}
|
||||
else if((*(line+1)!='\0' && tolower(*(line+1))=='a') &&
|
||||
(*(line+2)!='\0' && tolower(*(line+2))=='m') &&
|
||||
(*(line+3)!='\0' && tolower(*(line+3))=='p') &&
|
||||
(*(line+4)!='\0' && *(line+4)==';'))
|
||||
{
|
||||
uid[uidindex++]='&';
|
||||
line+=5;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
uid[uidindex++]=*line;
|
||||
line++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uid[uidindex]='\0';
|
||||
|
||||
/* Chop off the trailing \r, \n, or both. This is fussy as the
|
||||
true HKP servers have \r\n, and the NAI HKP servers have just
|
||||
\n. */
|
||||
|
||||
if(isspace(uid[uidindex-1]))
|
||||
uid[uidindex-1]='\0';
|
||||
|
||||
if(isspace(uid[uidindex-2]))
|
||||
uid[uidindex-2]='\0';
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int hkp_search(STRLIST tokens)
|
||||
{
|
||||
int rc=0,len=0,max,first=1;
|
||||
unsigned int maxlen=1024,buflen=0;
|
||||
#ifndef __riscos__
|
||||
unsigned char *searchstr=NULL,*searchurl;
|
||||
unsigned char *request;
|
||||
#else
|
||||
char *searchstr=NULL,*searchurl;
|
||||
char *request;
|
||||
#endif
|
||||
struct http_context hd;
|
||||
unsigned int hflags=opt.keyserver_options.honor_http_proxy?HTTP_FLAG_TRY_PROXY:0;
|
||||
byte *line=NULL;
|
||||
|
||||
/* Glue the tokens together to make a search string */
|
||||
|
||||
for(;tokens;tokens=tokens->next)
|
||||
{
|
||||
len+=strlen(tokens->d)+1;
|
||||
|
||||
searchstr=m_realloc(searchstr,len+1);
|
||||
if(first)
|
||||
{
|
||||
searchstr[0]='\0';
|
||||
first=0;
|
||||
}
|
||||
|
||||
strcat(searchstr,tokens->d);
|
||||
strcat(searchstr," ");
|
||||
}
|
||||
|
||||
if(len<=1)
|
||||
{
|
||||
m_free(searchstr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
searchstr[len-1]='\0';
|
||||
|
||||
log_info(_("searching for \"%s\" from HKP server %s\n"),
|
||||
searchstr,opt.keyserver_host);
|
||||
|
||||
/* Now make it url-ish */
|
||||
|
||||
max=0;
|
||||
len=0;
|
||||
searchurl=NULL;
|
||||
request=searchstr;
|
||||
|
||||
while(*request!='\0')
|
||||
{
|
||||
if(max-len<3)
|
||||
{
|
||||
max+=100;
|
||||
searchurl=m_realloc(searchurl,max+1); /* Note +1 for \0 */
|
||||
}
|
||||
|
||||
if(isalnum(*request) || *request=='-')
|
||||
searchurl[len++]=*request;
|
||||
else if(*request==' ')
|
||||
searchurl[len++]='+';
|
||||
else
|
||||
{
|
||||
sprintf(&searchurl[len],"%%%02X",*request);
|
||||
len+=3;
|
||||
}
|
||||
|
||||
request++;
|
||||
}
|
||||
|
||||
searchurl[len]='\0';
|
||||
|
||||
request=m_alloc(strlen(opt.keyserver_host) + 100 + strlen(searchurl));
|
||||
|
||||
if(opt.keyserver_options.broken_http_proxy)
|
||||
hflags |= HTTP_FLAG_NO_SHUTDOWN;
|
||||
|
||||
sprintf(request,"x-hkp://%s%s%s/pks/lookup?op=index&search=%s",
|
||||
opt.keyserver_host,
|
||||
atoi(opt.keyserver_port)>0?":":"",
|
||||
atoi(opt.keyserver_port)>0?opt.keyserver_port:"",
|
||||
searchurl);
|
||||
|
||||
if(opt.keyserver_options.verbose>2)
|
||||
log_info("request is \"%s\"\n",request);
|
||||
|
||||
rc=http_open_document(&hd,request,hflags);
|
||||
if(rc)
|
||||
{
|
||||
log_error(_("can't search keyserver: %s\n"),
|
||||
rc==G10ERR_NETWORK?strerror(errno):g10_errstr(rc));
|
||||
}
|
||||
else
|
||||
{
|
||||
IOBUF buffer;
|
||||
int count=1;
|
||||
int ret;
|
||||
|
||||
buffer=iobuf_temp();
|
||||
|
||||
rc=1;
|
||||
while(rc!=0)
|
||||
{
|
||||
/* This is a judgement call. Is it better to slurp up all
|
||||
the results before prompting the user? On the one hand,
|
||||
it probably makes the keyserver happier to not be blocked
|
||||
on sending for a long time while the user picks a key.
|
||||
On the other hand, it might be nice for the server to be
|
||||
able to stop sending before a large search result page is
|
||||
complete. */
|
||||
|
||||
rc=iobuf_read_line(hd.fp_read,&line,&buflen,&maxlen);
|
||||
|
||||
ret=parse_hkp_index(buffer,line);
|
||||
if(ret==-1)
|
||||
break;
|
||||
|
||||
if(rc!=0)
|
||||
count+=ret;
|
||||
}
|
||||
|
||||
http_close(&hd);
|
||||
|
||||
count--;
|
||||
|
||||
if(ret>-1)
|
||||
keyserver_search_prompt(buffer,count,searchstr);
|
||||
|
||||
iobuf_close(buffer);
|
||||
m_free(line);
|
||||
}
|
||||
|
||||
m_free(request);
|
||||
m_free(searchurl);
|
||||
m_free(searchstr);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
15
g10/hkp.h
15
g10/hkp.h
@ -1,5 +1,5 @@
|
||||
/* hkp.h - Horrowitz Keyserver Protocol
|
||||
* Copyright (C) 1999, 2000 Free Software Foundation, Inc.
|
||||
/* hkp.h - Horowitz Keyserver Protocol
|
||||
* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
@ -18,13 +18,12 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
#ifndef GPG_HKP_H
|
||||
#define GPG_HKP_H 1
|
||||
#ifndef G10_HKP_H
|
||||
#define G10_HKP_H 1
|
||||
|
||||
|
||||
int hkp_ask_import( u32 *keyid );
|
||||
int hkp_ask_import( KEYDB_SEARCH_DESC *desc, void *stats_handle);
|
||||
int hkp_import( STRLIST users );
|
||||
int hkp_export( STRLIST users );
|
||||
int hkp_search(STRLIST tokens);
|
||||
|
||||
|
||||
#endif /*GPG_HKP_H*/
|
||||
#endif /*G10_HKP_H*/
|
||||
|
801
g10/import.c
801
g10/import.c
File diff suppressed because it is too large
Load Diff
56
g10/kbnode.c
56
g10/kbnode.c
@ -1,5 +1,5 @@
|
||||
/* kbnode.c - keyblock node utility functions
|
||||
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
|
||||
* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
@ -23,9 +23,8 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <gcrypt.h>
|
||||
#include "util.h"
|
||||
#include "memory.h"
|
||||
#include "packet.h"
|
||||
#include "keydb.h"
|
||||
|
||||
@ -42,7 +41,7 @@ alloc_node(void)
|
||||
if( n )
|
||||
unused_nodes = n->next;
|
||||
else
|
||||
n = gcry_xmalloc( sizeof *n );
|
||||
n = m_alloc( sizeof *n );
|
||||
n->next = NULL;
|
||||
n->pkt = NULL;
|
||||
n->flag = 0;
|
||||
@ -59,7 +58,7 @@ free_node( KBNODE n )
|
||||
n->next = unused_nodes;
|
||||
unused_nodes = n;
|
||||
#else
|
||||
gcry_free( n );
|
||||
m_free( n );
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@ -95,7 +94,7 @@ release_kbnode( KBNODE n )
|
||||
n2 = n->next;
|
||||
if( !is_cloned_kbnode(n) ) {
|
||||
free_packet( n->pkt );
|
||||
gcry_free( n->pkt );
|
||||
m_free( n->pkt );
|
||||
}
|
||||
free_node( n );
|
||||
n = n2;
|
||||
@ -165,9 +164,10 @@ find_prev_kbnode( KBNODE root, KBNODE node, int pkttype )
|
||||
{
|
||||
KBNODE n1;
|
||||
|
||||
for(n1=NULL ; root && root != node; root = root->next )
|
||||
if( !pkttype || root->pkt->pkttype == pkttype )
|
||||
n1 = root;
|
||||
for (n1=NULL; root && root != node; root = root->next ) {
|
||||
if (!pkttype ||root->pkt->pkttype == pkttype)
|
||||
n1 = root;
|
||||
}
|
||||
return n1;
|
||||
}
|
||||
|
||||
@ -185,7 +185,7 @@ find_next_kbnode( KBNODE node, int pkttype )
|
||||
for( node=node->next ; node; node = node->next ) {
|
||||
if( !pkttype )
|
||||
return node;
|
||||
else if( pkttype == PKT_USER_ID
|
||||
else if( pkttype == PKT_USER_ID
|
||||
&& ( node->pkt->pkttype == PKT_PUBLIC_KEY
|
||||
|| node->pkt->pkttype == PKT_SECRET_KEY ) )
|
||||
return NULL;
|
||||
@ -267,7 +267,7 @@ commit_kbnode( KBNODE *root )
|
||||
nl->next = n->next;
|
||||
if( !is_cloned_kbnode(n) ) {
|
||||
free_packet( n->pkt );
|
||||
gcry_free( n->pkt );
|
||||
m_free( n->pkt );
|
||||
}
|
||||
free_node( n );
|
||||
changed = 1;
|
||||
@ -291,7 +291,7 @@ remove_kbnode( KBNODE *root, KBNODE node )
|
||||
nl->next = n->next;
|
||||
if( !is_cloned_kbnode(n) ) {
|
||||
free_packet( n->pkt );
|
||||
gcry_free( n->pkt );
|
||||
m_free( n->pkt );
|
||||
}
|
||||
free_node( n );
|
||||
}
|
||||
@ -356,28 +356,44 @@ dump_kbnode( KBNODE node )
|
||||
case PKT_PLAINTEXT: s="plaintext"; break;
|
||||
case PKT_COMPRESSED: s="compressed"; break;
|
||||
case PKT_ENCRYPTED: s="encrypted"; break;
|
||||
case PKT_GPG_CONTROL: s="gpg-control"; break;
|
||||
default: s="unknown"; break;
|
||||
}
|
||||
fprintf(stderr, "node %p %02x/%02x type=%s",
|
||||
node, node->flag, node->private_flag, s);
|
||||
if( node->pkt->pkttype == PKT_USER_ID ) {
|
||||
PKT_user_id *uid = node->pkt->pkt.user_id;
|
||||
fputs(" \"", stderr);
|
||||
print_string( stderr, node->pkt->pkt.user_id->name,
|
||||
node->pkt->pkt.user_id->len, 0 );
|
||||
fputs("\"\n", stderr);
|
||||
print_string( stderr, uid->name, uid->len, 0 );
|
||||
fprintf (stderr, "\" %c%c%c%c\n",
|
||||
uid->is_expired? 'e':'.',
|
||||
uid->is_revoked? 'r':'.',
|
||||
uid->created? 'v':'.',
|
||||
uid->is_primary? 'p':'.' );
|
||||
}
|
||||
else if( node->pkt->pkttype == PKT_SIGNATURE ) {
|
||||
fprintf(stderr, " class=%02x keyid=%08lX\n",
|
||||
fprintf(stderr, " class=%02x keyid=%08lX ts=%lu\n",
|
||||
node->pkt->pkt.signature->sig_class,
|
||||
(ulong)node->pkt->pkt.signature->keyid[1] );
|
||||
(ulong)node->pkt->pkt.signature->keyid[1],
|
||||
(ulong)node->pkt->pkt.signature->timestamp);
|
||||
}
|
||||
else if( node->pkt->pkttype == PKT_GPG_CONTROL ) {
|
||||
fprintf(stderr, " ctrl=%d len=%u\n",
|
||||
node->pkt->pkt.gpg_control->control,
|
||||
(unsigned int)node->pkt->pkt.gpg_control->datalen);
|
||||
}
|
||||
else if( node->pkt->pkttype == PKT_PUBLIC_KEY
|
||||
|| node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) {
|
||||
fprintf(stderr, " keyid=%08lX\n", (ulong)
|
||||
keyid_from_pk( node->pkt->pkt.public_key, NULL ));
|
||||
PKT_public_key *pk = node->pkt->pkt.public_key;
|
||||
fprintf(stderr, " keyid=%08lX a=%d u=%d %c%c%c%c\n",
|
||||
(ulong)keyid_from_pk( pk, NULL ),
|
||||
pk->pubkey_algo, pk->pubkey_usage,
|
||||
pk->has_expired? 'e':'.',
|
||||
pk->is_revoked? 'r':'.',
|
||||
pk->is_valid? 'v':'.',
|
||||
pk->mdc_feature? 'm':'.');
|
||||
}
|
||||
else
|
||||
fputs("\n", stderr);
|
||||
}
|
||||
}
|
||||
|
||||
|
51
g10/kbx.h
51
g10/kbx.h
@ -1,51 +0,0 @@
|
||||
/* kbx.h - The GnuPG Keybox
|
||||
* Copyright (C) 2000 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
* GnuPG is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GnuPG is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
#ifndef GPG_KBX_H
|
||||
#define GPG_KBX_H 1
|
||||
|
||||
#include "keydb.h"
|
||||
|
||||
/*-- kbxblob.c */
|
||||
struct kbxblob;
|
||||
typedef struct kbxblob *KBXBLOB;
|
||||
|
||||
int kbx_new_blob ( KBXBLOB *r_blob, char *image, size_t imagelen );
|
||||
int kbx_create_blob ( KBXBLOB *r_blob, KBNODE keyblock );
|
||||
void kbx_release_blob ( KBXBLOB blob );
|
||||
const char *kbx_get_blob_image ( KBXBLOB blob, size_t *n );
|
||||
|
||||
int kbx_dump_blob ( FILE *fp, KBXBLOB blob );
|
||||
int kbx_blob_has_fpr ( KBXBLOB blob, const byte *fpr );
|
||||
int kbx_blob_has_kid ( KBXBLOB blob, const byte *keyidbuf, size_t keyidlen );
|
||||
int kbx_blob_has_uid ( KBXBLOB blob,
|
||||
int (*cmp)(const byte *, size_t, void *), void *opaque );
|
||||
|
||||
/*-- kbxio.c --*/
|
||||
int kbx_read_blob ( KBXBLOB *r_blob, FILE *a );
|
||||
|
||||
/*-- kbxfile.c --*/
|
||||
int kbxfile_search_by_fpr( const char *filename, const byte *fpr );
|
||||
int kbxfile_search_by_kid ( const char *filename, u32 *kid, int mode );
|
||||
int kbxfile_search_by_uid ( const char *filename, const char *name );
|
||||
void print_kbxfile( const char *filename );
|
||||
|
||||
|
||||
#endif /*GPG_KBX_H*/
|
895
g10/kbxblob.c
895
g10/kbxblob.c
@ -1,895 +0,0 @@
|
||||
/* kbxblob.c - KBX Blob handling
|
||||
* Copyright (C) 2000 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
* GnuPG is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GnuPG is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
|
||||
/* The keybox data formats
|
||||
|
||||
The KeyBox uses an augmented OpenPGP key format. This makes random
|
||||
access to a keyblock easier and also gives the opportunity to store
|
||||
additional information (e.g. the fingerprint) along with the key.
|
||||
All integers are stored in network byte order, offsets are counted from
|
||||
the beginning of the Blob.
|
||||
|
||||
The first record of a plain KBX file has a special format:
|
||||
|
||||
u32 length of the first record
|
||||
byte Blob type (1)
|
||||
byte version number (1)
|
||||
byte reserved
|
||||
byte reserved
|
||||
u32 magic 'KBXf'
|
||||
byte marginals used for validity calculation of this file
|
||||
byte completes ditto.
|
||||
byte cert_depth ditto.
|
||||
|
||||
The standard KBX Blob looks like this:
|
||||
|
||||
u32 length of this blob (including these 4 bytes)
|
||||
byte Blob type (2)
|
||||
byte version number of this blob type (1)
|
||||
u16 Blob flags
|
||||
bit 0 = contains secret key material
|
||||
|
||||
u32 offset to the OpenPGP keyblock
|
||||
u32 length of the keyblock
|
||||
u16 number of keys (at least 1!)
|
||||
u16 size of additional key information
|
||||
n times:
|
||||
b20 The keys fingerprint
|
||||
(fingerprints are always 20 bytes, MD5 left padded with zeroes)
|
||||
u32 offset to the n-th key's keyID (a keyID is always 8 byte)
|
||||
u16 special key flags
|
||||
bit 0 =
|
||||
u16 reserved
|
||||
u16 number of user IDs
|
||||
u16 size of additional user ID information
|
||||
n times:
|
||||
u32 offset to the n-th user ID
|
||||
u32 length of this user ID.
|
||||
u16 special user ID flags.
|
||||
bit 0 =
|
||||
byte validity
|
||||
byte reserved
|
||||
u16 number of signatures
|
||||
u16 size of signature information (4)
|
||||
u32 expiration time of signature with some special values:
|
||||
0x00000000 = not checked
|
||||
0x00000001 = missing key
|
||||
0x00000002 = bad signature
|
||||
0x10000000 = valid and expires at some date in 1978.
|
||||
0xffffffff = valid and does not expire
|
||||
u8 assigned ownertrust
|
||||
u8 all_validity
|
||||
u16 reserved
|
||||
u32 recheck_after
|
||||
u32 Newest timestamp in the keyblock (useful for KS syncronsiation?)
|
||||
u32 Blob created at
|
||||
u32 size of reserved space (not including this field)
|
||||
reserved space
|
||||
|
||||
Here we might want to put other data
|
||||
|
||||
Here comes the keyblock
|
||||
|
||||
maybe we put a signature here later.
|
||||
|
||||
b16 MD5 checksum (useful for KS syncronisation)
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include <config.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
#include <gcrypt.h>
|
||||
|
||||
#include "iobuf.h"
|
||||
#include "util.h"
|
||||
#include "kbx.h"
|
||||
|
||||
/* special values of the signature status */
|
||||
#define SF_NONE(a) ( !(a) )
|
||||
#define SF_NOKEY(a) ((a) & (1<<0))
|
||||
#define SF_BAD(a) ((a) & (1<<1))
|
||||
#define SF_VALID(a) ((a) & (1<<29))
|
||||
|
||||
#if MAX_FINGERPRINT_LEN < 20
|
||||
#error fingerprints are 20 bytes
|
||||
#endif
|
||||
|
||||
struct kbxblob_key {
|
||||
char fpr[20];
|
||||
u32 off_kid;
|
||||
ulong off_kid_addr;
|
||||
u16 flags;
|
||||
};
|
||||
struct kbxblob_uid {
|
||||
ulong off_addr;
|
||||
u32 len;
|
||||
u16 flags;
|
||||
byte validity;
|
||||
};
|
||||
|
||||
struct keyid_list {
|
||||
struct keyid_list *next;
|
||||
int seqno;
|
||||
byte kid[8];
|
||||
};
|
||||
|
||||
struct fixup_list {
|
||||
struct fixup_list *next;
|
||||
u32 off;
|
||||
u32 val;
|
||||
};
|
||||
|
||||
|
||||
struct kbxblob {
|
||||
byte *blob;
|
||||
size_t bloblen;
|
||||
|
||||
/* stuff used only by kbx_create_blob */
|
||||
int nkeys;
|
||||
struct kbxblob_key *keys;
|
||||
int nuids;
|
||||
struct kbxblob_uid *uids;
|
||||
int nsigs;
|
||||
u32 *sigs;
|
||||
struct fixup_list *fixups;
|
||||
|
||||
struct keyid_list *temp_kids;
|
||||
IOBUF buf; /* the KBX is temporarly stored here */
|
||||
};
|
||||
|
||||
void kbx_release_blob ( KBXBLOB blob );
|
||||
|
||||
/* Note: this functions are only used for temportay iobufs and therefore
|
||||
* they can't fail */
|
||||
static void
|
||||
put8 ( IOBUF out, byte a )
|
||||
{
|
||||
iobuf_put ( out, a );
|
||||
}
|
||||
|
||||
static void
|
||||
put16 ( IOBUF out, u16 a )
|
||||
{
|
||||
iobuf_put ( out, a>>8 );
|
||||
iobuf_put ( out, a );
|
||||
}
|
||||
|
||||
static void
|
||||
put32 ( IOBUF out, u32 a )
|
||||
{
|
||||
iobuf_put (out, a>> 24);
|
||||
iobuf_put (out, a>> 16);
|
||||
iobuf_put (out, a>> 8);
|
||||
iobuf_put (out, a );
|
||||
}
|
||||
|
||||
static void
|
||||
putn ( IOBUF out, const byte *p, size_t n )
|
||||
{
|
||||
for ( ; n; p++, n-- ) {
|
||||
iobuf_put ( out, *p );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
* We must store the keyid at some place because we can't calculate the
|
||||
* offset yet. This is only used for v3 keyIDs. Function returns an index
|
||||
* value for later fixupd; this must be a non-zero value
|
||||
*/
|
||||
static int
|
||||
temp_store_kid ( KBXBLOB blob, PKT_public_key *pk )
|
||||
{
|
||||
struct keyid_list *k, *r;
|
||||
|
||||
k = gcry_xmalloc ( sizeof *k );
|
||||
k->kid[0] = pk->keyid[0] >> 24 ;
|
||||
k->kid[1] = pk->keyid[0] >> 16 ;
|
||||
k->kid[2] = pk->keyid[0] >> 8 ;
|
||||
k->kid[3] = pk->keyid[0] ;
|
||||
k->kid[4] = pk->keyid[0] >> 24 ;
|
||||
k->kid[5] = pk->keyid[0] >> 16 ;
|
||||
k->kid[6] = pk->keyid[0] >> 8 ;
|
||||
k->kid[7] = pk->keyid[0] ;
|
||||
k->seqno = 0;
|
||||
k->next = blob->temp_kids;
|
||||
blob->temp_kids = k;
|
||||
for ( r=k; r; r = r->next ) {
|
||||
k->seqno++;
|
||||
}
|
||||
|
||||
return k->seqno;
|
||||
}
|
||||
|
||||
static void
|
||||
put_stored_kid( KBXBLOB blob, int seqno )
|
||||
{
|
||||
struct keyid_list *r;
|
||||
|
||||
for ( r = blob->temp_kids; r; r = r->next ) {
|
||||
if( r->seqno == seqno ) {
|
||||
putn ( blob->buf, r->kid, 8 );
|
||||
return;
|
||||
}
|
||||
}
|
||||
BUG();
|
||||
}
|
||||
|
||||
static void
|
||||
release_kid_list ( struct keyid_list *kl )
|
||||
{
|
||||
struct keyid_list *r, *r2;
|
||||
|
||||
for ( r = kl; r; r = r2 ) {
|
||||
r2 = r->next;
|
||||
gcry_free( r );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
create_key_part( KBXBLOB blob, KBNODE keyblock )
|
||||
{
|
||||
KBNODE node;
|
||||
size_t fprlen;
|
||||
int n;
|
||||
|
||||
for ( n=0, node = keyblock; node; node = node->next ) {
|
||||
if ( node->pkt->pkttype == PKT_PUBLIC_KEY
|
||||
|| node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) {
|
||||
PKT_public_key *pk = node->pkt->pkt.public_key;
|
||||
char tmp[20];
|
||||
|
||||
fingerprint_from_pk( pk, tmp , &fprlen );
|
||||
memcpy(blob->keys[n].fpr,tmp,20);
|
||||
if ( fprlen != 20 ) { /*v3 fpr - shift right and fill with zeroes*/
|
||||
assert( fprlen == 16 );
|
||||
memmove( blob->keys[n].fpr+4, blob->keys[n].fpr, 16);
|
||||
memset( blob->keys[n].fpr, 0, 4 );
|
||||
blob->keys[n].off_kid = temp_store_kid( blob, pk );
|
||||
}
|
||||
else {
|
||||
blob->keys[n].off_kid = 0; /* will be fixed up later */
|
||||
}
|
||||
blob->keys[n].flags = 0;
|
||||
n++;
|
||||
}
|
||||
else if ( node->pkt->pkttype == PKT_SECRET_KEY
|
||||
|| node->pkt->pkttype == PKT_SECRET_SUBKEY ) {
|
||||
BUG(); /* not yet implemented */
|
||||
}
|
||||
}
|
||||
assert( n == blob->nkeys );
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
create_uid_part( KBXBLOB blob, KBNODE keyblock )
|
||||
{
|
||||
KBNODE node;
|
||||
int n;
|
||||
|
||||
for ( n=0, node = keyblock; node; node = node->next ) {
|
||||
if ( node->pkt->pkttype == PKT_USER_ID ) {
|
||||
PKT_user_id *u = node->pkt->pkt.user_id;
|
||||
|
||||
blob->uids[n].len = u->len;
|
||||
blob->uids[n].flags = 0;
|
||||
blob->uids[n].validity = 0;
|
||||
n++;
|
||||
}
|
||||
}
|
||||
assert( n == blob->nuids );
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
create_sig_part( KBXBLOB blob, KBNODE keyblock )
|
||||
{
|
||||
KBNODE node;
|
||||
int n;
|
||||
|
||||
for ( n=0, node = keyblock; node; node = node->next ) {
|
||||
if ( node->pkt->pkttype == PKT_SIGNATURE ) {
|
||||
PKT_signature *sig = node->pkt->pkt.signature;
|
||||
|
||||
blob->sigs[n] = 0; /* FIXME: check the signature here */
|
||||
n++;
|
||||
}
|
||||
}
|
||||
assert( n == blob->nsigs );
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
create_blob_header( KBXBLOB blob )
|
||||
{
|
||||
IOBUF a = blob->buf;
|
||||
int i;
|
||||
|
||||
put32 ( a, 0 ); /* blob length, needs fixup */
|
||||
put8 ( a, 2 ); /* blob type */
|
||||
put8 ( a, 1 ); /* blob type version */
|
||||
put16 ( a, 0 ); /* blob flags */
|
||||
|
||||
put32 ( a, 0 ); /* offset to the keyblock, needs fixup */
|
||||
put32 ( a, 0 ); /* length of the keyblock, needs fixup */
|
||||
|
||||
put16 ( a, blob->nkeys );
|
||||
put16 ( a, 20 + 4 + 2 + 2 ); /* size of key info */
|
||||
for ( i=0; i < blob->nkeys; i++ ) {
|
||||
putn ( a, blob->keys[i].fpr, 20 );
|
||||
blob->keys[i].off_kid_addr = iobuf_get_temp_length (a);
|
||||
put32 ( a, 0 ); /* offset to keyid, fixed up later */
|
||||
put16 ( a, blob->keys[i].flags );
|
||||
put16 ( a, 0 ); /* reserved */
|
||||
}
|
||||
|
||||
put16 ( a, blob->nuids );
|
||||
put16 ( a, 4 + 4 + 2 + 1 + 1 ); /* size of uid info */
|
||||
for ( i=0; i < blob->nuids; i++ ) {
|
||||
blob->uids[i].off_addr = iobuf_get_temp_length ( a );
|
||||
put32 ( a, 0 ); /* offset to userid, fixed up later */
|
||||
put32 ( a, blob->uids[i].len );
|
||||
put16 ( a, blob->uids[i].flags );
|
||||
put8 ( a, 0 ); /* validity */
|
||||
put8 ( a, 0 ); /* reserved */
|
||||
}
|
||||
|
||||
put16 ( a, blob->nsigs );
|
||||
put16 ( a, 4 ); /* size of sig info */
|
||||
for ( i=0; i < blob->nsigs; i++ ) {
|
||||
put32 ( a, blob->sigs[i] );
|
||||
}
|
||||
|
||||
put8 ( a, 0 ); /* assigned ownertrust */
|
||||
put8 ( a, 0 ); /* validity of all user IDs */
|
||||
put16 ( a, 0 ); /* reserved */
|
||||
put32 ( a, 0 ); /* time of next recheck */
|
||||
put32 ( a, 0 ); /* newest timestamp (none) */
|
||||
put32 ( a, make_timestamp() ); /* creation time */
|
||||
put32 ( a, 0 ); /* size of reserved space */
|
||||
/* reserved space (which is currently of size 0) */
|
||||
|
||||
/* We need to store the keyids for all v3 keys because those key IDs are
|
||||
* not part of the fingerprint. While we are doing that, we fixup all
|
||||
* the keyID offsets */
|
||||
for ( i=0; i < blob->nkeys; i++ ) {
|
||||
struct fixup_list *fl = gcry_xcalloc(1, sizeof *fl );
|
||||
fl->off = blob->keys[i].off_kid_addr;
|
||||
fl->next = blob->fixups;
|
||||
blob->fixups = fl;
|
||||
|
||||
if ( blob->keys[i].off_kid ) { /* this is a v3 one */
|
||||
fl->val = iobuf_get_temp_length (a);
|
||||
put_stored_kid ( blob, blob->keys[i].off_kid );
|
||||
}
|
||||
else { /* the better v4 key IDs - just store an offset 8 bytes back */
|
||||
fl->val = blob->keys[i].off_kid_addr-8;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
create_blob_keyblock( KBXBLOB blob, KBNODE keyblock )
|
||||
{
|
||||
IOBUF a = blob->buf;
|
||||
KBNODE node;
|
||||
int rc;
|
||||
int n;
|
||||
u32 kbstart = iobuf_get_temp_length ( a );
|
||||
|
||||
{
|
||||
struct fixup_list *fl = gcry_xcalloc(1, sizeof *fl );
|
||||
fl->off = 8;
|
||||
fl->val = kbstart;
|
||||
fl->next = blob->fixups;
|
||||
blob->fixups = fl;
|
||||
}
|
||||
for ( n = 0, node = keyblock; node; node = node->next ) {
|
||||
rc = build_packet ( a, node->pkt );
|
||||
if ( rc ) {
|
||||
gpg_log_error("build_packet(%d) for kbxblob failed: %s\n",
|
||||
node->pkt->pkttype, gpg_errstr(rc) );
|
||||
return GPGERR_WRITE_FILE;
|
||||
}
|
||||
if ( node->pkt->pkttype == PKT_USER_ID ) {
|
||||
PKT_user_id *u = node->pkt->pkt.user_id;
|
||||
/* build_packet has set the offset of the name into u ;
|
||||
* now we can do the fixup */
|
||||
struct fixup_list *fl = gcry_xcalloc(1, sizeof *fl );
|
||||
fl->off = blob->uids[n].off_addr;
|
||||
fl->val = u->stored_at;
|
||||
fl->next = blob->fixups;
|
||||
blob->fixups = fl;
|
||||
n++;
|
||||
}
|
||||
}
|
||||
assert( n == blob->nuids );
|
||||
{
|
||||
struct fixup_list *fl = gcry_xcalloc(1, sizeof *fl );
|
||||
fl->off = 12;
|
||||
fl->val = iobuf_get_temp_length (a) - kbstart;
|
||||
fl->next = blob->fixups;
|
||||
blob->fixups = fl;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
create_blob_trailer( KBXBLOB blob )
|
||||
{
|
||||
IOBUF a = blob->buf;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
create_blob_finish( KBXBLOB blob )
|
||||
{
|
||||
IOBUF a = blob->buf;
|
||||
byte *p;
|
||||
char *pp;
|
||||
int i;
|
||||
size_t n;
|
||||
|
||||
/* write a placeholder for the checksum */
|
||||
for ( i = 0; i < 16; i++ )
|
||||
put32( a, 0 );
|
||||
/* get the memory area */
|
||||
iobuf_flush_temp ( a );
|
||||
p = iobuf_get_temp_buffer ( a );
|
||||
n = iobuf_get_temp_length ( a );
|
||||
assert( n >= 20 );
|
||||
|
||||
/* fixup the length */
|
||||
{
|
||||
struct fixup_list *fl = gcry_xcalloc(1, sizeof *fl );
|
||||
fl->off = 0;
|
||||
fl->val = n;
|
||||
fl->next = blob->fixups;
|
||||
blob->fixups = fl;
|
||||
}
|
||||
/* do the fixups */
|
||||
{
|
||||
struct fixup_list *fl;
|
||||
for ( fl = blob->fixups; fl; fl = fl->next ) {
|
||||
assert( fl->off+4 <= n );
|
||||
p[fl->off+0] = fl->val >> 24 ;
|
||||
p[fl->off+1] = fl->val >> 16 ;
|
||||
p[fl->off+2] = fl->val >> 8 ;
|
||||
p[fl->off+3] = fl->val ;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* calculate and store the MD5 checksum */
|
||||
gcry_md_hash_buffer( GCRY_MD_MD5, p + n - 16, p, n - 16 );
|
||||
|
||||
pp = gcry_malloc ( n );
|
||||
if ( !pp )
|
||||
return GCRYERR_NO_MEM;
|
||||
memcpy ( pp , p, n );
|
||||
blob->blob = pp;
|
||||
blob->bloblen = n;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
kbx_create_blob ( KBXBLOB *r_blob, KBNODE keyblock )
|
||||
{
|
||||
int rc = 0;
|
||||
KBNODE node;
|
||||
KBXBLOB blob;
|
||||
|
||||
*r_blob = NULL;
|
||||
blob = gcry_xcalloc (1, sizeof *blob );
|
||||
if( !blob )
|
||||
return GCRYERR_NO_MEM;
|
||||
|
||||
/* fixme: Do some sanity checks on the keyblock */
|
||||
|
||||
/* count userids and keys so that we can allocate the arrays */
|
||||
for ( node = keyblock; node; node = node->next ) {
|
||||
switch ( node->pkt->pkttype ) {
|
||||
case PKT_PUBLIC_KEY:
|
||||
case PKT_SECRET_KEY:
|
||||
case PKT_PUBLIC_SUBKEY:
|
||||
case PKT_SECRET_SUBKEY: blob->nkeys++; break;
|
||||
case PKT_USER_ID: blob->nuids++; break;
|
||||
case PKT_SIGNATURE: blob->nsigs++; break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
blob->keys = gcry_xcalloc ( blob->nkeys, sizeof ( *blob->keys ) );
|
||||
blob->uids = gcry_xcalloc ( blob->nuids, sizeof ( *blob->uids ) );
|
||||
blob->sigs = gcry_xcalloc ( blob->nsigs, sizeof ( *blob->sigs ) );
|
||||
if ( !blob->keys || !blob->uids || !blob->sigs ) {
|
||||
rc = GCRYERR_NO_MEM;
|
||||
goto leave;
|
||||
}
|
||||
|
||||
rc = create_key_part ( blob, keyblock );
|
||||
if( rc )
|
||||
goto leave;
|
||||
rc = create_uid_part ( blob, keyblock );
|
||||
if( rc )
|
||||
goto leave;
|
||||
rc = create_sig_part ( blob, keyblock );
|
||||
if( rc )
|
||||
goto leave;
|
||||
|
||||
blob->buf = iobuf_temp();
|
||||
rc = create_blob_header ( blob );
|
||||
if( rc )
|
||||
goto leave;
|
||||
rc = create_blob_keyblock ( blob, keyblock );
|
||||
if( rc )
|
||||
goto leave;
|
||||
rc = create_blob_trailer ( blob );
|
||||
if( rc )
|
||||
goto leave;
|
||||
rc = create_blob_finish ( blob );
|
||||
if( rc )
|
||||
goto leave;
|
||||
|
||||
|
||||
leave:
|
||||
release_kid_list( blob->temp_kids );
|
||||
blob->temp_kids = NULL;
|
||||
if ( rc ) {
|
||||
kbx_release_blob ( blob );
|
||||
*r_blob = NULL;
|
||||
}
|
||||
else {
|
||||
*r_blob = blob;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
kbx_new_blob ( KBXBLOB *r_blob, char *image, size_t imagelen )
|
||||
{
|
||||
KBXBLOB blob;
|
||||
|
||||
*r_blob = NULL;
|
||||
blob = gcry_xcalloc (1, sizeof *blob );
|
||||
if( !blob )
|
||||
return GCRYERR_NO_MEM;
|
||||
blob->blob = image;
|
||||
blob->bloblen = imagelen;
|
||||
*r_blob = blob;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
const char *
|
||||
kbx_get_blob_image ( KBXBLOB blob, size_t *n )
|
||||
{
|
||||
*n = blob->bloblen;
|
||||
return blob->blob;
|
||||
}
|
||||
|
||||
void
|
||||
kbx_release_blob ( KBXBLOB blob )
|
||||
{
|
||||
if( !blob )
|
||||
return;
|
||||
if( blob->buf )
|
||||
iobuf_cancel( blob->buf );
|
||||
gcry_free( blob->keys );
|
||||
gcry_free( blob->uids );
|
||||
gcry_free( blob->sigs );
|
||||
|
||||
gcry_free ( blob->blob );
|
||||
|
||||
gcry_free( blob );
|
||||
}
|
||||
|
||||
static ulong
|
||||
get32( const byte *buffer )
|
||||
{
|
||||
ulong a;
|
||||
a = *buffer << 24;
|
||||
a |= buffer[1] << 16;
|
||||
a |= buffer[2] << 8;
|
||||
a |= buffer[3];
|
||||
return a;
|
||||
}
|
||||
|
||||
static ulong
|
||||
get16( const byte *buffer )
|
||||
{
|
||||
ulong a;
|
||||
a = *buffer << 8;
|
||||
a |= buffer[1];
|
||||
return a;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
kbx_dump_blob ( FILE *fp, KBXBLOB blob )
|
||||
{
|
||||
const byte *buffer = blob->blob;
|
||||
size_t length = blob->bloblen;
|
||||
ulong n, nkeys, keyinfolen;
|
||||
ulong nuids, uidinfolen;
|
||||
ulong nsigs, siginfolen;
|
||||
ulong keyblock_off, keyblock_len;
|
||||
const byte *p;
|
||||
|
||||
if( length < 40 ) {
|
||||
fprintf( fp, "blob too short\n");
|
||||
return -1;
|
||||
}
|
||||
n = get32( buffer );
|
||||
if( n > length ) {
|
||||
fprintf( fp, "blob larger than length - output truncated\n");
|
||||
}
|
||||
else
|
||||
length = n; /* ignore the rest */
|
||||
fprintf( fp, "Length: %lu\n", n );
|
||||
fprintf( fp, "Type: %d\n", buffer[4] );
|
||||
fprintf( fp, "Version: %d\n", buffer[5] );
|
||||
if( buffer[4] != 2 ) {
|
||||
fprintf( fp, "can't dump this blob type\n" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
n = get16( buffer + 6 );
|
||||
fprintf( fp, "Blob-Flags: %04lX\n", n );
|
||||
keyblock_off = get32( buffer + 8 );
|
||||
keyblock_len = get32( buffer + 12 );
|
||||
fprintf( fp, "Keyblock-Offset: %lu\n", keyblock_off );
|
||||
fprintf( fp, "Keyblock-Length: %lu\n", keyblock_len );
|
||||
|
||||
nkeys = get16( buffer + 16 );
|
||||
fprintf( fp, "Key-Count: %lu\n", nkeys );
|
||||
keyinfolen = get16( buffer + 18 );
|
||||
fprintf( fp, "Key-Info-Length: %lu\n", keyinfolen );
|
||||
/* fixme: check bounds */
|
||||
p = buffer + 20;
|
||||
for(n=0; n < nkeys; n++, p += keyinfolen ) {
|
||||
int i;
|
||||
ulong kidoff, kflags;
|
||||
|
||||
fprintf( fp, "Key-%lu-Fpr: ", n );
|
||||
for(i=0; i < 20; i++ )
|
||||
fprintf( fp, "%02X", p[i] );
|
||||
kidoff = get32( p + 20 );
|
||||
fprintf( fp, "\nKey-%lu-Kid-Off: %lu\n", n, kidoff );
|
||||
fprintf( fp, "Key-%lu-Kid: ", n );
|
||||
/* fixme: check bounds */
|
||||
for(i=0; i < 8; i++ )
|
||||
fprintf( fp, "%02X", buffer[kidoff+i] );
|
||||
kflags = get16( p + 24 );
|
||||
fprintf( fp, "\nKey-%lu-Flags: %04lX\n", n, kflags );
|
||||
}
|
||||
|
||||
|
||||
nuids = get16( p );
|
||||
fprintf( fp, "Uid-Count: %lu\n", nuids );
|
||||
uidinfolen = get16( p + 2 );
|
||||
fprintf( fp, "Uid-Info-Length: %lu\n", uidinfolen );
|
||||
/* fixme: check bounds */
|
||||
p += 4;
|
||||
for(n=0; n < nuids; n++, p += uidinfolen ) {
|
||||
ulong uidoff, uidlen, uflags;
|
||||
|
||||
uidoff = get32( p );
|
||||
uidlen = get32( p+4 );
|
||||
fprintf( fp, "Uid-%lu-Off: %lu\n", n, uidoff );
|
||||
fprintf( fp, "Uid-%lu-Len: %lu\n", n, uidlen );
|
||||
fprintf( fp, "Uid-%lu: \"", n );
|
||||
print_string( fp, buffer+uidoff, uidlen, '\"' );
|
||||
fputs("\"\n", fp );
|
||||
uflags = get16( p + 8 );
|
||||
fprintf( fp, "Uid-%lu-Flags: %04lX\n", n, uflags );
|
||||
fprintf( fp, "Uid-%lu-Validity: %d\n", n, p[10] );
|
||||
}
|
||||
|
||||
nsigs = get16( p );
|
||||
fprintf( fp, "Sig-Count: %lu\n", nsigs );
|
||||
siginfolen = get16( p + 2 );
|
||||
fprintf( fp, "Sig-Info-Length: %lu\n", siginfolen );
|
||||
/* fixme: check bounds */
|
||||
p += 4;
|
||||
for(n=0; n < nsigs; n++, p += siginfolen ) {
|
||||
ulong sflags;
|
||||
|
||||
sflags = get32( p );
|
||||
fprintf( fp, "Sig-%lu-Expire: ", n );
|
||||
if( !sflags )
|
||||
fputs( "[not checked]", fp );
|
||||
else if( sflags == 1 )
|
||||
fputs( "[missing key]", fp );
|
||||
else if( sflags == 2 )
|
||||
fputs( "[bad signature]", fp );
|
||||
else if( sflags < 0x10000000 )
|
||||
fprintf( fp, "[bad flag %0lx]", sflags );
|
||||
else if( sflags == 0xffffffff )
|
||||
fputs( "0", fp );
|
||||
else
|
||||
fputs( strtimestamp( sflags ), fp );
|
||||
putc('\n', fp );
|
||||
}
|
||||
|
||||
fprintf( fp, "Ownertrust: %d\n", p[0] );
|
||||
fprintf( fp, "All-Validity: %d\n", p[1] );
|
||||
p += 4;
|
||||
n = get32( p ); p += 4;
|
||||
fprintf( fp, "Recheck-After: %s\n", n? strtimestamp(n) : "0" );
|
||||
n = get32( p ); p += 4;
|
||||
fprintf( fp, "Latest-Timestamp: %s\n", strtimestamp(n) );
|
||||
n = get32( p ); p += 4;
|
||||
fprintf( fp, "Created-At: %s\n", strtimestamp(n) );
|
||||
n = get32( p ); p += 4;
|
||||
fprintf( fp, "Reserved-Space: %lu\n", n );
|
||||
|
||||
|
||||
/* check that the keyblock is at the correct offset and other bounds */
|
||||
|
||||
|
||||
fprintf( fp, "Blob-Checksum: [MD5-hash]\n" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************
|
||||
* Check whether the given fingerprint (20 bytes) is in the
|
||||
* given keyblob. fpr is always 20 bytes.
|
||||
* Return: 0 = found
|
||||
* -1 = not found
|
||||
other = error (fixme: do not always reurn gpgerr_general)
|
||||
*/
|
||||
int
|
||||
kbx_blob_has_fpr ( KBXBLOB blob, const byte *fpr )
|
||||
{
|
||||
ulong n, nkeys, keyinfolen;
|
||||
const byte *p, *pend;
|
||||
byte *buffer = blob->blob;
|
||||
size_t buflen = blob->bloblen;
|
||||
|
||||
if ( buflen < 40 )
|
||||
return GPGERR_GENERAL; /* blob too short */
|
||||
n = get32( buffer );
|
||||
if ( n > buflen )
|
||||
return GPGERR_GENERAL; /* blob larger than announced length */
|
||||
buflen = n; /* ignore trailing stuff */
|
||||
pend = buffer + n - 1;
|
||||
|
||||
if ( buffer[4] != 2 )
|
||||
return GPGERR_GENERAL; /* invalid blob type */
|
||||
if ( buffer[5] != 1 )
|
||||
return GPGERR_GENERAL; /* invalid blob format version */
|
||||
|
||||
nkeys = get16( buffer + 16 );
|
||||
keyinfolen = get16( buffer + 18 );
|
||||
p = buffer + 20;
|
||||
for(n=0; n < nkeys; n++, p += keyinfolen ) {
|
||||
if ( p+20 > pend )
|
||||
return GPGERR_GENERAL; /* blob shorter than required */
|
||||
if (!memcmp ( p, fpr, 20 ) )
|
||||
return 0; /* found */
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/****************
|
||||
* Check whether the given keyID (20 bytes) is in the
|
||||
* given keyblob.
|
||||
* Return: 0 = found
|
||||
* -1 = not found
|
||||
other = error (fixme: do not always return gpgerr_general)
|
||||
*/
|
||||
int
|
||||
kbx_blob_has_kid ( KBXBLOB blob, const byte *keyidbuf, size_t keyidlen )
|
||||
{
|
||||
ulong n, nkeys, keyinfolen, off;
|
||||
const byte *p, *pend;
|
||||
byte *buffer = blob->blob;
|
||||
size_t buflen = blob->bloblen;
|
||||
|
||||
if ( buflen < 40 )
|
||||
return GPGERR_GENERAL; /* blob too short */
|
||||
n = get32( buffer );
|
||||
if ( n > buflen )
|
||||
return GPGERR_GENERAL; /* blob larger than announced length */
|
||||
buflen = n; /* ignore trailing stuff */
|
||||
pend = buffer + n - 1;
|
||||
|
||||
if ( buffer[4] != 2 )
|
||||
return GPGERR_GENERAL; /* invalid blob type */
|
||||
if ( buffer[5] != 1 )
|
||||
return GPGERR_GENERAL; /* invalid blob format version */
|
||||
|
||||
nkeys = get16( buffer + 16 );
|
||||
keyinfolen = get16( buffer + 18 );
|
||||
p = buffer + 20;
|
||||
for(n=0; n < nkeys; n++, p += keyinfolen ) {
|
||||
if ( p+24 > pend )
|
||||
return GPGERR_GENERAL; /* blob shorter than required */
|
||||
off = get32 ( p + 20 );
|
||||
if (keyidlen < 8 ) /* actually keyidlen may either be 4 or 8 */
|
||||
off +=4;
|
||||
if ( off+keyidlen > buflen )
|
||||
return GPGERR_GENERAL; /* offset out of bounds */
|
||||
if ( !memcmp ( buffer+off, keyidbuf, keyidlen ) )
|
||||
return 0; /* found */
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
kbx_blob_has_uid ( KBXBLOB blob,
|
||||
int (*cmp)(const byte *, size_t, void *), void *opaque )
|
||||
{
|
||||
ulong n, nuids, uidinfolen, off, len;
|
||||
const byte *p, *pend;
|
||||
byte *buffer = blob->blob;
|
||||
size_t buflen = blob->bloblen;
|
||||
|
||||
if ( buflen < 40 )
|
||||
return GPGERR_GENERAL; /* blob too short */
|
||||
n = get32( buffer );
|
||||
if ( n > buflen )
|
||||
return GPGERR_GENERAL; /* blob larger than announced length */
|
||||
buflen = n; /* ignore trailing stuff */
|
||||
pend = buffer + n - 1;
|
||||
|
||||
if ( buffer[4] != 2 )
|
||||
return GPGERR_GENERAL; /* invalid blob type */
|
||||
if ( buffer[5] != 1 )
|
||||
return GPGERR_GENERAL; /* invalid blob format version */
|
||||
|
||||
p = buffer + 20 + get16( buffer + 16 ) * get16( buffer + 18 );
|
||||
if ( p+4 > pend )
|
||||
return GPGERR_GENERAL; /* blob shorter than required */
|
||||
|
||||
nuids = get16( p ); p+= 2;
|
||||
uidinfolen = get16( p ); p+=2;
|
||||
for(n=0; n < nuids; n++, p += uidinfolen ) {
|
||||
if ( p+8 > pend )
|
||||
return GPGERR_GENERAL; /* blob shorter than required */
|
||||
off = get32 ( p );
|
||||
len = get32 ( p + 4 );
|
||||
if ( off+len > buflen )
|
||||
return GPGERR_GENERAL; /* offset out of bounds */
|
||||
if ( (*cmp) ( buffer+off, len, opaque ) )
|
||||
return 0; /* found */
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
332
g10/kbxfile.c
332
g10/kbxfile.c
@ -1,332 +0,0 @@
|
||||
/* kbxfile.c - KBX file handling
|
||||
* Copyright (C) 2000 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
* GnuPG is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GnuPG is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
/****************
|
||||
* We will change the whole system to use only KBX. This file here
|
||||
* will implement the methods needed to operate on plain KBXfiles.
|
||||
* Most stuff from getkey and ringedit will be replaced by stuff here.
|
||||
* To make things even more easier we will only allow one updateable kbxfile
|
||||
* and optionally some read-only files.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
#include <gcrypt.h>
|
||||
|
||||
#include "kbx.h"
|
||||
#include "options.h"
|
||||
#include "util.h"
|
||||
#include "i18n.h"
|
||||
#include "main.h"
|
||||
|
||||
/****************
|
||||
* Read the blob at the current fileposition and return an allocated
|
||||
* pointer nto the blob if it was found.
|
||||
* Fixme: return a blob object.
|
||||
*/
|
||||
static int
|
||||
do_search_by_fpr ( const char *filename, FILE *a, const char *fpr,
|
||||
KBXBLOB *r_blob )
|
||||
{
|
||||
KBXBLOB blob;
|
||||
int rc;
|
||||
|
||||
*r_blob = NULL;
|
||||
rc = kbx_read_blob ( &blob, a );
|
||||
if ( rc && rc != -1 ) {
|
||||
log_error (_("file `%s': error reading blob\n"), filename );
|
||||
}
|
||||
else if ( !rc ) {
|
||||
rc = kbx_blob_has_fpr ( blob, fpr );
|
||||
}
|
||||
else
|
||||
log_info ("eof\n");
|
||||
|
||||
if ( !rc ) {
|
||||
*r_blob = blob;
|
||||
}
|
||||
else {
|
||||
kbx_release_blob ( blob );
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
kbxfile_search_by_fpr( const char *filename, const byte *fpr )
|
||||
{
|
||||
FILE *fp;
|
||||
KBXBLOB blob;
|
||||
int rc;
|
||||
|
||||
fp = fopen ( filename, "rb" );
|
||||
if( !fp ) {
|
||||
log_error(_("can't open `%s': %s\n"), filename, strerror(errno) );
|
||||
return 1;
|
||||
}
|
||||
|
||||
while ( (rc=do_search_by_fpr ( filename, fp, fpr, &blob )) == -1 )
|
||||
;
|
||||
if ( !rc ) {
|
||||
fputs ("FOUND\n", stderr );
|
||||
kbx_dump_blob ( stderr, blob );
|
||||
kbx_release_blob ( blob );
|
||||
}
|
||||
|
||||
fclose (fp);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
* Read the blob at the current fileposition and return an allocated
|
||||
* pointer nto the blob if it was found.
|
||||
* Fixme: return a blob object.
|
||||
*/
|
||||
static int
|
||||
do_search_by_keyid ( const char *filename, FILE *a,
|
||||
const byte *keyidbuf, size_t keyidlen, KBXBLOB *r_blob )
|
||||
{
|
||||
KBXBLOB blob;
|
||||
int rc;
|
||||
|
||||
*r_blob = NULL;
|
||||
rc = kbx_read_blob ( &blob, a );
|
||||
if ( rc && rc != -1 ) {
|
||||
log_error (_("file `%s': error reading blob\n"), filename );
|
||||
}
|
||||
else if ( !rc ) {
|
||||
rc = kbx_blob_has_kid ( blob, keyidbuf, keyidlen );
|
||||
}
|
||||
else
|
||||
rc = GPGERR_GENERAL; /* eof */
|
||||
|
||||
if ( !rc ) {
|
||||
*r_blob = blob;
|
||||
}
|
||||
else {
|
||||
kbx_release_blob ( blob );
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/****************
|
||||
* Look for a KBX described by an keyid. This function will in
|
||||
* turn return each matching keyid because there may me duplicates
|
||||
* (which can't happen for fingerprints)
|
||||
* mode 10 = short keyid
|
||||
* 11 = long keyid
|
||||
*/
|
||||
int
|
||||
kbxfile_search_by_kid ( const char *filename, u32 *kid, int mode )
|
||||
{
|
||||
FILE *fp;
|
||||
KBXBLOB blob;
|
||||
int rc;
|
||||
byte kbuf[8], *kbufptr;
|
||||
int kbuflen;
|
||||
|
||||
fp = fopen ( filename, "rb" );
|
||||
if( !fp ) {
|
||||
log_error(_("can't open `%s': %s\n"), filename, strerror(errno) );
|
||||
return 1;
|
||||
}
|
||||
|
||||
kbuf[0] = kid[0] >> 24;
|
||||
kbuf[1] = kid[0] >> 16;
|
||||
kbuf[2] = kid[0] >> 8;
|
||||
kbuf[3] = kid[0];
|
||||
kbuf[4] = kid[1] >> 24;
|
||||
kbuf[5] = kid[1] >> 16;
|
||||
kbuf[6] = kid[1] >> 8;
|
||||
kbuf[7] = kid[1];
|
||||
if ( mode == 10 ) {
|
||||
kbufptr=kbuf+4;
|
||||
kbuflen = 4;
|
||||
}
|
||||
else if (mode == 11 ) {
|
||||
kbufptr=kbuf;
|
||||
kbuflen = 8;
|
||||
}
|
||||
else {
|
||||
BUG();
|
||||
}
|
||||
|
||||
do {
|
||||
while ( (rc=do_search_by_keyid ( filename, fp,
|
||||
kbufptr, kbuflen, &blob )) == -1 )
|
||||
;
|
||||
if ( !rc ) {
|
||||
fputs ("FOUND:\n", stderr );
|
||||
kbx_dump_blob ( stderr, blob );
|
||||
kbx_release_blob ( blob );
|
||||
}
|
||||
} while ( !rc );
|
||||
|
||||
fclose (fp);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
do_search_by_uid ( const char *filename, FILE *a,
|
||||
int (*cmpfnc)(const byte*,size_t,void*), void *cmpdata,
|
||||
KBXBLOB *r_blob )
|
||||
{
|
||||
KBXBLOB blob;
|
||||
int rc;
|
||||
|
||||
*r_blob = NULL;
|
||||
rc = kbx_read_blob ( &blob, a );
|
||||
if ( rc && rc != -1 ) {
|
||||
log_error (_("file `%s': error reading blob\n"), filename );
|
||||
}
|
||||
else if ( !rc ) {
|
||||
rc = kbx_blob_has_uid ( blob, cmpfnc, cmpdata );
|
||||
}
|
||||
else
|
||||
rc = GPGERR_GENERAL; /* eof */
|
||||
|
||||
if ( !rc ) {
|
||||
*r_blob = blob;
|
||||
}
|
||||
else {
|
||||
kbx_release_blob ( blob );
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
substr_compare ( const byte *buf, size_t buflen, void *opaque )
|
||||
{
|
||||
return !!memistr ( buf, buflen, opaque );
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
kbxfile_search_by_uid ( const char *filename, const char *name )
|
||||
{
|
||||
FILE *fp;
|
||||
KBXBLOB blob;
|
||||
int rc;
|
||||
byte kbuf[8], *kbufptr;
|
||||
int kbuflen;
|
||||
|
||||
fp = fopen ( filename, "rb" );
|
||||
if( !fp ) {
|
||||
log_error(_("can't open `%s': %s\n"), filename, strerror(errno) );
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
do {
|
||||
while ( (rc=do_search_by_uid ( filename, fp,
|
||||
substr_compare, name, &blob )) == -1 )
|
||||
;
|
||||
if ( !rc ) {
|
||||
fputs ("FOUND:\n", stderr );
|
||||
kbx_dump_blob ( stderr, blob );
|
||||
kbx_release_blob ( blob );
|
||||
}
|
||||
} while ( !rc );
|
||||
|
||||
fclose ( fp );
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
export_as_kbxfile(void)
|
||||
{
|
||||
|
||||
KBPOS kbpos;
|
||||
KBNODE keyblock = NULL;
|
||||
int rc=0;
|
||||
|
||||
rc = enum_keyblocks_begin( &kbpos, 0 );
|
||||
if( rc ) {
|
||||
if( rc != -1 )
|
||||
log_error("enum_keyblocks(open) failed: %s\n", gpg_errstr(rc) );
|
||||
goto leave;
|
||||
}
|
||||
|
||||
while( !(rc = enum_keyblocks_next( kbpos, 1, &keyblock )) ) {
|
||||
KBXBLOB blob;
|
||||
const char *p;
|
||||
size_t n;
|
||||
|
||||
merge_keys_and_selfsig( keyblock );
|
||||
rc = kbx_create_blob ( &blob, keyblock );
|
||||
if( rc ) {
|
||||
log_error("kbx_create_blob failed: %s\n", gpg_errstr(rc) );
|
||||
goto leave;
|
||||
}
|
||||
p = kbx_get_blob_image ( blob, &n );
|
||||
fwrite( p, n, 1, stdout );
|
||||
kbx_release_blob ( blob );
|
||||
}
|
||||
|
||||
if( rc && rc != -1 )
|
||||
log_error("enum_keyblocks(read) failed: %s\n", gpg_errstr(rc));
|
||||
|
||||
leave:
|
||||
enum_keyblocks_end( kbpos );
|
||||
release_kbnode( keyblock );
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
do_print_kbxfile( const char *filename, FILE *a )
|
||||
{
|
||||
KBXBLOB blob;
|
||||
int rc;
|
||||
|
||||
rc = kbx_read_blob ( &blob, a );
|
||||
if ( rc && rc != -1 ) {
|
||||
log_error (_("file `%s': error reading blob\n"), filename );
|
||||
}
|
||||
else if ( ! rc )
|
||||
kbx_dump_blob ( stdout, blob );
|
||||
kbx_release_blob ( blob );
|
||||
return rc;
|
||||
}
|
||||
|
||||
void
|
||||
print_kbxfile( const char *filename )
|
||||
{
|
||||
FILE *fp;
|
||||
|
||||
fp = fopen ( filename, "rb" );
|
||||
if( !fp ) {
|
||||
log_error(_("can't open `%s': %s\n"), filename, strerror(errno) );
|
||||
return;
|
||||
}
|
||||
|
||||
while ( !do_print_kbxfile( filename, fp ) )
|
||||
;
|
||||
|
||||
fclose (fp);
|
||||
}
|
||||
|
75
g10/kbxio.c
75
g10/kbxio.c
@ -1,75 +0,0 @@
|
||||
/* kbxio.c - KBX I/O handling
|
||||
* Copyright (C) 2000 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
* GnuPG is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GnuPG is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
|
||||
#include <config.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
#include <gcrypt.h>
|
||||
|
||||
#include "iobuf.h"
|
||||
#include "util.h"
|
||||
#include "kbx.h"
|
||||
|
||||
|
||||
int
|
||||
kbx_read_blob ( KBXBLOB *r_blob, FILE *a )
|
||||
{
|
||||
char *image;
|
||||
size_t imagelen = 0;
|
||||
int c1, c2, c3, c4;
|
||||
int rc;
|
||||
|
||||
*r_blob = NULL;
|
||||
if ( (c1 = getc ( a )) == EOF
|
||||
|| (c2 = getc ( a )) == EOF
|
||||
|| (c3 = getc ( a )) == EOF
|
||||
|| (c4 = getc ( a )) == EOF ) {
|
||||
if ( c1 == EOF && !ferror ( a ) )
|
||||
return -1;
|
||||
return GPGERR_GENERAL;
|
||||
}
|
||||
imagelen = (c1 << 24) | (c2 << 16) | (c3 << 8 ) | c4;
|
||||
if ( imagelen > 500000 ) { /* sanity check:blob too large */
|
||||
return GPGERR_GENERAL;
|
||||
}
|
||||
else if ( imagelen < 4 ) { /* blobtoo short */
|
||||
return GPGERR_GENERAL;
|
||||
}
|
||||
image = gcry_malloc ( imagelen );
|
||||
if ( !image ) {
|
||||
return GPGERR_GENERAL;
|
||||
}
|
||||
|
||||
image[0] = c1; image[1] = c2; image[2] = c3; image[3] = c4;
|
||||
if ( fread ( image+4, imagelen-4, 1, a ) != 1 ) {
|
||||
gcry_free ( image );
|
||||
return GPGERR_GENERAL;
|
||||
}
|
||||
|
||||
rc = kbx_new_blob ( r_blob, image, imagelen );
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
|
442
g10/kbxutil.c
442
g10/kbxutil.c
@ -1,442 +0,0 @@
|
||||
/* gpg.c - The GnuPG utility (main for gpg)
|
||||
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
* GnuPG is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GnuPG is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <gcrypt.h>
|
||||
|
||||
#include "packet.h"
|
||||
#include "iobuf.h"
|
||||
#include "util.h"
|
||||
#include "main.h"
|
||||
#include "options.h"
|
||||
#include "keydb.h"
|
||||
#include "filter.h"
|
||||
#include "ttyio.h"
|
||||
#include "i18n.h"
|
||||
#include "gnupg-defs.h"
|
||||
#include "kbx.h"
|
||||
|
||||
|
||||
enum cmd_and_opt_values { aNull = 0,
|
||||
oArmor = 'a',
|
||||
aDetachedSign = 'b',
|
||||
aSym = 'c',
|
||||
aDecrypt = 'd',
|
||||
aEncr = 'e',
|
||||
oInteractive = 'i',
|
||||
oKOption = 'k',
|
||||
oDryRun = 'n',
|
||||
oOutput = 'o',
|
||||
oQuiet = 'q',
|
||||
oRecipient = 'r',
|
||||
aSign = 's',
|
||||
oTextmodeShort= 't',
|
||||
oUser = 'u',
|
||||
oVerbose = 'v',
|
||||
oCompress = 'z',
|
||||
oNotation = 'N',
|
||||
oBatch = 500,
|
||||
aClearsign,
|
||||
aStore,
|
||||
aKeygen,
|
||||
aSignEncr,
|
||||
aSignKey,
|
||||
aLSignKey,
|
||||
aListPackets,
|
||||
aEditKey,
|
||||
aDeleteKey,
|
||||
aDeleteSecretKey,
|
||||
aKMode,
|
||||
aKModeC,
|
||||
aImport,
|
||||
aFastImport,
|
||||
aVerify,
|
||||
aListKeys,
|
||||
aListSigs,
|
||||
aListSecretKeys,
|
||||
aSendKeys,
|
||||
aRecvKeys,
|
||||
aExport,
|
||||
aExportAll,
|
||||
aExportSecret,
|
||||
aCheckKeys,
|
||||
aGenRevoke,
|
||||
aPrimegen,
|
||||
aPrintMD,
|
||||
aPrintHMAC,
|
||||
aPrintMDs,
|
||||
aCheckTrustDB,
|
||||
aUpdateTrustDB,
|
||||
aFixTrustDB,
|
||||
aListTrustDB,
|
||||
aListTrustPath,
|
||||
aExportOwnerTrust,
|
||||
aImportOwnerTrust,
|
||||
aDeArmor,
|
||||
aEnArmor,
|
||||
aGenRandom,
|
||||
|
||||
oTextmode,
|
||||
oFingerprint,
|
||||
oWithFingerprint,
|
||||
oAnswerYes,
|
||||
oAnswerNo,
|
||||
oKeyring,
|
||||
oSecretKeyring,
|
||||
oDefaultKey,
|
||||
oDefRecipient,
|
||||
oDefRecipientSelf,
|
||||
oNoDefRecipient,
|
||||
oOptions,
|
||||
oDebug,
|
||||
oDebugAll,
|
||||
oStatusFD,
|
||||
oNoComment,
|
||||
oNoVersion,
|
||||
oEmitVersion,
|
||||
oCompletesNeeded,
|
||||
oMarginalsNeeded,
|
||||
oMaxCertDepth,
|
||||
oLoadExtension,
|
||||
oRFC1991,
|
||||
oOpenPGP,
|
||||
oCipherAlgo,
|
||||
oDigestAlgo,
|
||||
oCompressAlgo,
|
||||
oPasswdFD,
|
||||
oNoVerbose,
|
||||
oTrustDBName,
|
||||
oNoSecmemWarn,
|
||||
oNoArmor,
|
||||
oNoDefKeyring,
|
||||
oNoGreeting,
|
||||
oNoTTY,
|
||||
oNoOptions,
|
||||
oNoBatch,
|
||||
oHomedir,
|
||||
oWithColons,
|
||||
oWithKeyData,
|
||||
oSkipVerify,
|
||||
oCompressKeys,
|
||||
oCompressSigs,
|
||||
oAlwaysTrust,
|
||||
oEmuChecksumBug,
|
||||
oRunAsShmCP,
|
||||
oSetFilename,
|
||||
oSetPolicyURL,
|
||||
oUseEmbeddedFilename,
|
||||
oComment,
|
||||
oDefaultComment,
|
||||
oThrowKeyid,
|
||||
oForceV3Sigs,
|
||||
oForceMDC,
|
||||
oS2KMode,
|
||||
oS2KDigest,
|
||||
oS2KCipher,
|
||||
oCharset,
|
||||
oNotDashEscaped,
|
||||
oEscapeFrom,
|
||||
oLockOnce,
|
||||
oLockMultiple,
|
||||
oKeyServer,
|
||||
oEncryptTo,
|
||||
oNoEncryptTo,
|
||||
oLoggerFD,
|
||||
oUtf8Strings,
|
||||
oNoUtf8Strings,
|
||||
oDisableCipherAlgo,
|
||||
oDisablePubkeyAlgo,
|
||||
oAllowNonSelfsignedUID,
|
||||
oNoLiteral,
|
||||
oSetFilesize,
|
||||
oEntropyDLLName,
|
||||
|
||||
aFindByFpr,
|
||||
aFindByKid,
|
||||
aFindByUid,
|
||||
aTest };
|
||||
|
||||
|
||||
static ARGPARSE_OPTS opts[] = {
|
||||
|
||||
{ 300, NULL, 0, N_("@Commands:\n ") },
|
||||
|
||||
{ aFindByFpr, "find-by-fpr", 0, "|FPR| find key using it's fingerprnt" },
|
||||
{ aFindByKid, "find-by-kid", 0, "|KID| find key using it's keyid" },
|
||||
{ aFindByUid, "find-by-uid", 0, "|NAME| find key by user name" },
|
||||
|
||||
{ 301, NULL, 0, N_("@\nOptions:\n ") },
|
||||
|
||||
{ oArmor, "armor", 0, N_("create ascii armored output")},
|
||||
{ oArmor, "armour", 0, "@" },
|
||||
{ oCompress, NULL, 1, N_("|N|set compress level N (0 disables)") },
|
||||
{ oOutput, "output", 2, N_("use as output file")},
|
||||
{ oVerbose, "verbose", 0, N_("verbose") },
|
||||
{ oQuiet, "quiet", 0, N_("be somewhat more quiet") },
|
||||
{ oDryRun, "dry-run", 0, N_("do not make any changes") },
|
||||
{ oOptions, "options" , 2, N_("read options from file")},
|
||||
|
||||
{ oDebug, "debug" ,4|16, N_("set debugging flags")},
|
||||
{ oDebugAll, "debug-all" ,0, N_("enable full debugging")},
|
||||
|
||||
|
||||
{0} };
|
||||
|
||||
|
||||
|
||||
int gpg_errors_seen = 0;
|
||||
|
||||
|
||||
static const char *
|
||||
my_strusage( int level )
|
||||
{
|
||||
const char *p;
|
||||
switch( level ) {
|
||||
case 11: p = "kbxutil (GnuPG)";
|
||||
break;
|
||||
case 13: p = VERSION; break;
|
||||
case 17: p = PRINTABLE_OS_NAME; break;
|
||||
case 19: p =
|
||||
_("Please report bugs to <gnupg-bugs@gnu.org>.\n");
|
||||
break;
|
||||
case 1:
|
||||
case 40: p =
|
||||
_("Usage: kbxutil [options] [files] (-h for help)");
|
||||
break;
|
||||
case 41: p =
|
||||
_("Syntax: kbxutil [options] [files]\n"
|
||||
"list, export, import KBX data\n");
|
||||
break;
|
||||
|
||||
|
||||
default: p = NULL;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
i18n_init(void)
|
||||
{
|
||||
#ifdef USE_SIMPLE_GETTEXT
|
||||
set_gettext_file( PACKAGE );
|
||||
#else
|
||||
#ifdef ENABLE_NLS
|
||||
#ifdef HAVE_LC_MESSAGES
|
||||
setlocale( LC_TIME, "" );
|
||||
setlocale( LC_MESSAGES, "" );
|
||||
#else
|
||||
setlocale( LC_ALL, "" );
|
||||
#endif
|
||||
bindtextdomain( PACKAGE, GNUPG_LOCALEDIR );
|
||||
textdomain( PACKAGE );
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
wrong_args( const char *text )
|
||||
{
|
||||
log_error("usage: kbxutil %s\n", text);
|
||||
gpg_exit ( 1 );
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
hextobyte( const byte *s )
|
||||
{
|
||||
int c;
|
||||
|
||||
if( *s >= '0' && *s <= '9' )
|
||||
c = 16 * (*s - '0');
|
||||
else if( *s >= 'A' && *s <= 'F' )
|
||||
c = 16 * (10 + *s - 'A');
|
||||
else if( *s >= 'a' && *s <= 'f' )
|
||||
c = 16 * (10 + *s - 'a');
|
||||
else
|
||||
return -1;
|
||||
s++;
|
||||
if( *s >= '0' && *s <= '9' )
|
||||
c += *s - '0';
|
||||
else if( *s >= 'A' && *s <= 'F' )
|
||||
c += 10 + *s - 'A';
|
||||
else if( *s >= 'a' && *s <= 'f' )
|
||||
c += 10 + *s - 'a';
|
||||
else
|
||||
return -1;
|
||||
return c;
|
||||
}
|
||||
|
||||
static char *
|
||||
format_fingerprint ( const char *s )
|
||||
{
|
||||
int i, c;
|
||||
byte fpr[20];
|
||||
|
||||
for (i=0; i < 20 && *s; ) {
|
||||
if ( *s == ' ' || *s == '\t' ) {
|
||||
s++;
|
||||
continue;
|
||||
}
|
||||
c = hextobyte(s);
|
||||
if (c == -1) {
|
||||
return NULL;
|
||||
}
|
||||
fpr[i++] = c;
|
||||
s += 2;
|
||||
}
|
||||
return gcry_xstrdup ( fpr );
|
||||
}
|
||||
|
||||
static int
|
||||
format_keyid ( const char *s, u32 *kid )
|
||||
{
|
||||
char helpbuf[9];
|
||||
switch ( strlen ( s ) ) {
|
||||
case 8:
|
||||
kid[0] = 0;
|
||||
kid[1] = strtoul( s, NULL, 16 );
|
||||
return 10;
|
||||
|
||||
case 16:
|
||||
mem2str( helpbuf, s, 9 );
|
||||
kid[0] = strtoul( helpbuf, NULL, 16 );
|
||||
kid[1] = strtoul( s+8, NULL, 16 );
|
||||
return 11;
|
||||
}
|
||||
return 0; /* error */
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
main( int argc, char **argv )
|
||||
{
|
||||
ARGPARSE_ARGS pargs;
|
||||
enum cmd_and_opt_values cmd = 0;
|
||||
|
||||
set_strusage( my_strusage );
|
||||
log_set_name("kbxutil");
|
||||
/* check that the libraries are suitable. Do it here because
|
||||
* the option parse may need services of the library */
|
||||
if ( !gcry_check_version ( "1.1.0a" ) ) {
|
||||
log_fatal(_("libgcrypt is too old (need %s, have %s)\n"),
|
||||
VERSION, gcry_check_version(NULL) );
|
||||
}
|
||||
|
||||
create_dotlock(NULL); /* register locking cleanup */
|
||||
i18n_init();
|
||||
|
||||
|
||||
pargs.argc = &argc;
|
||||
pargs.argv = &argv;
|
||||
pargs.flags= 1; /* do not remove the args */
|
||||
while( arg_parse( &pargs, opts) ) {
|
||||
switch( pargs.r_opt ) {
|
||||
case oVerbose:
|
||||
opt.verbose++;
|
||||
gcry_control( GCRYCTL_SET_VERBOSITY, (int)opt.verbose );
|
||||
break;
|
||||
case oDebug: opt.debug |= pargs.r.ret_ulong; break;
|
||||
case oDebugAll: opt.debug = ~0; break;
|
||||
|
||||
case aFindByFpr:
|
||||
case aFindByKid:
|
||||
case aFindByUid:
|
||||
cmd = pargs.r_opt;
|
||||
break;
|
||||
|
||||
default : pargs.err = 2; break;
|
||||
}
|
||||
}
|
||||
if( log_get_errorcount(0) )
|
||||
gpg_exit(2);
|
||||
|
||||
if ( !cmd ) { /* default is to list a KBX file */
|
||||
if( !argc ) {
|
||||
print_kbxfile( NULL );
|
||||
}
|
||||
else {
|
||||
for ( ; argc; argc--, argv++ ) {
|
||||
print_kbxfile( *argv );
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( cmd == aFindByFpr ) {
|
||||
char *fpr;
|
||||
if ( argc != 2 )
|
||||
wrong_args ("kbxfile foingerprint");
|
||||
fpr = format_fingerprint ( argv[1] );
|
||||
if ( !fpr )
|
||||
log_error ("invalid formatted fingerprint\n");
|
||||
else {
|
||||
kbxfile_search_by_fpr ( argv[0], fpr );
|
||||
gcry_free ( fpr );
|
||||
}
|
||||
}
|
||||
else if ( cmd == aFindByKid ) {
|
||||
u32 kid[2];
|
||||
int mode;
|
||||
|
||||
if ( argc != 2 )
|
||||
wrong_args ("kbxfile short-or-long-keyid");
|
||||
mode = format_keyid ( argv[1], kid );
|
||||
if ( !mode )
|
||||
log_error ("invalid formatted keyID\n");
|
||||
else {
|
||||
kbxfile_search_by_kid ( argv[0], kid, mode );
|
||||
}
|
||||
}
|
||||
else if ( cmd == aFindByUid ) {
|
||||
if ( argc != 2 )
|
||||
wrong_args ("kbxfile userID");
|
||||
kbxfile_search_by_uid ( argv[0], argv[1] );
|
||||
}
|
||||
else
|
||||
log_error ("unsupported action\n");
|
||||
|
||||
gpg_exit(0);
|
||||
return 8; /*NEVER REACHED*/
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
gpg_exit( int rc )
|
||||
{
|
||||
if( opt.debug & DBG_MEMSTAT_VALUE ) {
|
||||
gcry_control( GCRYCTL_DUMP_MEMORY_STATS );
|
||||
gcry_control( GCRYCTL_DUMP_RANDOM_STATS );
|
||||
}
|
||||
if( opt.debug )
|
||||
gcry_control( GCRYCTL_DUMP_SECMEM_STATS );
|
||||
rc = rc? rc : log_get_errorcount(0)? 2 :
|
||||
gpg_errors_seen? 1 : 0;
|
||||
exit(rc );
|
||||
}
|
||||
|
||||
|
698
g10/keydb.c
Normal file
698
g10/keydb.c
Normal file
@ -0,0 +1,698 @@
|
||||
/* keydb.c - key database dispatcher
|
||||
* Copyright (C) 2001, 2002 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
* GnuPG is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GnuPG is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "util.h"
|
||||
#include "options.h"
|
||||
#include "main.h" /*try_make_homedir ()*/
|
||||
#include "packet.h"
|
||||
#include "keyring.h"
|
||||
#include "keydb.h"
|
||||
#include "i18n.h"
|
||||
|
||||
static int active_handles;
|
||||
|
||||
typedef enum {
|
||||
KEYDB_RESOURCE_TYPE_NONE = 0,
|
||||
KEYDB_RESOURCE_TYPE_KEYRING
|
||||
} KeydbResourceType;
|
||||
#define MAX_KEYDB_RESOURCES 20
|
||||
|
||||
struct resource_item {
|
||||
KeydbResourceType type;
|
||||
union {
|
||||
KEYRING_HANDLE kr;
|
||||
} u;
|
||||
void *token;
|
||||
int secret;
|
||||
};
|
||||
|
||||
static struct resource_item all_resources[MAX_KEYDB_RESOURCES];
|
||||
static int used_resources;
|
||||
|
||||
struct keydb_handle {
|
||||
int locked;
|
||||
int found;
|
||||
int current;
|
||||
int used; /* items in active */
|
||||
struct resource_item active[MAX_KEYDB_RESOURCES];
|
||||
};
|
||||
|
||||
|
||||
static int lock_all (KEYDB_HANDLE hd);
|
||||
static void unlock_all (KEYDB_HANDLE hd);
|
||||
|
||||
|
||||
/*
|
||||
* Register a resource (which currently may only be a keyring file).
|
||||
* The first keyring which is added by this function is
|
||||
* created if it does not exist.
|
||||
* Note: this function may be called before secure memory is
|
||||
* available.
|
||||
*/
|
||||
int
|
||||
keydb_add_resource (const char *url, int force, int secret)
|
||||
{
|
||||
static int any_secret, any_public;
|
||||
const char *resname = url;
|
||||
IOBUF iobuf = NULL;
|
||||
char *filename = NULL;
|
||||
int rc = 0;
|
||||
KeydbResourceType rt = KEYDB_RESOURCE_TYPE_NONE;
|
||||
void *token;
|
||||
|
||||
/* Do we have an URL?
|
||||
* gnupg-ring:filename := this is a plain keyring
|
||||
* filename := See what is is, but create as plain keyring.
|
||||
*/
|
||||
if (strlen (resname) > 11) {
|
||||
if (!strncmp( resname, "gnupg-ring:", 11) ) {
|
||||
rt = KEYDB_RESOURCE_TYPE_KEYRING;
|
||||
resname += 11;
|
||||
}
|
||||
#if !defined(HAVE_DRIVE_LETTERS) && !defined(__riscos__)
|
||||
else if (strchr (resname, ':')) {
|
||||
log_error ("invalid key resource URL `%s'\n", url );
|
||||
rc = G10ERR_GENERAL;
|
||||
goto leave;
|
||||
}
|
||||
#endif /* !HAVE_DRIVE_LETTERS && !__riscos__ */
|
||||
}
|
||||
|
||||
if (*resname != DIRSEP_C ) { /* do tilde expansion etc */
|
||||
if (strchr(resname, DIRSEP_C) )
|
||||
filename = make_filename (resname, NULL);
|
||||
else
|
||||
filename = make_filename (opt.homedir, resname, NULL);
|
||||
}
|
||||
else
|
||||
filename = m_strdup (resname);
|
||||
|
||||
check_permissions(filename,0,0);
|
||||
|
||||
if (!force)
|
||||
force = secret? !any_secret : !any_public;
|
||||
|
||||
/* see whether we can determine the filetype */
|
||||
if (rt == KEYDB_RESOURCE_TYPE_NONE) {
|
||||
FILE *fp = fopen( filename, "rb" );
|
||||
|
||||
if (fp) {
|
||||
u32 magic;
|
||||
|
||||
if (fread( &magic, 4, 1, fp) == 1 ) {
|
||||
if (magic == 0x13579ace || magic == 0xce9a5713)
|
||||
; /* GDBM magic - no more support */
|
||||
else
|
||||
rt = KEYDB_RESOURCE_TYPE_KEYRING;
|
||||
}
|
||||
else /* maybe empty: assume ring */
|
||||
rt = KEYDB_RESOURCE_TYPE_KEYRING;
|
||||
fclose( fp );
|
||||
}
|
||||
else /* no file yet: create ring */
|
||||
rt = KEYDB_RESOURCE_TYPE_KEYRING;
|
||||
}
|
||||
|
||||
switch (rt) {
|
||||
case KEYDB_RESOURCE_TYPE_NONE:
|
||||
log_error ("unknown type of key resource `%s'\n", url );
|
||||
rc = G10ERR_GENERAL;
|
||||
goto leave;
|
||||
|
||||
case KEYDB_RESOURCE_TYPE_KEYRING:
|
||||
if (access(filename, F_OK))
|
||||
{ /* file does not exist */
|
||||
char *last_slash_in_filename;
|
||||
|
||||
if (!force)
|
||||
{
|
||||
rc = G10ERR_OPEN_FILE;
|
||||
goto leave;
|
||||
}
|
||||
|
||||
last_slash_in_filename = strrchr (filename, DIRSEP_C);
|
||||
*last_slash_in_filename = 0;
|
||||
if (access(filename, F_OK))
|
||||
{ /* on the first time we try to create the default
|
||||
homedir and in this case the process will be
|
||||
terminated, so that on the next invocation it can
|
||||
read the options file in on startup */
|
||||
try_make_homedir (filename);
|
||||
rc = G10ERR_OPEN_FILE;
|
||||
*last_slash_in_filename = DIRSEP_C;
|
||||
goto leave;
|
||||
}
|
||||
*last_slash_in_filename = DIRSEP_C;
|
||||
|
||||
iobuf = iobuf_create (filename);
|
||||
if (!iobuf)
|
||||
{
|
||||
log_error ( _("error creating keyring `%s': %s\n"),
|
||||
filename, strerror(errno));
|
||||
rc = G10ERR_OPEN_FILE;
|
||||
goto leave;
|
||||
}
|
||||
|
||||
#ifndef HAVE_DOSISH_SYSTEM
|
||||
if (secret && !opt.preserve_permissions)
|
||||
{
|
||||
if (chmod (filename, S_IRUSR | S_IWUSR) )
|
||||
{
|
||||
log_error (_("changing permission of "
|
||||
" `%s' failed: %s\n"),
|
||||
filename, strerror(errno) );
|
||||
rc = G10ERR_WRITE_FILE;
|
||||
goto leave;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (!opt.quiet)
|
||||
log_info (_("keyring `%s' created\n"), filename);
|
||||
iobuf_close (iobuf);
|
||||
iobuf = NULL;
|
||||
/* must invalidate that ugly cache */
|
||||
iobuf_ioctl (NULL, 2, 0, (char*)filename);
|
||||
} /* end file creation */
|
||||
|
||||
token = keyring_register_filename (filename, secret);
|
||||
if (!token)
|
||||
; /* already registered - ignore it */
|
||||
else if (used_resources >= MAX_KEYDB_RESOURCES)
|
||||
rc = G10ERR_RESOURCE_LIMIT;
|
||||
else
|
||||
{
|
||||
all_resources[used_resources].type = rt;
|
||||
all_resources[used_resources].u.kr = NULL; /* Not used here */
|
||||
all_resources[used_resources].token = token;
|
||||
all_resources[used_resources].secret = secret;
|
||||
used_resources++;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
log_error ("resource type of `%s' not supported\n", url);
|
||||
rc = G10ERR_GENERAL;
|
||||
goto leave;
|
||||
}
|
||||
|
||||
/* fixme: check directory permissions and print a warning */
|
||||
|
||||
leave:
|
||||
if (rc)
|
||||
log_error ("keyblock resource `%s': %s\n", filename, g10_errstr(rc));
|
||||
else if (secret)
|
||||
any_secret = 1;
|
||||
else
|
||||
any_public = 1;
|
||||
m_free (filename);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
KEYDB_HANDLE
|
||||
keydb_new (int secret)
|
||||
{
|
||||
KEYDB_HANDLE hd;
|
||||
int i, j;
|
||||
|
||||
hd = m_alloc_clear (sizeof *hd);
|
||||
hd->found = -1;
|
||||
|
||||
assert (used_resources <= MAX_KEYDB_RESOURCES);
|
||||
for (i=j=0; i < used_resources; i++)
|
||||
{
|
||||
if (!all_resources[i].secret != !secret)
|
||||
continue;
|
||||
switch (all_resources[i].type)
|
||||
{
|
||||
case KEYDB_RESOURCE_TYPE_NONE: /* ignore */
|
||||
break;
|
||||
case KEYDB_RESOURCE_TYPE_KEYRING:
|
||||
hd->active[j].type = all_resources[i].type;
|
||||
hd->active[j].token = all_resources[i].token;
|
||||
hd->active[j].secret = all_resources[i].secret;
|
||||
hd->active[j].u.kr = keyring_new (all_resources[i].token, secret);
|
||||
if (!hd->active[j].u.kr) {
|
||||
m_free (hd);
|
||||
return NULL; /* fixme: release all previously allocated handles*/
|
||||
}
|
||||
j++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
hd->used = j;
|
||||
|
||||
active_handles++;
|
||||
return hd;
|
||||
}
|
||||
|
||||
void
|
||||
keydb_release (KEYDB_HANDLE hd)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!hd)
|
||||
return;
|
||||
assert (active_handles > 0);
|
||||
active_handles--;
|
||||
|
||||
unlock_all (hd);
|
||||
for (i=0; i < hd->used; i++) {
|
||||
switch (hd->active[i].type) {
|
||||
case KEYDB_RESOURCE_TYPE_NONE:
|
||||
break;
|
||||
case KEYDB_RESOURCE_TYPE_KEYRING:
|
||||
keyring_release (hd->active[i].u.kr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
m_free (hd);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Return the name of the current resource. This is function first
|
||||
* looks for the last found found, then for the current search
|
||||
* position, and last returns the first available resource. The
|
||||
* returned string is only valid as long as the handle exists. This
|
||||
* function does only return NULL if no handle is specified, in all
|
||||
* other error cases an empty string is returned.
|
||||
*/
|
||||
const char *
|
||||
keydb_get_resource_name (KEYDB_HANDLE hd)
|
||||
{
|
||||
int idx;
|
||||
const char *s = NULL;
|
||||
|
||||
if (!hd)
|
||||
return NULL;
|
||||
|
||||
if ( hd->found >= 0 && hd->found < hd->used)
|
||||
idx = hd->found;
|
||||
else if ( hd->current >= 0 && hd->current < hd->used)
|
||||
idx = hd->current;
|
||||
else
|
||||
idx = 0;
|
||||
|
||||
switch (hd->active[idx].type) {
|
||||
case KEYDB_RESOURCE_TYPE_NONE:
|
||||
s = NULL;
|
||||
break;
|
||||
case KEYDB_RESOURCE_TYPE_KEYRING:
|
||||
s = keyring_get_resource_name (hd->active[idx].u.kr);
|
||||
break;
|
||||
}
|
||||
|
||||
return s? s: "";
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int
|
||||
lock_all (KEYDB_HANDLE hd)
|
||||
{
|
||||
int i, rc = 0;
|
||||
|
||||
for (i=0; !rc && i < hd->used; i++) {
|
||||
switch (hd->active[i].type) {
|
||||
case KEYDB_RESOURCE_TYPE_NONE:
|
||||
break;
|
||||
case KEYDB_RESOURCE_TYPE_KEYRING:
|
||||
rc = keyring_lock (hd->active[i].u.kr, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (rc) {
|
||||
/* revert the already set locks */
|
||||
for (i--; i >= 0; i--) {
|
||||
switch (hd->active[i].type) {
|
||||
case KEYDB_RESOURCE_TYPE_NONE:
|
||||
break;
|
||||
case KEYDB_RESOURCE_TYPE_KEYRING:
|
||||
keyring_lock (hd->active[i].u.kr, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
hd->locked = 1;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void
|
||||
unlock_all (KEYDB_HANDLE hd)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!hd->locked)
|
||||
return;
|
||||
|
||||
for (i=hd->used-1; i >= 0; i--) {
|
||||
switch (hd->active[i].type) {
|
||||
case KEYDB_RESOURCE_TYPE_NONE:
|
||||
break;
|
||||
case KEYDB_RESOURCE_TYPE_KEYRING:
|
||||
keyring_lock (hd->active[i].u.kr, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
hd->locked = 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Return the last found keyring. Caller must free it.
|
||||
* The returned keyblock has the kbode flag bit 0 set for the node with
|
||||
* the public key used to locate the keyblock or flag bit 1 set for
|
||||
* the user ID node.
|
||||
*/
|
||||
int
|
||||
keydb_get_keyblock (KEYDB_HANDLE hd, KBNODE *ret_kb)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (!hd)
|
||||
return G10ERR_INV_ARG;
|
||||
|
||||
if ( hd->found < 0 || hd->found >= hd->used)
|
||||
return -1; /* nothing found */
|
||||
|
||||
switch (hd->active[hd->found].type) {
|
||||
case KEYDB_RESOURCE_TYPE_NONE:
|
||||
rc = G10ERR_GENERAL; /* oops */
|
||||
break;
|
||||
case KEYDB_RESOURCE_TYPE_KEYRING:
|
||||
rc = keyring_get_keyblock (hd->active[hd->found].u.kr, ret_kb);
|
||||
break;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* update the current keyblock with KB
|
||||
*/
|
||||
int
|
||||
keydb_update_keyblock (KEYDB_HANDLE hd, KBNODE kb)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (!hd)
|
||||
return G10ERR_INV_ARG;
|
||||
|
||||
if ( hd->found < 0 || hd->found >= hd->used)
|
||||
return -1; /* nothing found */
|
||||
|
||||
if( opt.dry_run )
|
||||
return 0;
|
||||
|
||||
rc = lock_all (hd);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
switch (hd->active[hd->found].type) {
|
||||
case KEYDB_RESOURCE_TYPE_NONE:
|
||||
rc = G10ERR_GENERAL; /* oops */
|
||||
break;
|
||||
case KEYDB_RESOURCE_TYPE_KEYRING:
|
||||
rc = keyring_update_keyblock (hd->active[hd->found].u.kr, kb);
|
||||
break;
|
||||
}
|
||||
|
||||
unlock_all (hd);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Insert a new KB into one of the resources.
|
||||
*/
|
||||
int
|
||||
keydb_insert_keyblock (KEYDB_HANDLE hd, KBNODE kb)
|
||||
{
|
||||
int rc = -1;
|
||||
int idx;
|
||||
|
||||
if (!hd)
|
||||
return G10ERR_INV_ARG;
|
||||
|
||||
if( opt.dry_run )
|
||||
return 0;
|
||||
|
||||
if ( hd->found >= 0 && hd->found < hd->used)
|
||||
idx = hd->found;
|
||||
else if ( hd->current >= 0 && hd->current < hd->used)
|
||||
idx = hd->current;
|
||||
else
|
||||
return G10ERR_GENERAL;
|
||||
|
||||
rc = lock_all (hd);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
switch (hd->active[idx].type) {
|
||||
case KEYDB_RESOURCE_TYPE_NONE:
|
||||
rc = G10ERR_GENERAL; /* oops */
|
||||
break;
|
||||
case KEYDB_RESOURCE_TYPE_KEYRING:
|
||||
rc = keyring_insert_keyblock (hd->active[idx].u.kr, kb);
|
||||
break;
|
||||
}
|
||||
|
||||
unlock_all (hd);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The current keyblock will be deleted.
|
||||
*/
|
||||
int
|
||||
keydb_delete_keyblock (KEYDB_HANDLE hd)
|
||||
{
|
||||
int rc = -1;
|
||||
|
||||
if (!hd)
|
||||
return G10ERR_INV_ARG;
|
||||
|
||||
if ( hd->found < 0 || hd->found >= hd->used)
|
||||
return -1; /* nothing found */
|
||||
|
||||
if( opt.dry_run )
|
||||
return 0;
|
||||
|
||||
rc = lock_all (hd);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
switch (hd->active[hd->found].type) {
|
||||
case KEYDB_RESOURCE_TYPE_NONE:
|
||||
rc = G10ERR_GENERAL; /* oops */
|
||||
break;
|
||||
case KEYDB_RESOURCE_TYPE_KEYRING:
|
||||
rc = keyring_delete_keyblock (hd->active[hd->found].u.kr);
|
||||
break;
|
||||
}
|
||||
|
||||
unlock_all (hd);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Locate the default writable key resource, so that the next
|
||||
* operation (which is only relevant for inserts) will be done on this
|
||||
* resource.
|
||||
*/
|
||||
int
|
||||
keydb_locate_writable (KEYDB_HANDLE hd, const char *reserved)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if (!hd)
|
||||
return G10ERR_INV_ARG;
|
||||
|
||||
rc = keydb_search_reset (hd); /* this does reset hd->current */
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
for ( ; hd->current >= 0 && hd->current < hd->used; hd->current++)
|
||||
{
|
||||
switch (hd->active[hd->current].type)
|
||||
{
|
||||
case KEYDB_RESOURCE_TYPE_NONE:
|
||||
BUG();
|
||||
break;
|
||||
case KEYDB_RESOURCE_TYPE_KEYRING:
|
||||
if (keyring_is_writable (hd->active[hd->current].token))
|
||||
return 0; /* found (hd->current is set to it) */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Rebuild the caches of all key resources.
|
||||
*/
|
||||
void
|
||||
keydb_rebuild_caches (void)
|
||||
{
|
||||
int i, rc;
|
||||
|
||||
for (i=0; i < used_resources; i++)
|
||||
{
|
||||
if (all_resources[i].secret)
|
||||
continue;
|
||||
switch (all_resources[i].type)
|
||||
{
|
||||
case KEYDB_RESOURCE_TYPE_NONE: /* ignore */
|
||||
break;
|
||||
case KEYDB_RESOURCE_TYPE_KEYRING:
|
||||
rc = keyring_rebuild_cache (all_resources[i].token);
|
||||
if (rc)
|
||||
log_error (_("failed to rebuild keyring cache: %s\n"),
|
||||
g10_errstr (rc));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Start the next search on this handle right at the beginning
|
||||
*/
|
||||
int
|
||||
keydb_search_reset (KEYDB_HANDLE hd)
|
||||
{
|
||||
int i, rc = 0;
|
||||
|
||||
if (!hd)
|
||||
return G10ERR_INV_ARG;
|
||||
|
||||
hd->current = 0;
|
||||
hd->found = -1;
|
||||
/* and reset all resources */
|
||||
for (i=0; !rc && i < hd->used; i++) {
|
||||
switch (hd->active[i].type) {
|
||||
case KEYDB_RESOURCE_TYPE_NONE:
|
||||
break;
|
||||
case KEYDB_RESOURCE_TYPE_KEYRING:
|
||||
rc = keyring_search_reset (hd->active[i].u.kr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Search through all keydb resources, starting at the current position,
|
||||
* for a keyblock which contains one of the keys described in the DESC array.
|
||||
*/
|
||||
int
|
||||
keydb_search (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc, size_t ndesc)
|
||||
{
|
||||
int rc = -1;
|
||||
|
||||
if (!hd)
|
||||
return G10ERR_INV_ARG;
|
||||
|
||||
while (rc == -1 && hd->current >= 0 && hd->current < hd->used) {
|
||||
switch (hd->active[hd->current].type) {
|
||||
case KEYDB_RESOURCE_TYPE_NONE:
|
||||
BUG(); /* we should never see it here */
|
||||
break;
|
||||
case KEYDB_RESOURCE_TYPE_KEYRING:
|
||||
rc = keyring_search (hd->active[hd->current].u.kr, desc, ndesc);
|
||||
break;
|
||||
}
|
||||
if (rc == -1) /* EOF -> switch to next resource */
|
||||
hd->current++;
|
||||
else if (!rc)
|
||||
hd->found = hd->current;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
keydb_search_first (KEYDB_HANDLE hd)
|
||||
{
|
||||
KEYDB_SEARCH_DESC desc;
|
||||
|
||||
memset (&desc, 0, sizeof desc);
|
||||
desc.mode = KEYDB_SEARCH_MODE_FIRST;
|
||||
return keydb_search (hd, &desc, 1);
|
||||
}
|
||||
|
||||
int
|
||||
keydb_search_next (KEYDB_HANDLE hd)
|
||||
{
|
||||
KEYDB_SEARCH_DESC desc;
|
||||
|
||||
memset (&desc, 0, sizeof desc);
|
||||
desc.mode = KEYDB_SEARCH_MODE_NEXT;
|
||||
return keydb_search (hd, &desc, 1);
|
||||
}
|
||||
|
||||
int
|
||||
keydb_search_kid (KEYDB_HANDLE hd, u32 *kid)
|
||||
{
|
||||
KEYDB_SEARCH_DESC desc;
|
||||
|
||||
memset (&desc, 0, sizeof desc);
|
||||
desc.mode = KEYDB_SEARCH_MODE_LONG_KID;
|
||||
desc.u.kid[0] = kid[0];
|
||||
desc.u.kid[1] = kid[1];
|
||||
return keydb_search (hd, &desc, 1);
|
||||
}
|
||||
|
||||
int
|
||||
keydb_search_fpr (KEYDB_HANDLE hd, const byte *fpr)
|
||||
{
|
||||
KEYDB_SEARCH_DESC desc;
|
||||
|
||||
memset (&desc, 0, sizeof desc);
|
||||
desc.mode = KEYDB_SEARCH_MODE_FPR;
|
||||
memcpy (desc.u.fpr, fpr, MAX_FINGERPRINT_LEN);
|
||||
return keydb_search (hd, &desc, 1);
|
||||
}
|
||||
|
||||
|
||||
|
156
g10/keydb.h
156
g10/keydb.h
@ -1,5 +1,5 @@
|
||||
/* keydb.h - Key database
|
||||
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
|
||||
* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
@ -18,14 +18,18 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
#ifndef GPG_KEYDB_H
|
||||
#define GPG_KEYDB_H
|
||||
#ifndef G10_KEYDB_H
|
||||
#define G10_KEYDB_H
|
||||
|
||||
#include "types.h"
|
||||
#include "basicdefs.h"
|
||||
#include "global.h"
|
||||
#include "packet.h"
|
||||
#include "cipher.h"
|
||||
|
||||
#define MAX_FINGERPRINT_LEN 20
|
||||
/* What qualifies as a certification (rather than a signature?) */
|
||||
#define IS_SIG(s) (((s)->sig_class==0x00) || ((s)->sig_class==0x01) || \
|
||||
((s)->sig_class==0x02) || ((s)->sig_class==0x40))
|
||||
#define IS_CERT(s) (!IS_SIG(s))
|
||||
|
||||
#define IS_KEY_SIG(s) ((s)->sig_class == 0x1f)
|
||||
#define IS_UID_SIG(s) (((s)->sig_class & ~3) == 0x10)
|
||||
@ -35,7 +39,6 @@
|
||||
#define IS_SUBKEY_REV(s) ((s)->sig_class == 0x28)
|
||||
|
||||
|
||||
|
||||
struct getkey_ctx_s;
|
||||
typedef struct getkey_ctx_s *GETKEY_CTX;
|
||||
|
||||
@ -47,7 +50,6 @@ typedef struct getkey_ctx_s *GETKEY_CTX;
|
||||
* This structure is also used to bind arbitrary packets together.
|
||||
*/
|
||||
|
||||
typedef struct kbnode_struct *KBNODE;
|
||||
struct kbnode_struct {
|
||||
KBNODE next;
|
||||
PACKET *pkt;
|
||||
@ -62,19 +64,28 @@ struct kbnode_struct {
|
||||
|
||||
enum resource_type {
|
||||
rt_UNKNOWN = 0,
|
||||
rt_RING = 1,
|
||||
rt_KBXF = 2
|
||||
rt_RING = 1
|
||||
};
|
||||
|
||||
|
||||
/****************
|
||||
* A data structure to hold information about the external position
|
||||
* A data structre to hold information about the external position
|
||||
* of a keyblock.
|
||||
*/
|
||||
struct keyblock_pos_struct;
|
||||
typedef struct keyblock_pos_struct *KBPOS;
|
||||
struct keyblock_pos_struct {
|
||||
int resno; /* resource number */
|
||||
enum resource_type rt;
|
||||
off_t offset; /* position information */
|
||||
unsigned count; /* length of the keyblock in packets */
|
||||
IOBUF fp; /* used by enum_keyblocks */
|
||||
int secret; /* working on a secret keyring */
|
||||
PACKET *pkt; /* ditto */
|
||||
int valid;
|
||||
};
|
||||
typedef struct keyblock_pos_struct KBPOS;
|
||||
|
||||
/* structure to hold a couple of public key certificates */
|
||||
typedef struct pk_list *PK_LIST;
|
||||
struct pk_list {
|
||||
PK_LIST next;
|
||||
PKT_public_key *pk;
|
||||
@ -82,18 +93,82 @@ struct pk_list {
|
||||
};
|
||||
|
||||
/* structure to hold a couple of secret key certificates */
|
||||
typedef struct sk_list *SK_LIST;
|
||||
struct sk_list {
|
||||
SK_LIST next;
|
||||
PKT_secret_key *sk;
|
||||
int mark;
|
||||
};
|
||||
|
||||
/* structure to collect all information which can be used to
|
||||
* identify a public key */
|
||||
typedef struct pubkey_find_info *PUBKEY_FIND_INFO;
|
||||
struct pubkey_find_info {
|
||||
u32 keyid[2];
|
||||
unsigned nbits;
|
||||
byte pubkey_algo;
|
||||
byte fingerprint[MAX_FINGERPRINT_LEN];
|
||||
char userid[1];
|
||||
};
|
||||
|
||||
|
||||
typedef struct keydb_handle *KEYDB_HANDLE;
|
||||
|
||||
typedef enum {
|
||||
KEYDB_SEARCH_MODE_NONE,
|
||||
KEYDB_SEARCH_MODE_EXACT,
|
||||
KEYDB_SEARCH_MODE_SUBSTR,
|
||||
KEYDB_SEARCH_MODE_MAIL,
|
||||
KEYDB_SEARCH_MODE_MAILSUB,
|
||||
KEYDB_SEARCH_MODE_MAILEND,
|
||||
KEYDB_SEARCH_MODE_WORDS,
|
||||
KEYDB_SEARCH_MODE_SHORT_KID,
|
||||
KEYDB_SEARCH_MODE_LONG_KID,
|
||||
KEYDB_SEARCH_MODE_FPR16,
|
||||
KEYDB_SEARCH_MODE_FPR20,
|
||||
KEYDB_SEARCH_MODE_FPR,
|
||||
KEYDB_SEARCH_MODE_FIRST,
|
||||
KEYDB_SEARCH_MODE_NEXT
|
||||
} KeydbSearchMode;
|
||||
|
||||
struct keydb_search_desc {
|
||||
KeydbSearchMode mode;
|
||||
int (*skipfnc)(void *,u32*);
|
||||
void *skipfncvalue;
|
||||
union {
|
||||
const char *name;
|
||||
char fpr[MAX_FINGERPRINT_LEN];
|
||||
u32 kid[2];
|
||||
} u;
|
||||
};
|
||||
|
||||
/*-- keydb.c --*/
|
||||
int keydb_add_resource (const char *url, int force, int secret);
|
||||
KEYDB_HANDLE keydb_new (int secret);
|
||||
void keydb_release (KEYDB_HANDLE hd);
|
||||
const char *keydb_get_resource_name (KEYDB_HANDLE hd);
|
||||
int keydb_get_keyblock (KEYDB_HANDLE hd, KBNODE *ret_kb);
|
||||
int keydb_update_keyblock (KEYDB_HANDLE hd, KBNODE kb);
|
||||
int keydb_insert_keyblock (KEYDB_HANDLE hd, KBNODE kb);
|
||||
int keydb_delete_keyblock (KEYDB_HANDLE hd);
|
||||
int keydb_locate_writable (KEYDB_HANDLE hd, const char *reserved);
|
||||
void keydb_rebuild_caches (void);
|
||||
int keydb_search_reset (KEYDB_HANDLE hd);
|
||||
int keydb_search (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc, size_t ndesc);
|
||||
int keydb_search_first (KEYDB_HANDLE hd);
|
||||
int keydb_search_next (KEYDB_HANDLE hd);
|
||||
int keydb_search_kid (KEYDB_HANDLE hd, u32 *kid);
|
||||
int keydb_search_fpr (KEYDB_HANDLE hd, const byte *fpr);
|
||||
|
||||
|
||||
/*-- pkclist.c --*/
|
||||
void show_revocation_reason( PKT_public_key *pk, int mode );
|
||||
int check_signatures_trust( PKT_signature *sig );
|
||||
void release_pk_list( PK_LIST pk_list );
|
||||
int build_pk_list( STRLIST remusr, PK_LIST *ret_pk_list, unsigned use );
|
||||
int select_algo_from_prefs( PK_LIST pk_list, int preftype );
|
||||
int build_pk_list( STRLIST rcpts, PK_LIST *ret_pk_list, unsigned use );
|
||||
int select_algo_from_prefs( PK_LIST pk_list, int preftype,
|
||||
int request, void *hint );
|
||||
int select_mdc_from_pklist (PK_LIST pk_list);
|
||||
|
||||
/*-- skclist.c --*/
|
||||
void release_sk_list( SK_LIST sk_list );
|
||||
@ -105,18 +180,19 @@ int have_static_passphrase(void);
|
||||
void read_passphrase_from_fd( int fd );
|
||||
void passphrase_clear_cache ( u32 *keyid, int algo );
|
||||
DEK *passphrase_to_dek( u32 *keyid, int pubkey_algo,
|
||||
int cipher_algo, STRING2KEY *s2k, int mode);
|
||||
int cipher_algo, STRING2KEY *s2k, int mode,
|
||||
const char *tryagain_text);
|
||||
void set_next_passphrase( const char *s );
|
||||
char *get_last_passphrase(void);
|
||||
|
||||
/*-- getkey.c --*/
|
||||
int classify_user_id( const char *name, u32 *keyid, byte *fprint,
|
||||
const char **retstr, size_t *retlen );
|
||||
int classify_user_id( const char *name, KEYDB_SEARCH_DESC *desc);
|
||||
void cache_public_key( PKT_public_key *pk );
|
||||
void getkey_disable_caches(void);
|
||||
int get_pubkey( PKT_public_key *pk, u32 *keyid );
|
||||
KBNODE get_pubkeyblock( u32 *keyid );
|
||||
int get_pubkey_byname( GETKEY_CTX *rx, PKT_public_key *pk,
|
||||
const char *name, KBNODE *ret_keyblock );
|
||||
int get_pubkey_byname( PKT_public_key *pk, const char *name,
|
||||
KBNODE *ret_keyblock, KEYDB_HANDLE *ret_kdbhd);
|
||||
int get_pubkey_bynames( GETKEY_CTX *rx, PKT_public_key *pk,
|
||||
STRLIST names, KBNODE *ret_keyblock );
|
||||
int get_pubkey_next( GETKEY_CTX ctx, PKT_public_key *pk, KBNODE *ret_keyblock );
|
||||
@ -129,25 +205,21 @@ int get_keyblock_byfprint( KBNODE *ret_keyblock, const byte *fprint,
|
||||
size_t fprint_len );
|
||||
int get_keyblock_bylid( KBNODE *ret_keyblock, ulong lid );
|
||||
int seckey_available( u32 *keyid );
|
||||
int get_seckey_byname( GETKEY_CTX *rx,
|
||||
PKT_secret_key *sk, const char *name, int unlock,
|
||||
KBNODE *retblock );
|
||||
int get_seckey_byname( PKT_secret_key *sk, const char *name, int unlock );
|
||||
int get_seckey_bynames( GETKEY_CTX *rx, PKT_secret_key *sk,
|
||||
STRLIST names, KBNODE *ret_keyblock );
|
||||
int get_seckey_byfprint( PKT_secret_key *sk,
|
||||
const byte *fprint, size_t fprint_len);
|
||||
int get_seckey_next( GETKEY_CTX ctx, PKT_secret_key *sk, KBNODE *ret_keyblock );
|
||||
void get_seckey_end( GETKEY_CTX ctx );
|
||||
int find_keyblock_byname( KBNODE *retblock, const char *username );
|
||||
int find_secret_keyblock_byname( KBNODE *retblock, const char *username );
|
||||
int find_keyblock_bypk( KBNODE *retblock, PKT_public_key *pk );
|
||||
int find_keyblock_bysk( KBNODE *retblock, PKT_secret_key *sk );
|
||||
|
||||
int enum_secret_keys( void **context, PKT_secret_key *sk, int with_subkeys );
|
||||
void merge_keys_and_selfsig( KBNODE keyblock );
|
||||
void merge_public_with_secret ( KBNODE pubblock, KBNODE secblock );
|
||||
char*get_user_id_string( u32 *keyid );
|
||||
char*get_user_id_string_native( u32 *keyid );
|
||||
char*get_long_user_id_string( u32 *keyid );
|
||||
char*get_user_id( u32 *keyid, size_t *rn );
|
||||
char*get_user_id_native( u32 *keyid );
|
||||
KEYDB_HANDLE get_ctx_handle(GETKEY_CTX ctx);
|
||||
|
||||
/*-- keyid.c --*/
|
||||
int pubkey_letter( int algo );
|
||||
@ -162,12 +234,16 @@ const char *datestr_from_sk( PKT_secret_key *sk );
|
||||
const char *datestr_from_sig( PKT_signature *sig );
|
||||
const char *expirestr_from_pk( PKT_public_key *pk );
|
||||
const char *expirestr_from_sk( PKT_secret_key *sk );
|
||||
const char *expirestr_from_sig( PKT_signature *sig );
|
||||
|
||||
const char *colon_strtime (u32 t);
|
||||
const char *colon_datestr_from_pk (PKT_public_key *pk);
|
||||
const char *colon_datestr_from_sk (PKT_secret_key *sk);
|
||||
const char *colon_datestr_from_sig (PKT_signature *sig);
|
||||
const char *colon_expirestr_from_sig (PKT_signature *sig);
|
||||
|
||||
byte *fingerprint_from_sk( PKT_secret_key *sk, byte *buf, size_t *ret_len );
|
||||
byte *fingerprint_from_pk( PKT_public_key *pk, byte *buf, size_t *ret_len );
|
||||
char *unified_fingerprint_from_pk( PKT_public_key *pk,
|
||||
char *buffer, size_t bufsize );
|
||||
char *unified_fingerprint_from_sk( PKT_secret_key *sk,
|
||||
char *buffer, size_t bufsize );
|
||||
|
||||
/*-- kbnode.c --*/
|
||||
KBNODE new_kbnode( PACKET *pkt );
|
||||
@ -186,18 +262,4 @@ void clear_kbnode_flags( KBNODE n );
|
||||
int commit_kbnode( KBNODE *root );
|
||||
void dump_kbnode( KBNODE node );
|
||||
|
||||
/*-- ringedit.c --*/
|
||||
const char *enum_keyblock_resources( int *sequence, int secret );
|
||||
int add_keyblock_resource( const char *resname, int force, int secret );
|
||||
const char *keyblock_resource_name( KBPOS kbpos );
|
||||
int get_keyblock_handle( const char *filename, int secret, KBPOS kbpos );
|
||||
char *get_writable_keyblock_file( int secret );
|
||||
int enum_keyblocks_begin( KBPOS *kbpos, int mode );
|
||||
int enum_keyblocks_next( KBPOS kbpos, int mode, KBNODE *ret_root );
|
||||
void enum_keyblocks_end( KBPOS kbpos );
|
||||
int insert_keyblock( KBNODE keyblock );
|
||||
int delete_keyblock( KBNODE keyblock );
|
||||
int update_keyblock( KBNODE keyblock );
|
||||
|
||||
|
||||
#endif /*GPG_KEYDB_H*/
|
||||
#endif /*G10_KEYDB_H*/
|
||||
|
1720
g10/keyedit.c
1720
g10/keyedit.c
File diff suppressed because it is too large
Load Diff
1299
g10/keygen.c
1299
g10/keygen.c
File diff suppressed because it is too large
Load Diff
436
g10/keyid.c
436
g10/keyid.c
@ -1,5 +1,5 @@
|
||||
/* keyid.c - jeyid and fingerprint handling
|
||||
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
|
||||
/* keyid.c - key ID and fingerprint handling
|
||||
* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
@ -25,12 +25,11 @@
|
||||
#include <errno.h>
|
||||
#include <time.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <gcrypt.h>
|
||||
#include "util.h"
|
||||
#include "main.h"
|
||||
#include "packet.h"
|
||||
#include "options.h"
|
||||
#include "mpi.h"
|
||||
#include "keydb.h"
|
||||
#include "i18n.h"
|
||||
|
||||
@ -39,58 +38,48 @@ int
|
||||
pubkey_letter( int algo )
|
||||
{
|
||||
switch( algo ) {
|
||||
case GCRY_PK_RSA: return 'R' ;
|
||||
case GCRY_PK_RSA_E: return 'r' ;
|
||||
case GCRY_PK_RSA_S: return 's' ;
|
||||
case GCRY_PK_ELG_E: return 'g';
|
||||
case GCRY_PK_ELG: return 'G' ;
|
||||
case GCRY_PK_DSA: return 'D' ;
|
||||
case PUBKEY_ALGO_RSA: return 'R' ;
|
||||
case PUBKEY_ALGO_RSA_E: return 'r' ;
|
||||
case PUBKEY_ALGO_RSA_S: return 's' ;
|
||||
case PUBKEY_ALGO_ELGAMAL_E: return 'g';
|
||||
case PUBKEY_ALGO_ELGAMAL: return 'G' ;
|
||||
case PUBKEY_ALGO_DSA: return 'D' ;
|
||||
default: return '?';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static GCRY_MD_HD
|
||||
static MD_HANDLE
|
||||
do_fingerprint_md( PKT_public_key *pk )
|
||||
{
|
||||
GCRY_MD_HD md;
|
||||
unsigned int n;
|
||||
unsigned int nn[GNUPG_MAX_NPKEY];
|
||||
byte *pp[GNUPG_MAX_NPKEY];
|
||||
MD_HANDLE md;
|
||||
unsigned n;
|
||||
unsigned nb[PUBKEY_MAX_NPKEY];
|
||||
unsigned nn[PUBKEY_MAX_NPKEY];
|
||||
byte *pp[PUBKEY_MAX_NPKEY];
|
||||
int i;
|
||||
int npkey = pubkey_get_npkey( pk->pubkey_algo );
|
||||
|
||||
md = gcry_md_open( pk->version < 4 ? GCRY_MD_RMD160 : GCRY_MD_SHA1, 0);
|
||||
if( !md )
|
||||
BUG();
|
||||
md = md_open( pk->version < 4 ? DIGEST_ALGO_RMD160 : DIGEST_ALGO_SHA1, 0);
|
||||
n = pk->version < 4 ? 8 : 6;
|
||||
for(i=0; i < npkey; i++ ) {
|
||||
int rc;
|
||||
size_t nbytes;
|
||||
|
||||
rc = gcry_mpi_print( GCRYMPI_FMT_PGP, NULL, &nbytes, pk->pkey[i] );
|
||||
assert( !rc );
|
||||
/* fixme: we should try to allocate a buffer on the stack */
|
||||
pp[i] = gcry_xmalloc(nbytes);
|
||||
rc = gcry_mpi_print( GCRYMPI_FMT_PGP, pp[i], &nbytes, pk->pkey[i] );
|
||||
assert( !rc );
|
||||
nn[i] = nbytes;
|
||||
n += nn[i];
|
||||
nb[i] = mpi_get_nbits(pk->pkey[i]);
|
||||
pp[i] = mpi_get_buffer( pk->pkey[i], nn+i, NULL );
|
||||
n += 2 + nn[i];
|
||||
}
|
||||
|
||||
gcry_md_putc( md, 0x99 ); /* ctb */
|
||||
gcry_md_putc( md, n >> 8 ); /* 2 byte length header */
|
||||
gcry_md_putc( md, n );
|
||||
md_putc( md, 0x99 ); /* ctb */
|
||||
md_putc( md, n >> 8 ); /* 2 byte length header */
|
||||
md_putc( md, n );
|
||||
if( pk->version < 4 )
|
||||
gcry_md_putc( md, 3 );
|
||||
md_putc( md, 3 );
|
||||
else
|
||||
gcry_md_putc( md, 4 );
|
||||
md_putc( md, 4 );
|
||||
|
||||
{ u32 a = pk->timestamp;
|
||||
gcry_md_putc( md, a >> 24 );
|
||||
gcry_md_putc( md, a >> 16 );
|
||||
gcry_md_putc( md, a >> 8 );
|
||||
gcry_md_putc( md, a );
|
||||
md_putc( md, a >> 24 );
|
||||
md_putc( md, a >> 16 );
|
||||
md_putc( md, a >> 8 );
|
||||
md_putc( md, a );
|
||||
}
|
||||
if( pk->version < 4 ) {
|
||||
u16 a;
|
||||
@ -99,20 +88,22 @@ do_fingerprint_md( PKT_public_key *pk )
|
||||
a = (u16)((pk->expiredate - pk->timestamp) / 86400L);
|
||||
else
|
||||
a = 0;
|
||||
gcry_md_putc( md, a >> 8 );
|
||||
gcry_md_putc( md, a );
|
||||
md_putc( md, a >> 8 );
|
||||
md_putc( md, a );
|
||||
}
|
||||
gcry_md_putc( md, pk->pubkey_algo );
|
||||
md_putc( md, pk->pubkey_algo );
|
||||
for(i=0; i < npkey; i++ ) {
|
||||
gcry_md_write( md, pp[i], nn[i] );
|
||||
gcry_free(pp[i]);
|
||||
md_putc( md, nb[i]>>8);
|
||||
md_putc( md, nb[i] );
|
||||
md_write( md, pp[i], nn[i] );
|
||||
m_free(pp[i]);
|
||||
}
|
||||
gcry_md_final( md );
|
||||
md_final( md );
|
||||
|
||||
return md;
|
||||
}
|
||||
|
||||
static GCRY_MD_HD
|
||||
static MD_HANDLE
|
||||
do_fingerprint_md_sk( PKT_secret_key *sk )
|
||||
{
|
||||
PKT_public_key pk;
|
||||
@ -130,30 +121,6 @@ do_fingerprint_md_sk( PKT_secret_key *sk )
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
v3_keyid( MPI a, u32 *ki )
|
||||
{
|
||||
int rc;
|
||||
byte *buffer;
|
||||
size_t nbytes;
|
||||
|
||||
rc = gcry_mpi_print( GCRYMPI_FMT_USG, NULL, &nbytes, a );
|
||||
assert( !rc );
|
||||
/* fixme: allocate it on the stack */
|
||||
buffer = gcry_xmalloc(nbytes);
|
||||
rc = gcry_mpi_print( GCRYMPI_FMT_USG, buffer, &nbytes, a );
|
||||
assert( !rc );
|
||||
if( nbytes < 8 ) { /* oops */
|
||||
ki[0] = ki[1] = 0;
|
||||
}
|
||||
else {
|
||||
memcpy( ki+0, buffer+nbytes-8, 4);
|
||||
memcpy( ki+1, buffer+nbytes-4, 4);
|
||||
}
|
||||
gcry_free( buffer );
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
* Get the keyid from the secret key and put it into keyid
|
||||
* if this is not NULL. Return the 32 low bits of the keyid.
|
||||
@ -161,36 +128,28 @@ v3_keyid( MPI a, u32 *ki )
|
||||
u32
|
||||
keyid_from_sk( PKT_secret_key *sk, u32 *keyid )
|
||||
{
|
||||
u32 lowbits;
|
||||
u32 dummy_keyid[2];
|
||||
|
||||
if( !keyid )
|
||||
keyid = dummy_keyid;
|
||||
|
||||
if( sk->keyid[0] || sk->keyid[1] ) {
|
||||
keyid[0] = sk->keyid[0];
|
||||
keyid[1] = sk->keyid[1];
|
||||
}
|
||||
else if( sk->version < 4 && is_RSA(sk->pubkey_algo) ) {
|
||||
if( pubkey_get_npkey(sk->pubkey_algo) )
|
||||
v3_keyid( sk->skey[0], keyid ); /* take n */
|
||||
else
|
||||
keyid[0] = keyid[1] = 0;
|
||||
sk->keyid[0] = keyid[0];
|
||||
sk->keyid[1] = keyid[1];
|
||||
if( sk->version < 4 && is_RSA(sk->pubkey_algo) ) {
|
||||
lowbits = pubkey_get_npkey(sk->pubkey_algo) ?
|
||||
mpi_get_keyid( sk->skey[0], keyid ) : 0; /* take n */
|
||||
}
|
||||
else {
|
||||
const byte *dp;
|
||||
GCRY_MD_HD md;
|
||||
MD_HANDLE md;
|
||||
md = do_fingerprint_md_sk(sk);
|
||||
dp = gcry_md_read( md, 0 );
|
||||
dp = md_read( md, 0 );
|
||||
keyid[0] = dp[12] << 24 | dp[13] << 16 | dp[14] << 8 | dp[15] ;
|
||||
keyid[1] = dp[16] << 24 | dp[17] << 16 | dp[18] << 8 | dp[19] ;
|
||||
gcry_md_close(md);
|
||||
sk->keyid[0] = keyid[0];
|
||||
sk->keyid[1] = keyid[1];
|
||||
lowbits = keyid[1];
|
||||
md_close(md);
|
||||
}
|
||||
|
||||
return keyid[1];
|
||||
return lowbits;
|
||||
}
|
||||
|
||||
|
||||
@ -201,6 +160,7 @@ keyid_from_sk( PKT_secret_key *sk, u32 *keyid )
|
||||
u32
|
||||
keyid_from_pk( PKT_public_key *pk, u32 *keyid )
|
||||
{
|
||||
u32 lowbits;
|
||||
u32 dummy_keyid[2];
|
||||
|
||||
if( !keyid )
|
||||
@ -209,28 +169,28 @@ keyid_from_pk( PKT_public_key *pk, u32 *keyid )
|
||||
if( pk->keyid[0] || pk->keyid[1] ) {
|
||||
keyid[0] = pk->keyid[0];
|
||||
keyid[1] = pk->keyid[1];
|
||||
lowbits = keyid[1];
|
||||
}
|
||||
else if( pk->version < 4 && is_RSA(pk->pubkey_algo) ) {
|
||||
if( pubkey_get_npkey(pk->pubkey_algo) )
|
||||
v3_keyid( pk->pkey[0], keyid ); /* from n */
|
||||
else
|
||||
keyid[0] = keyid[1] = 0;
|
||||
lowbits = pubkey_get_npkey(pk->pubkey_algo) ?
|
||||
mpi_get_keyid( pk->pkey[0], keyid ) : 0 ; /* from n */
|
||||
pk->keyid[0] = keyid[0];
|
||||
pk->keyid[1] = keyid[1];
|
||||
}
|
||||
else {
|
||||
const byte *dp;
|
||||
GCRY_MD_HD md;
|
||||
MD_HANDLE md;
|
||||
md = do_fingerprint_md(pk);
|
||||
dp = gcry_md_read( md, 0 );
|
||||
dp = md_read( md, 0 );
|
||||
keyid[0] = dp[12] << 24 | dp[13] << 16 | dp[14] << 8 | dp[15] ;
|
||||
keyid[1] = dp[16] << 24 | dp[17] << 16 | dp[18] << 8 | dp[19] ;
|
||||
gcry_md_close(md);
|
||||
lowbits = keyid[1];
|
||||
md_close(md);
|
||||
pk->keyid[0] = keyid[0];
|
||||
pk->keyid[1] = keyid[1];
|
||||
}
|
||||
|
||||
return keyid[1];
|
||||
return lowbits;
|
||||
}
|
||||
|
||||
|
||||
@ -299,6 +259,21 @@ nbits_from_sk( PKT_secret_key *sk )
|
||||
return pubkey_nbits( sk->pubkey_algo, sk->skey );
|
||||
}
|
||||
|
||||
static const char *
|
||||
mk_datestr (char *buffer, time_t atime)
|
||||
{
|
||||
struct tm *tp;
|
||||
|
||||
if ( atime < 0 ) /* 32 bit time_t and after 2038-01-19 */
|
||||
strcpy (buffer, "????" "-??" "-??"); /* mark this as invalid */
|
||||
else {
|
||||
tp = gmtime (&atime);
|
||||
sprintf (buffer,"%04d-%02d-%02d",
|
||||
1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday );
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/****************
|
||||
* return a string with the creation date of the pk
|
||||
* Note: this is alloced in a static buffer.
|
||||
@ -308,67 +283,122 @@ const char *
|
||||
datestr_from_pk( PKT_public_key *pk )
|
||||
{
|
||||
static char buffer[11+5];
|
||||
struct tm *tp;
|
||||
time_t atime = pk->timestamp;
|
||||
|
||||
tp = gmtime( &atime );
|
||||
sprintf(buffer,"%04d-%02d-%02d", 1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday );
|
||||
return buffer;
|
||||
return mk_datestr (buffer, atime);
|
||||
}
|
||||
|
||||
const char *
|
||||
datestr_from_sk( PKT_secret_key *sk )
|
||||
{
|
||||
static char buffer[11+5];
|
||||
struct tm *tp;
|
||||
time_t atime = sk->timestamp;
|
||||
|
||||
tp = gmtime( &atime );
|
||||
sprintf(buffer,"%04d-%02d-%02d", 1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday );
|
||||
return buffer;
|
||||
return mk_datestr (buffer, atime);
|
||||
}
|
||||
|
||||
const char *
|
||||
datestr_from_sig( PKT_signature *sig )
|
||||
{
|
||||
static char buffer[11+5];
|
||||
struct tm *tp;
|
||||
time_t atime = sig->timestamp;
|
||||
|
||||
tp = gmtime( &atime );
|
||||
sprintf(buffer,"%04d-%02d-%02d", 1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday );
|
||||
return buffer;
|
||||
return mk_datestr (buffer, atime);
|
||||
}
|
||||
|
||||
|
||||
const char *
|
||||
expirestr_from_pk( PKT_public_key *pk )
|
||||
{
|
||||
static char buffer[11+5];
|
||||
struct tm *tp;
|
||||
time_t atime;
|
||||
|
||||
if( !pk->expiredate )
|
||||
return _("never ");
|
||||
atime = pk->expiredate;
|
||||
tp = gmtime( &atime );
|
||||
sprintf(buffer,"%04d-%02d-%02d", 1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday );
|
||||
return buffer;
|
||||
return mk_datestr (buffer, atime);
|
||||
}
|
||||
|
||||
const char *
|
||||
expirestr_from_sk( PKT_secret_key *sk )
|
||||
{
|
||||
static char buffer[11+5];
|
||||
struct tm *tp;
|
||||
time_t atime;
|
||||
|
||||
if( !sk->expiredate )
|
||||
return _("never ");
|
||||
atime = sk->expiredate;
|
||||
tp = gmtime( &atime );
|
||||
sprintf(buffer,"%04d-%02d-%02d", 1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday );
|
||||
return buffer;
|
||||
return mk_datestr (buffer, atime);
|
||||
}
|
||||
|
||||
const char *
|
||||
expirestr_from_sig( PKT_signature *sig )
|
||||
{
|
||||
static char buffer[11+5];
|
||||
time_t atime;
|
||||
|
||||
if(!sig->expiredate)
|
||||
return _("never ");
|
||||
atime=sig->expiredate;
|
||||
return mk_datestr (buffer, atime);
|
||||
}
|
||||
|
||||
const char *
|
||||
colon_strtime (u32 t)
|
||||
{
|
||||
if (!t)
|
||||
return "";
|
||||
if (opt.fixed_list_mode) {
|
||||
static char buf[15];
|
||||
sprintf (buf, "%lu", (ulong)t);
|
||||
return buf;
|
||||
}
|
||||
return strtimestamp(t);
|
||||
}
|
||||
|
||||
const char *
|
||||
colon_datestr_from_pk (PKT_public_key *pk)
|
||||
{
|
||||
if (opt.fixed_list_mode) {
|
||||
static char buf[15];
|
||||
sprintf (buf, "%lu", (ulong)pk->timestamp);
|
||||
return buf;
|
||||
}
|
||||
return datestr_from_pk (pk);
|
||||
}
|
||||
|
||||
const char *
|
||||
colon_datestr_from_sk (PKT_secret_key *sk)
|
||||
{
|
||||
if (opt.fixed_list_mode) {
|
||||
static char buf[15];
|
||||
sprintf (buf, "%lu", (ulong)sk->timestamp);
|
||||
return buf;
|
||||
}
|
||||
return datestr_from_sk (sk);
|
||||
}
|
||||
|
||||
const char *
|
||||
colon_datestr_from_sig (PKT_signature *sig)
|
||||
{
|
||||
if (opt.fixed_list_mode) {
|
||||
static char buf[15];
|
||||
sprintf (buf, "%lu", (ulong)sig->timestamp);
|
||||
return buf;
|
||||
}
|
||||
return datestr_from_sig (sig);
|
||||
}
|
||||
|
||||
const char *
|
||||
colon_expirestr_from_sig (PKT_signature *sig)
|
||||
{
|
||||
if(!sig->expiredate)
|
||||
return "";
|
||||
if (opt.fixed_list_mode) {
|
||||
static char buf[15];
|
||||
sprintf (buf, "%lu", (ulong)sig->expiredate);
|
||||
return buf;
|
||||
}
|
||||
return expirestr_from_sig (sig);
|
||||
}
|
||||
|
||||
|
||||
@ -381,184 +411,92 @@ expirestr_from_sk( PKT_secret_key *sk )
|
||||
byte *
|
||||
fingerprint_from_pk( PKT_public_key *pk, byte *array, size_t *ret_len )
|
||||
{
|
||||
byte *buf;
|
||||
const char *dp;
|
||||
byte *p, *buf;
|
||||
const byte *dp;
|
||||
size_t len;
|
||||
unsigned int n;
|
||||
|
||||
if( pk->version < 4 && is_RSA(pk->pubkey_algo) ) {
|
||||
/* RSA in version 3 packets is special */
|
||||
GCRY_MD_HD md;
|
||||
MD_HANDLE md;
|
||||
|
||||
md = gcry_md_open( GCRY_MD_MD5, 0);
|
||||
if( !md )
|
||||
BUG();
|
||||
md = md_open( DIGEST_ALGO_MD5, 0);
|
||||
if( pubkey_get_npkey( pk->pubkey_algo ) > 1 ) {
|
||||
int rc;
|
||||
size_t nbytes;
|
||||
|
||||
rc = gcry_mpi_print( GCRYMPI_FMT_USG, NULL, &nbytes, pk->pkey[0] );
|
||||
assert( !rc );
|
||||
/* fixme: allocate it on the stack */
|
||||
buf = gcry_xmalloc(nbytes);
|
||||
rc = gcry_mpi_print( GCRYMPI_FMT_USG, buf, &nbytes, pk->pkey[0] );
|
||||
assert( !rc );
|
||||
gcry_md_write( md, buf, nbytes );
|
||||
gcry_free(buf);
|
||||
rc = gcry_mpi_print( GCRYMPI_FMT_USG, NULL, &nbytes, pk->pkey[1] );
|
||||
assert( !rc );
|
||||
/* fixme: allocate it on the stack */
|
||||
buf = gcry_xmalloc(nbytes);
|
||||
rc = gcry_mpi_print( GCRYMPI_FMT_USG, buf, &nbytes, pk->pkey[1] );
|
||||
assert( !rc );
|
||||
gcry_md_write( md, buf, nbytes );
|
||||
gcry_free(buf);
|
||||
p = buf = mpi_get_buffer( pk->pkey[0], &n, NULL );
|
||||
md_write( md, p, n );
|
||||
m_free(buf);
|
||||
p = buf = mpi_get_buffer( pk->pkey[1], &n, NULL );
|
||||
md_write( md, p, n );
|
||||
m_free(buf);
|
||||
}
|
||||
gcry_md_final(md);
|
||||
md_final(md);
|
||||
if( !array )
|
||||
array = gcry_xmalloc( 16 );
|
||||
array = m_alloc( 16 );
|
||||
len = 16;
|
||||
memcpy(array, gcry_md_read(md, GCRY_MD_MD5), 16 );
|
||||
gcry_md_close(md);
|
||||
memcpy(array, md_read(md, DIGEST_ALGO_MD5), 16 );
|
||||
md_close(md);
|
||||
}
|
||||
else {
|
||||
GCRY_MD_HD md;
|
||||
MD_HANDLE md;
|
||||
md = do_fingerprint_md(pk);
|
||||
dp = gcry_md_read( md, 0 );
|
||||
len = gcry_md_get_algo_dlen( gcry_md_get_algo( md ) );
|
||||
dp = md_read( md, 0 );
|
||||
len = md_digest_length( md_get_algo( md ) );
|
||||
assert( len <= MAX_FINGERPRINT_LEN );
|
||||
if( !array )
|
||||
array = gcry_xmalloc( len );
|
||||
array = m_alloc( len );
|
||||
memcpy(array, dp, len );
|
||||
gcry_md_close(md);
|
||||
pk->keyid[0] = dp[12] << 24 | dp[13] << 16 | dp[14] << 8 | dp[15] ;
|
||||
pk->keyid[1] = dp[16] << 24 | dp[17] << 16 | dp[18] << 8 | dp[19] ;
|
||||
md_close(md);
|
||||
}
|
||||
|
||||
*ret_len = len;
|
||||
return array;
|
||||
}
|
||||
|
||||
|
||||
/* Create a unified fingerprint, that is a printable fingerprint along
|
||||
* wth some other information suitable to passto get_pubkye_byname.
|
||||
* Pass NULL for buffer to let this function allocate the buffer.
|
||||
* This function will truncate the buffer in a way that a valid C string
|
||||
* is returnd (unless bufsize is 0)
|
||||
* Returns: Supplied buffer or newly allocated buffer
|
||||
*/
|
||||
char *
|
||||
unified_fingerprint_from_pk( PKT_public_key *pk,
|
||||
char *buffer, size_t bufsize )
|
||||
{
|
||||
byte fpr[MAX_FINGERPRINT_LEN];
|
||||
size_t fprlen;
|
||||
int i;
|
||||
|
||||
fingerprint_from_pk( pk, fpr, &fprlen );
|
||||
if ( !buffer ) {
|
||||
bufsize = 1+fprlen*2+1+4+1+1;
|
||||
buffer = gcry_xmalloc( bufsize );
|
||||
}
|
||||
if ( bufsize < 1+fprlen*2+1+4+1+1 ) {
|
||||
/* Hmmm, that should be sufficiend also not very nice */
|
||||
if ( bufsize )
|
||||
*buffer = 0;
|
||||
return buffer;
|
||||
}
|
||||
*buffer = ':';
|
||||
for (i=0; i < fprlen; i++ )
|
||||
sprintf( buffer+1+i*2, "%02X", fpr[i] );
|
||||
sprintf( buffer+1+i*2, ":%d:", (pk->pubkey_algo & 0xff) );
|
||||
return buffer;
|
||||
}
|
||||
|
||||
byte *
|
||||
fingerprint_from_sk( PKT_secret_key *sk, byte *array, size_t *ret_len )
|
||||
{
|
||||
byte *buf;
|
||||
byte *p, *buf;
|
||||
const char *dp;
|
||||
size_t len;
|
||||
unsigned n;
|
||||
|
||||
if( sk->version < 4 && is_RSA(sk->pubkey_algo) ) {
|
||||
/* RSA in version 3 packets is special */
|
||||
GCRY_MD_HD md;
|
||||
MD_HANDLE md;
|
||||
|
||||
md = gcry_md_open( GCRY_MD_MD5, 0);
|
||||
if( !md )
|
||||
BUG();
|
||||
md = md_open( DIGEST_ALGO_MD5, 0);
|
||||
if( pubkey_get_npkey( sk->pubkey_algo ) > 1 ) {
|
||||
int rc;
|
||||
size_t nbytes;
|
||||
|
||||
/* FIXME: Why is the hash sequence for secret keys different */
|
||||
rc = gcry_mpi_print( GCRYMPI_FMT_USG, NULL, &nbytes, sk->skey[1] );
|
||||
assert( !rc );
|
||||
/* fixme: allocate it on the stack */
|
||||
buf = gcry_xmalloc(nbytes);
|
||||
rc = gcry_mpi_print( GCRYMPI_FMT_USG, buf, &nbytes, sk->skey[1] );
|
||||
assert( !rc );
|
||||
gcry_md_write( md, buf, nbytes );
|
||||
gcry_free(buf);
|
||||
rc = gcry_mpi_print( GCRYMPI_FMT_USG, NULL, &nbytes, sk->skey[0] );
|
||||
assert( !rc );
|
||||
/* fixme: allocate it on the stack */
|
||||
buf = gcry_xmalloc(nbytes);
|
||||
rc = gcry_mpi_print( GCRYMPI_FMT_USG, buf, &nbytes, sk->skey[0] );
|
||||
assert( !rc );
|
||||
gcry_md_write( md, buf, nbytes );
|
||||
gcry_free(buf);
|
||||
p = buf = mpi_get_buffer( sk->skey[0], &n, NULL );
|
||||
md_write( md, p, n );
|
||||
m_free(buf);
|
||||
p = buf = mpi_get_buffer( sk->skey[1], &n, NULL );
|
||||
md_write( md, p, n );
|
||||
m_free(buf);
|
||||
}
|
||||
gcry_md_final(md);
|
||||
md_final(md);
|
||||
if( !array )
|
||||
array = gcry_xmalloc( 16 );
|
||||
array = m_alloc( 16 );
|
||||
len = 16;
|
||||
memcpy(array, gcry_md_read(md, GCRY_MD_MD5), 16 );
|
||||
gcry_md_close(md);
|
||||
memcpy(array, md_read(md, DIGEST_ALGO_MD5), 16 );
|
||||
md_close(md);
|
||||
}
|
||||
else {
|
||||
GCRY_MD_HD md;
|
||||
MD_HANDLE md;
|
||||
md = do_fingerprint_md_sk(sk);
|
||||
dp = gcry_md_read( md, 0 );
|
||||
len = gcry_md_get_algo_dlen( gcry_md_get_algo( md ) );
|
||||
dp = md_read( md, 0 );
|
||||
len = md_digest_length( md_get_algo( md ) );
|
||||
assert( len <= MAX_FINGERPRINT_LEN );
|
||||
if( !array )
|
||||
array = gcry_xmalloc( len );
|
||||
array = m_alloc( len );
|
||||
memcpy(array, dp, len );
|
||||
gcry_md_close(md);
|
||||
md_close(md);
|
||||
}
|
||||
|
||||
*ret_len = len;
|
||||
return array;
|
||||
}
|
||||
|
||||
char *
|
||||
unified_fingerprint_from_sk( PKT_secret_key *sk,
|
||||
char *buffer, size_t bufsize )
|
||||
{
|
||||
byte fpr[MAX_FINGERPRINT_LEN];
|
||||
size_t fprlen;
|
||||
int i;
|
||||
|
||||
fingerprint_from_sk( sk, fpr, &fprlen );
|
||||
if ( !buffer ) {
|
||||
bufsize = 1+fprlen*2+1+4+1+1;
|
||||
buffer = gcry_xmalloc( bufsize );
|
||||
}
|
||||
if ( bufsize < 1+fprlen*2+1+4+1+1 ) {
|
||||
/* Hmmm, that should be sufficiend also not very nice */
|
||||
if ( bufsize )
|
||||
*buffer = 0;
|
||||
return buffer;
|
||||
}
|
||||
*buffer = ':';
|
||||
for (i=0; i < fprlen; i++ )
|
||||
sprintf( buffer+1+i*2, "%02X", fpr[i] );
|
||||
sprintf( buffer+1+i*2, ":%d:", (sk->pubkey_algo & 0xff) );
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
1050
g10/keylist.c
1050
g10/keylist.c
File diff suppressed because it is too large
Load Diff
1550
g10/keyring.c
Normal file
1550
g10/keyring.c
Normal file
File diff suppressed because it is too large
Load Diff
45
g10/keyring.h
Normal file
45
g10/keyring.h
Normal file
@ -0,0 +1,45 @@
|
||||
/* keyring.h - Keyring operations
|
||||
* Copyright (C) 2001 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
* GnuPG is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GnuPG is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
#ifndef GPG_KEYRING_H
|
||||
#define GPG_KEYRING_H 1
|
||||
|
||||
#include "global.h"
|
||||
|
||||
|
||||
typedef struct keyring_handle *KEYRING_HANDLE;
|
||||
|
||||
void *keyring_register_filename (const char *fname, int secret);
|
||||
int keyring_is_writable (void *token);
|
||||
|
||||
KEYRING_HANDLE keyring_new (void *token, int secret);
|
||||
void keyring_release (KEYRING_HANDLE hd);
|
||||
const char *keyring_get_resource_name (KEYRING_HANDLE hd);
|
||||
int keyring_lock (KEYRING_HANDLE hd, int yes);
|
||||
int keyring_get_keyblock (KEYRING_HANDLE hd, KBNODE *ret_kb);
|
||||
int keyring_update_keyblock (KEYRING_HANDLE hd, KBNODE kb);
|
||||
int keyring_insert_keyblock (KEYRING_HANDLE hd, KBNODE kb);
|
||||
int keyring_locate_writable (KEYRING_HANDLE hd);
|
||||
int keyring_delete_keyblock (KEYRING_HANDLE hd);
|
||||
int keyring_search_reset (KEYRING_HANDLE hd);
|
||||
int keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc, size_t ndesc);
|
||||
int keyring_rebuild_cache (void *);
|
||||
|
||||
#endif /*GPG_KEYRING_H*/
|
22
g10/keyserver-internal.h
Normal file
22
g10/keyserver-internal.h
Normal file
@ -0,0 +1,22 @@
|
||||
/* Keyserver internals */
|
||||
|
||||
#ifndef _KEYSERVER_INTERNAL_H_
|
||||
#define _KEYSERVER_INTERNAL_H_
|
||||
|
||||
#include <time.h>
|
||||
#include "keyserver.h"
|
||||
#include "iobuf.h"
|
||||
#include "types.h"
|
||||
|
||||
void parse_keyserver_options(char *options);
|
||||
int parse_keyserver_uri(char *uri,
|
||||
const char *configname,unsigned int configlineno);
|
||||
int keyserver_export(STRLIST users);
|
||||
int keyserver_import(STRLIST users);
|
||||
int keyserver_import_fprint(const byte *fprint,size_t fprint_len);
|
||||
int keyserver_import_keyid(u32 *keyid);
|
||||
int keyserver_refresh(STRLIST users);
|
||||
int keyserver_search(STRLIST tokens);
|
||||
void keyserver_search_prompt(IOBUF buffer,int count,const char *searchstr);
|
||||
|
||||
#endif /* !_KEYSERVER_INTERNAL_H_ */
|
1033
g10/keyserver.c
Normal file
1033
g10/keyserver.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,5 @@
|
||||
/* ks-proto.c keyserver protocol handling
|
||||
* Copyright (C) 1998 Free Software Foundation, Inc.
|
||||
* Copyright (C) 1998 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* ks-proto.h
|
||||
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
|
||||
* Copyright (C) 1998 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
@ -17,7 +17,7 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifndef GPG_KS_PROTO_H
|
||||
#define GPG_KS_PROTO_H
|
||||
#ifndef G10_KS_PROTO_H
|
||||
#define G10_KS_PROTO_H
|
||||
|
||||
#endif /*GPG_KS_PROTO_H*/
|
||||
#endif /*G10_KS_PROTO_H*/
|
||||
|
108
g10/main.h
108
g10/main.h
@ -1,5 +1,5 @@
|
||||
/* main.h
|
||||
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
|
||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
@ -17,30 +17,39 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifndef GPG_MAIN_H
|
||||
#define GPG_MAIN_H
|
||||
|
||||
#include <gcrypt.h>
|
||||
#include "basicdefs.h"
|
||||
#ifndef G10_MAIN_H
|
||||
#define G10_MAIN_H
|
||||
#include "types.h"
|
||||
#include "iobuf.h"
|
||||
#include "mpi.h"
|
||||
#include "cipher.h"
|
||||
#include "keydb.h"
|
||||
|
||||
#define DEFAULT_CIPHER_ALGO GCRY_CIPHER_BLOWFISH
|
||||
#define DEFAULT_PUBKEY_ALGO GCRY_PUBKEY_ELGAMAL
|
||||
#define DEFAULT_DIGEST_ALGO GCRY_MD_RMD160
|
||||
#define DEFAULT_CIPHER_ALGO CIPHER_ALGO_CAST5
|
||||
#define DEFAULT_PUBKEY_ALGO PUBKEY_ALGO_ELGAMAL
|
||||
#define DEFAULT_DIGEST_ALGO DIGEST_ALGO_SHA1
|
||||
#define DEFAULT_COMPRESS_ALGO 1
|
||||
|
||||
#define is_RSA(a) ((a)==GCRY_PK_RSA || (a)==GCRY_PK_RSA_E \
|
||||
|| (a)==GCRY_PK_RSA_S )
|
||||
#define is_ELGAMAL(a) ((a)==GCRY_PK_ELG || (a)==GCRY_PK_ELG_E)
|
||||
typedef struct {
|
||||
int header_okay;
|
||||
PK_LIST pk_list;
|
||||
cipher_filter_context_t cfx;
|
||||
} encrypt_filter_context_t;
|
||||
|
||||
struct groupitem
|
||||
{
|
||||
char *name;
|
||||
STRLIST values;
|
||||
struct groupitem *next;
|
||||
};
|
||||
|
||||
/*-- gpg.c --*/
|
||||
extern int gpg_errors_seen;
|
||||
/*-- g10.c --*/
|
||||
extern int g10_errors_seen;
|
||||
|
||||
#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5 )
|
||||
void gpg_exit(int rc) __attribute__ ((noreturn));
|
||||
void g10_exit(int rc) __attribute__ ((noreturn));
|
||||
#else
|
||||
void gpg_exit(int rc);
|
||||
void g10_exit(int rc);
|
||||
#endif
|
||||
void print_pubkey_algo_note( int algo );
|
||||
void print_cipher_algo_note( int algo );
|
||||
@ -55,24 +64,29 @@ int disable_core_dumps(void);
|
||||
u16 checksum_u16( unsigned n );
|
||||
u16 checksum( byte *p, unsigned n );
|
||||
u16 checksum_mpi( MPI a );
|
||||
u16 checksum_mpi_counted_nbits( MPI a );
|
||||
u32 buffer_to_u32( const byte *buffer );
|
||||
|
||||
int mpi_write( IOBUF out, GCRY_MPI a );
|
||||
int mpi_write_opaque( IOBUF out, MPI a );
|
||||
GCRY_MPI mpi_read(IOBUF inp, unsigned int *ret_nread, int secure );
|
||||
GCRY_MPI mpi_read_opaque(IOBUF inp, unsigned int *ret_nread );
|
||||
int mpi_print( FILE *fp, MPI a, int mode );
|
||||
|
||||
const byte *get_session_marker( size_t *rlen );
|
||||
int openpgp_cipher_test_algo( int algo );
|
||||
int openpgp_pk_test_algo( int algo, unsigned int usage_flags );
|
||||
int openpgp_pk_algo_usage ( int algo );
|
||||
int openpgp_md_test_algo( int algo );
|
||||
int check_permissions(const char *path,int extension,int checkonly);
|
||||
void idea_cipher_warn( int show );
|
||||
|
||||
int pubkey_get_npkey( int algo );
|
||||
int pubkey_get_nskey( int algo );
|
||||
int pubkey_get_nsig( int algo );
|
||||
int pubkey_get_nenc( int algo );
|
||||
unsigned int pubkey_nbits( int algo, MPI *pkey );
|
||||
struct expando_args
|
||||
{
|
||||
PKT_public_key *pk;
|
||||
PKT_secret_key *sk;
|
||||
byte imagetype;
|
||||
};
|
||||
|
||||
char *pct_expando(const char *string,struct expando_args *args);
|
||||
int hextobyte( const char *s );
|
||||
void deprecated_warning(const char *configname,unsigned int configlineno,
|
||||
const char *option,const char *repl1,const char *repl2);
|
||||
const char *compress_algo_to_string(int algo);
|
||||
int check_compress_algo(int algo);
|
||||
|
||||
/*-- helptext.c --*/
|
||||
void display_online_help( const char *keyword );
|
||||
@ -81,15 +95,17 @@ void display_online_help( const char *keyword );
|
||||
int encode_symmetric( const char *filename );
|
||||
int encode_store( const char *filename );
|
||||
int encode_crypt( const char *filename, STRLIST remusr );
|
||||
void encode_crypt_files(int nfiles, char **files, STRLIST remusr);
|
||||
int encrypt_filter( void *opaque, int control,
|
||||
IOBUF a, byte *buf, size_t *ret_len);
|
||||
|
||||
|
||||
/*-- sign.c --*/
|
||||
int complete_sig( PKT_signature *sig, PKT_secret_key *sk, GCRY_MD_HD md );
|
||||
int complete_sig( PKT_signature *sig, PKT_secret_key *sk, MD_HANDLE md );
|
||||
int sign_file( STRLIST filenames, int detached, STRLIST locusr,
|
||||
int do_encrypt, STRLIST remusr, const char *outfile );
|
||||
int clearsign_file( const char *fname, STRLIST locusr, const char *outfile );
|
||||
int sign_symencrypt_file (const char *fname, STRLIST locusr);
|
||||
|
||||
/*-- sig-check.c --*/
|
||||
int check_key_signature( KBNODE root, KBNODE node, int *is_selfsig );
|
||||
@ -97,17 +113,22 @@ int check_key_signature2( KBNODE root, KBNODE node,
|
||||
int *is_selfsig, u32 *r_expiredate, int *r_expired );
|
||||
|
||||
/*-- delkey.c --*/
|
||||
int delete_key( const char *username, int secure );
|
||||
int delete_keys( STRLIST names, int secret, int allow_both );
|
||||
|
||||
/*-- keyedit.c --*/
|
||||
void keyedit_menu( const char *username, STRLIST locusr, STRLIST cmds,
|
||||
int sign_mode );
|
||||
|
||||
/*-- keygen.c --*/
|
||||
u32 ask_expire_interval(int object);
|
||||
u32 ask_expiredate(void);
|
||||
void generate_keypair( const char *fname );
|
||||
int keygen_set_std_prefs (const char *string,int personal);
|
||||
char *keygen_get_std_prefs (void);
|
||||
int keygen_add_key_expire( PKT_signature *sig, void *opaque );
|
||||
int keygen_add_std_prefs( PKT_signature *sig, void *opaque );
|
||||
int keygen_upd_std_prefs( PKT_signature *sig, void *opaque );
|
||||
int keygen_add_revkey(PKT_signature *sig, void *opaque);
|
||||
int generate_subkeypair( KBNODE pub_keyblock, KBNODE sec_keyblock );
|
||||
|
||||
/*-- openfile.c --*/
|
||||
@ -121,16 +142,20 @@ void try_make_homedir( const char *fname );
|
||||
/*-- seskey.c --*/
|
||||
void make_session_key( DEK *dek );
|
||||
MPI encode_session_key( DEK *dek, unsigned nbits );
|
||||
MPI encode_md_value( int pubkey_algo, GCRY_MD_HD md,
|
||||
MPI encode_md_value( int pubkey_algo, MD_HANDLE md,
|
||||
int hash_algo, unsigned nbits, int v3compathack );
|
||||
|
||||
/*-- comment.c --*/
|
||||
KBNODE make_comment_node_from_buffer( const char *s, size_t n );
|
||||
KBNODE make_comment_node( const char *s );
|
||||
KBNODE make_mpi_comment_node( const char *s, MPI a );
|
||||
|
||||
/*-- import.c --*/
|
||||
void import_keys( char **fnames, int nnames, int fast );
|
||||
int import_keys_stream( IOBUF inp, int fast );
|
||||
void import_keys( char **fnames, int nnames, int fast, void *stats_hd );
|
||||
int import_keys_stream( IOBUF inp, int fast, void *stats_hd );
|
||||
void *import_new_stats_handle (void);
|
||||
void import_release_stats_handle (void *p);
|
||||
void import_print_stats (void *hd);
|
||||
|
||||
int collapse_uids( KBNODE *keyblock );
|
||||
|
||||
/*-- export.c --*/
|
||||
@ -146,6 +171,7 @@ int enarmor_file( const char *fname );
|
||||
/*-- revoke.c --*/
|
||||
struct revocation_reason_info;
|
||||
int gen_revoke( const char *uname );
|
||||
int gen_desig_revoke( const char *uname );
|
||||
int revocation_reason_build_cb( PKT_signature *sig, void *opaque );
|
||||
struct revocation_reason_info *
|
||||
ask_revocation_reason( int key_rev, int cert_rev, int hint );
|
||||
@ -154,22 +180,32 @@ void release_revocation_reason_info( struct revocation_reason_info *reason );
|
||||
/*-- keylist.c --*/
|
||||
void public_key_list( STRLIST list );
|
||||
void secret_key_list( STRLIST list );
|
||||
void list_keyblock( KBNODE keyblock, int secret, int fpr, void *opaque );
|
||||
void print_fingerprint (PKT_public_key *pk, PKT_secret_key *sk, int mode);
|
||||
void show_policy_url(PKT_signature *sig,int indent);
|
||||
void show_notation(PKT_signature *sig,int indent);
|
||||
void set_attrib_fd(int fd);
|
||||
|
||||
/*-- verify.c --*/
|
||||
void print_file_status( int status, const char *name, int what );
|
||||
int verify_signatures( int nfiles, char **files );
|
||||
int verify_files( int nfiles, char **files );
|
||||
|
||||
/*-- decrypt.c --*/
|
||||
int decrypt_message( const char *filename );
|
||||
void decrypt_messages(int nfiles, char **files);
|
||||
|
||||
/*-- plaintext.c --*/
|
||||
int hash_datafiles( GCRY_MD_HD md, GCRY_MD_HD md2,
|
||||
int hash_datafiles( MD_HANDLE md, MD_HANDLE md2,
|
||||
STRLIST files, const char *sigfilename, int textmode );
|
||||
|
||||
/*-- pipemode.c --*/
|
||||
void run_in_pipemode (void);
|
||||
|
||||
/*-- signal.c --*/
|
||||
void init_signals(void);
|
||||
void pause_on_sigusr( int which );
|
||||
void block_all_signals(void);
|
||||
void unblock_all_signals(void);
|
||||
|
||||
#endif /*GPG_MAIN_H*/
|
||||
#endif /*G10_MAIN_H*/
|
||||
|
833
g10/mainproc.c
833
g10/mainproc.c
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,5 @@
|
||||
/* mdfilter.c - filter data and calculate a message digest
|
||||
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
|
||||
* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
@ -25,9 +25,9 @@
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <gcrypt.h>
|
||||
#include "errors.h"
|
||||
#include "iobuf.h"
|
||||
#include "memory.h"
|
||||
#include "util.h"
|
||||
#include "filter.h"
|
||||
|
||||
@ -50,9 +50,9 @@ md_filter( void *opaque, int control,
|
||||
i = iobuf_read( a, buf, size );
|
||||
if( i == -1 ) i = 0;
|
||||
if( i ) {
|
||||
gcry_md_write(mfx->md, buf, i );
|
||||
md_write(mfx->md, buf, i );
|
||||
if( mfx->md2 )
|
||||
gcry_md_write(mfx->md2, buf, i );
|
||||
md_write(mfx->md2, buf, i );
|
||||
}
|
||||
else
|
||||
rc = -1; /* eof */
|
||||
@ -67,8 +67,8 @@ md_filter( void *opaque, int control,
|
||||
void
|
||||
free_md_filter_context( md_filter_context_t *mfx )
|
||||
{
|
||||
gcry_md_close(mfx->md);
|
||||
gcry_md_close(mfx->md2);
|
||||
md_close(mfx->md);
|
||||
md_close(mfx->md2);
|
||||
mfx->md = NULL;
|
||||
mfx->md2 = NULL;
|
||||
mfx->maxbuf_size = 0;
|
||||
|
734
g10/misc.c
734
g10/misc.c
@ -1,5 +1,5 @@
|
||||
/* misc.c - miscellaneous functions
|
||||
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
|
||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
@ -22,28 +22,44 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#ifdef HAVE_STAT
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
#if defined(__linux__) && defined(__alpha__) && __GLIBC__ < 2
|
||||
#include <asm/sysinfo.h>
|
||||
#include <asm/unistd.h>
|
||||
#endif
|
||||
#ifdef HAVE_SETRLIMIT
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/resource.h>
|
||||
#endif
|
||||
#include <assert.h>
|
||||
|
||||
#include <gcrypt.h>
|
||||
#include "util.h"
|
||||
#include "main.h"
|
||||
#include "photoid.h"
|
||||
#include "options.h"
|
||||
#include "i18n.h"
|
||||
|
||||
|
||||
#define MAX_EXTERN_MPI_BITS 16384
|
||||
const char *g10m_revision_string(int);
|
||||
const char *g10c_revision_string(int);
|
||||
const char *g10u_revision_string(int);
|
||||
|
||||
#ifdef __GNUC__
|
||||
volatile
|
||||
#endif
|
||||
void
|
||||
pull_in_libs(void)
|
||||
{
|
||||
g10m_revision_string(0);
|
||||
g10c_revision_string(0);
|
||||
g10u_revision_string(0);
|
||||
}
|
||||
|
||||
|
||||
#if defined(__linux__) && defined(__alpha__) && __GLIBC__ < 2
|
||||
#warning using trap_unaligned
|
||||
static int
|
||||
setsysinfo(unsigned long op, void *buffer, unsigned long size,
|
||||
int *start, void *arg, unsigned long flag)
|
||||
@ -68,7 +84,6 @@ trap_unaligned(void)
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
int
|
||||
disable_core_dumps()
|
||||
{
|
||||
@ -91,169 +106,26 @@ disable_core_dumps()
|
||||
|
||||
|
||||
|
||||
/****************
|
||||
* write an mpi to out.
|
||||
*/
|
||||
int
|
||||
mpi_write( IOBUF out, MPI a )
|
||||
{
|
||||
char buffer[(MAX_EXTERN_MPI_BITS+7)/8];
|
||||
size_t nbytes;
|
||||
int rc;
|
||||
|
||||
nbytes = (MAX_EXTERN_MPI_BITS+7)/8;
|
||||
rc = gcry_mpi_print( GCRYMPI_FMT_PGP, buffer, &nbytes, a );
|
||||
if( !rc )
|
||||
rc = iobuf_write( out, buffer, nbytes );
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/****************
|
||||
* Writye a MPI to out, but in this case it is an opaque one,
|
||||
* s used vor v3 protected keys.
|
||||
*/
|
||||
int
|
||||
mpi_write_opaque( IOBUF out, MPI a )
|
||||
{
|
||||
size_t nbytes, nbits;
|
||||
int rc;
|
||||
char *p;
|
||||
|
||||
assert( gcry_mpi_get_flag( a, GCRYMPI_FLAG_OPAQUE ) );
|
||||
p = gcry_mpi_get_opaque( a, &nbits );
|
||||
nbytes = (nbits+7) / 8;
|
||||
iobuf_put( out, nbits >> 8 );
|
||||
iobuf_put( out, nbits );
|
||||
rc = iobuf_write( out, p, nbytes );
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
* Read an external representation of an mpi and return the MPI
|
||||
* The external format is a 16 bit unsigned value stored in network byte order,
|
||||
* giving the number of bits for the following integer. The integer is stored
|
||||
* with MSB first (left padded with zeroes to align on a byte boundary).
|
||||
*/
|
||||
MPI
|
||||
mpi_read(IOBUF inp, unsigned int *ret_nread, int secure)
|
||||
{
|
||||
int c, c1, c2, i;
|
||||
unsigned int nbits, nbytes, nread=0;
|
||||
MPI a = NULL;
|
||||
byte *buf = NULL;
|
||||
byte *p;
|
||||
|
||||
if( (c = c1 = iobuf_get(inp)) == -1 )
|
||||
goto leave;
|
||||
nbits = c << 8;
|
||||
if( (c = c2 = iobuf_get(inp)) == -1 )
|
||||
goto leave;
|
||||
nbits |= c;
|
||||
if( nbits > MAX_EXTERN_MPI_BITS ) {
|
||||
log_error("mpi too large (%u bits)\n", nbits);
|
||||
goto leave;
|
||||
}
|
||||
nread = 2;
|
||||
nbytes = (nbits+7) / 8;
|
||||
buf = secure? gcry_xmalloc_secure( nbytes+2 ) : gcry_xmalloc( nbytes+2 );
|
||||
p = buf;
|
||||
p[0] = c1;
|
||||
p[1] = c2;
|
||||
for( i=0 ; i < nbytes; i++ ) {
|
||||
p[i+2] = iobuf_get(inp) & 0xff;
|
||||
nread++;
|
||||
}
|
||||
nread += nbytes;
|
||||
if( gcry_mpi_scan( &a, GCRYMPI_FMT_PGP, buf, &nread ) )
|
||||
a = NULL;
|
||||
|
||||
leave:
|
||||
gcry_free(buf);
|
||||
if( nread > *ret_nread )
|
||||
log_bug("mpi larger than packet");
|
||||
else
|
||||
*ret_nread = nread;
|
||||
return a;
|
||||
}
|
||||
|
||||
/****************
|
||||
* Same as mpi_read but the value is stored as an opaque MPI.
|
||||
* This function is used to read encrypted MPI of v3 packets.
|
||||
*/
|
||||
GCRY_MPI
|
||||
mpi_read_opaque(IOBUF inp, unsigned *ret_nread )
|
||||
{
|
||||
int c, c1, c2, i;
|
||||
unsigned nbits, nbytes, nread=0;
|
||||
GCRY_MPI a = NULL;
|
||||
byte *buf = NULL;
|
||||
byte *p;
|
||||
|
||||
if( (c = c1 = iobuf_get(inp)) == -1 )
|
||||
goto leave;
|
||||
nbits = c << 8;
|
||||
if( (c = c2 = iobuf_get(inp)) == -1 )
|
||||
goto leave;
|
||||
nbits |= c;
|
||||
if( nbits > MAX_EXTERN_MPI_BITS ) {
|
||||
log_error("mpi too large (%u bits)\n", nbits);
|
||||
goto leave;
|
||||
}
|
||||
nread = 2;
|
||||
nbytes = (nbits+7) / 8;
|
||||
buf = gcry_xmalloc( nbytes );
|
||||
p = buf;
|
||||
for( i=0 ; i < nbytes; i++ ) {
|
||||
p[i] = iobuf_get(inp) & 0xff;
|
||||
}
|
||||
nread += nbytes;
|
||||
a = gcry_mpi_set_opaque(NULL, buf, nbits );
|
||||
buf = NULL;
|
||||
|
||||
leave:
|
||||
gcry_free(buf);
|
||||
if( nread > *ret_nread )
|
||||
log_bug("mpi larger than packet");
|
||||
else
|
||||
*ret_nread = nread;
|
||||
return a;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
mpi_print( FILE *fp, MPI a, int mode )
|
||||
{
|
||||
int n=0;
|
||||
|
||||
if( !a )
|
||||
return fprintf(fp, "[MPI_NULL]");
|
||||
if( !mode ) {
|
||||
unsigned int n1;
|
||||
n1 = gcry_mpi_get_nbits(a);
|
||||
n += fprintf(fp, "[%u bits]", n1);
|
||||
}
|
||||
else {
|
||||
int rc;
|
||||
char *buffer;
|
||||
|
||||
rc = gcry_mpi_aprint( GCRYMPI_FMT_HEX, (void **)&buffer, NULL, a );
|
||||
assert( !rc );
|
||||
fputs( buffer, fp );
|
||||
n += strlen(buffer);
|
||||
gcry_free( buffer );
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
|
||||
u16
|
||||
checksum_u16( unsigned n )
|
||||
{
|
||||
u16 a;
|
||||
|
||||
a = (n >> 8) & 0xff;
|
||||
if( opt.emulate_bugs & EMUBUG_GPGCHKSUM ) {
|
||||
a |= n & 0xff;
|
||||
log_debug("csum_u16 emulated for n=%u\n", n);
|
||||
}
|
||||
else
|
||||
a += n & 0xff;
|
||||
return a;
|
||||
}
|
||||
|
||||
static u16
|
||||
checksum_u16_nobug( unsigned n )
|
||||
{
|
||||
u16 a;
|
||||
|
||||
a = (n >> 8) & 0xff;
|
||||
a += n & 0xff;
|
||||
return a;
|
||||
@ -272,22 +144,47 @@ checksum( byte *p, unsigned n )
|
||||
u16
|
||||
checksum_mpi( MPI a )
|
||||
{
|
||||
int rc;
|
||||
u16 csum;
|
||||
byte *buffer;
|
||||
size_t nbytes;
|
||||
unsigned nbytes;
|
||||
unsigned nbits;
|
||||
|
||||
rc = gcry_mpi_print( GCRYMPI_FMT_PGP, NULL, &nbytes, a );
|
||||
assert( !rc );
|
||||
/* fixme: for numbers not in the suecre memory we
|
||||
* should use a stack based buffer and only allocate
|
||||
* a larger one when the mpi_print return an error
|
||||
buffer = mpi_get_buffer( a, &nbytes, NULL );
|
||||
/* some versions of gpg encode wrong values for the length of an mpi
|
||||
* so that mpi_get_nbits() which counts the mpi yields another (shorter)
|
||||
* value than the one store with the mpi. mpi_get_nbit_info() returns
|
||||
* this stored value if it is still available.
|
||||
*/
|
||||
buffer = gcry_is_secure(a)? gcry_xmalloc_secure(nbytes) : gcry_xmalloc(nbytes);
|
||||
rc = gcry_mpi_print( GCRYMPI_FMT_PGP, buffer, &nbytes, a );
|
||||
assert( !rc );
|
||||
csum = checksum( buffer, nbytes );
|
||||
gcry_free( buffer );
|
||||
|
||||
if( opt.emulate_bugs & EMUBUG_GPGCHKSUM )
|
||||
nbits = 0;
|
||||
else
|
||||
nbits = mpi_get_nbit_info(a);
|
||||
if( !nbits )
|
||||
nbits = mpi_get_nbits(a);
|
||||
csum = checksum_u16( nbits );
|
||||
csum += checksum( buffer, nbytes );
|
||||
m_free( buffer );
|
||||
return csum;
|
||||
}
|
||||
|
||||
/****************
|
||||
* This is the correct function
|
||||
*/
|
||||
u16
|
||||
checksum_mpi_counted_nbits( MPI a )
|
||||
{
|
||||
u16 csum;
|
||||
byte *buffer;
|
||||
unsigned nbytes;
|
||||
unsigned nbits;
|
||||
|
||||
buffer = mpi_get_buffer( a, &nbytes, NULL );
|
||||
nbits = mpi_get_nbits(a);
|
||||
mpi_set_nbit_info(a,nbits);
|
||||
csum = checksum_u16_nobug( nbits );
|
||||
csum += checksum( buffer, nbytes );
|
||||
m_free( buffer );
|
||||
return csum;
|
||||
}
|
||||
|
||||
@ -327,11 +224,13 @@ print_cipher_algo_note( int algo )
|
||||
{
|
||||
if( algo >= 100 && algo <= 110 )
|
||||
no_exp_algo();
|
||||
else if( algo == GCRY_CIPHER_3DES
|
||||
|| algo == GCRY_CIPHER_CAST5
|
||||
|| algo == GCRY_CIPHER_BLOWFISH
|
||||
|| algo == GCRY_CIPHER_RIJNDAEL
|
||||
|| algo == GCRY_CIPHER_TWOFISH
|
||||
else if( algo == CIPHER_ALGO_3DES
|
||||
|| algo == CIPHER_ALGO_CAST5
|
||||
|| algo == CIPHER_ALGO_BLOWFISH
|
||||
|| algo == CIPHER_ALGO_TWOFISH
|
||||
|| algo == CIPHER_ALGO_RIJNDAEL
|
||||
|| algo == CIPHER_ALGO_RIJNDAEL192
|
||||
|| algo == CIPHER_ALGO_RIJNDAEL256
|
||||
)
|
||||
;
|
||||
else {
|
||||
@ -339,7 +238,7 @@ print_cipher_algo_note( int algo )
|
||||
|
||||
if( !did_note ) {
|
||||
did_note = 1;
|
||||
log_info(_("this cipher algorithm is depreciated; "
|
||||
log_info(_("this cipher algorithm is deprecated; "
|
||||
"please use a more standard one!\n"));
|
||||
}
|
||||
}
|
||||
@ -353,6 +252,32 @@ print_digest_algo_note( int algo )
|
||||
}
|
||||
|
||||
|
||||
/* Return a string which is used as a kind of process ID */
|
||||
const byte *
|
||||
get_session_marker( size_t *rlen )
|
||||
{
|
||||
static byte marker[SIZEOF_UNSIGNED_LONG*2];
|
||||
static int initialized;
|
||||
|
||||
if ( !initialized ) {
|
||||
volatile ulong aa, bb; /* we really want the uninitialized value */
|
||||
ulong a, b;
|
||||
|
||||
initialized = 1;
|
||||
/* also this marker is guessable it is not easy to use this
|
||||
* for a faked control packet because an attacker does not
|
||||
* have enough control about the time the verification does
|
||||
* take place. Of course, we can add just more random but
|
||||
* than we need the random generator even for verification
|
||||
* tasks - which does not make sense. */
|
||||
a = aa ^ (ulong)getpid();
|
||||
b = bb ^ (ulong)time(NULL);
|
||||
memcpy( marker, &a, SIZEOF_UNSIGNED_LONG );
|
||||
memcpy( marker+SIZEOF_UNSIGNED_LONG, &b, SIZEOF_UNSIGNED_LONG );
|
||||
}
|
||||
*rlen = sizeof(marker);
|
||||
return marker;
|
||||
}
|
||||
|
||||
/****************
|
||||
* Wrapper around the libgcrypt function with addional checks on
|
||||
@ -362,122 +287,405 @@ int
|
||||
openpgp_cipher_test_algo( int algo )
|
||||
{
|
||||
if( algo < 0 || algo > 110 )
|
||||
return GCRYERR_INV_CIPHER_ALGO;
|
||||
return gcry_cipher_test_algo(algo);
|
||||
return G10ERR_CIPHER_ALGO;
|
||||
return check_cipher_algo(algo);
|
||||
}
|
||||
|
||||
int
|
||||
openpgp_pk_test_algo( int algo, unsigned int usage_flags )
|
||||
{
|
||||
size_t n = usage_flags;
|
||||
|
||||
if( algo < 0 || algo > 110 )
|
||||
return GCRYERR_INV_PK_ALGO;
|
||||
return gcry_pk_algo_info( algo, GCRYCTL_TEST_ALGO, NULL, &n );
|
||||
return G10ERR_PUBKEY_ALGO;
|
||||
return check_pubkey_algo2( algo, usage_flags );
|
||||
}
|
||||
|
||||
int
|
||||
openpgp_pk_algo_usage ( int algo )
|
||||
{
|
||||
int usage = 0;
|
||||
int use = 0;
|
||||
|
||||
/* some are hardwired */
|
||||
/* they are hardwired in gpg 1.0 */
|
||||
switch ( algo ) {
|
||||
case GCRY_PK_RSA:
|
||||
usage = GCRY_PK_USAGE_SIGN | GCRY_PK_USAGE_ENCR;
|
||||
case PUBKEY_ALGO_RSA:
|
||||
use = PUBKEY_USAGE_SIG | PUBKEY_USAGE_ENC;
|
||||
break;
|
||||
case GCRY_PK_RSA_E:
|
||||
usage = GCRY_PK_USAGE_ENCR;
|
||||
case PUBKEY_ALGO_RSA_E:
|
||||
use = PUBKEY_USAGE_ENC;
|
||||
break;
|
||||
case GCRY_PK_RSA_S:
|
||||
usage = GCRY_PK_USAGE_SIGN;
|
||||
case PUBKEY_ALGO_RSA_S:
|
||||
use = PUBKEY_USAGE_SIG;
|
||||
break;
|
||||
case GCRY_PK_ELG_E:
|
||||
usage = GCRY_PK_USAGE_ENCR;
|
||||
case PUBKEY_ALGO_ELGAMAL_E:
|
||||
use = PUBKEY_USAGE_ENC;
|
||||
break;
|
||||
case GCRY_PK_DSA:
|
||||
usage = GCRY_PK_USAGE_SIGN;
|
||||
case PUBKEY_ALGO_DSA:
|
||||
use = PUBKEY_USAGE_SIG;
|
||||
break;
|
||||
case GCRY_PK_ELG:
|
||||
usage = GCRY_PK_USAGE_SIGN | GCRY_PK_USAGE_ENCR;
|
||||
case PUBKEY_ALGO_ELGAMAL:
|
||||
use = PUBKEY_USAGE_SIG | PUBKEY_USAGE_ENC;
|
||||
break;
|
||||
default:
|
||||
usage = gcry_pk_algo_info ( algo, GCRYCTL_GET_ALGO_USAGE,
|
||||
NULL, NULL);
|
||||
break;
|
||||
}
|
||||
return usage;
|
||||
|
||||
return use;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
openpgp_md_test_algo( int algo )
|
||||
{
|
||||
if( algo < 0 || algo > 110 )
|
||||
return GCRYERR_INV_MD_ALGO;
|
||||
return gcry_md_test_algo(algo);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
pubkey_get_npkey( int algo )
|
||||
{
|
||||
int n = gcry_pk_algo_info( algo, GCRYCTL_GET_ALGO_NPKEY, NULL, 0 );
|
||||
return n > 0? n : 0;
|
||||
return G10ERR_DIGEST_ALGO;
|
||||
return check_digest_algo(algo);
|
||||
}
|
||||
|
||||
int
|
||||
pubkey_get_nskey( int algo )
|
||||
check_permissions(const char *path,int extension,int checkonly)
|
||||
{
|
||||
int n = gcry_pk_algo_info( algo, GCRYCTL_GET_ALGO_NSKEY, NULL, 0 );
|
||||
return n > 0? n : 0;
|
||||
}
|
||||
#if defined(HAVE_STAT) && !defined(HAVE_DOSISH_SYSTEM)
|
||||
char *tmppath;
|
||||
struct stat statbuf;
|
||||
int ret=1;
|
||||
int isdir=0;
|
||||
|
||||
int
|
||||
pubkey_get_nsig( int algo )
|
||||
{
|
||||
int n = gcry_pk_algo_info( algo, GCRYCTL_GET_ALGO_NSIGN, NULL, 0 );
|
||||
return n > 0? n : 0;
|
||||
}
|
||||
if(opt.no_perm_warn)
|
||||
return 0;
|
||||
|
||||
int
|
||||
pubkey_get_nenc( int algo )
|
||||
{
|
||||
int n = gcry_pk_algo_info( algo, GCRYCTL_GET_ALGO_NENCR, NULL, 0 );
|
||||
return n > 0? n : 0;
|
||||
}
|
||||
|
||||
|
||||
unsigned int
|
||||
pubkey_nbits( int algo, MPI *key )
|
||||
{
|
||||
int rc, nbits;
|
||||
GCRY_SEXP sexp;
|
||||
|
||||
if( algo == GCRY_PK_DSA ) {
|
||||
rc = gcry_sexp_build ( &sexp, NULL,
|
||||
"(public-key(dsa(p%m)(q%m)(g%m)(y%m)))",
|
||||
key[0], key[1], key[2], key[3] );
|
||||
if(extension && path[0]!=DIRSEP_C)
|
||||
{
|
||||
if(strchr(path,DIRSEP_C))
|
||||
tmppath=make_filename(path,NULL);
|
||||
else
|
||||
tmppath=make_filename(GNUPG_LIBDIR,path,NULL);
|
||||
}
|
||||
else if( algo == GCRY_PK_ELG || algo == GCRY_PK_ELG_E ) {
|
||||
rc = gcry_sexp_build ( &sexp, NULL,
|
||||
"(public-key(elg(p%m)(g%m)(y%m)))",
|
||||
key[0], key[1], key[2] );
|
||||
else
|
||||
tmppath=m_strdup(path);
|
||||
|
||||
/* It's okay if the file doesn't exist */
|
||||
if(stat(tmppath,&statbuf)!=0)
|
||||
{
|
||||
ret=0;
|
||||
goto end;
|
||||
}
|
||||
else if( algo == GCRY_PK_RSA ) {
|
||||
rc = gcry_sexp_build ( &sexp, NULL,
|
||||
"(public-key(rsa(n%m)(e%m)))",
|
||||
key[0], key[1] );
|
||||
|
||||
isdir=S_ISDIR(statbuf.st_mode);
|
||||
|
||||
/* We may have to revisit this if we start piping keyrings to gpg
|
||||
over a named pipe or keyserver character device :) */
|
||||
if(!isdir && !S_ISREG(statbuf.st_mode))
|
||||
{
|
||||
ret=0;
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* Per-user files must be owned by the user. Extensions must be
|
||||
owned by the user or root. */
|
||||
if((!extension && statbuf.st_uid != getuid()) ||
|
||||
(extension && statbuf.st_uid!=0 && statbuf.st_uid!=getuid()))
|
||||
{
|
||||
if(!checkonly)
|
||||
log_info(_("Warning: unsafe ownership on %s \"%s\"\n"),
|
||||
isdir?"directory":extension?"extension":"file",path);
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* This works for both directories and files - basically, we don't
|
||||
care what the owner permissions are, so long as the group and
|
||||
other permissions are 0 for per-user files, and non-writable for
|
||||
extensions. */
|
||||
if((extension && (statbuf.st_mode & (S_IWGRP|S_IWOTH)) !=0) ||
|
||||
(!extension && (statbuf.st_mode & (S_IRWXG|S_IRWXO)) != 0))
|
||||
{
|
||||
char *dir;
|
||||
|
||||
/* However, if the directory the directory/file is in is owned
|
||||
by the user and is 700, then this is not a problem.
|
||||
Theoretically, we could walk this test up to the root
|
||||
directory /, but for the sake of sanity, I'm stopping at one
|
||||
level down. */
|
||||
|
||||
dir=make_dirname(tmppath);
|
||||
if(stat(dir,&statbuf)==0 && statbuf.st_uid==getuid() &&
|
||||
S_ISDIR(statbuf.st_mode) && (statbuf.st_mode & (S_IRWXG|S_IRWXO))==0)
|
||||
{
|
||||
m_free(dir);
|
||||
ret=0;
|
||||
goto end;
|
||||
}
|
||||
|
||||
m_free(dir);
|
||||
|
||||
if(!checkonly)
|
||||
log_info(_("Warning: unsafe permissions on %s \"%s\"\n"),
|
||||
isdir?"directory":extension?"extension":"file",path);
|
||||
goto end;
|
||||
}
|
||||
|
||||
ret=0;
|
||||
|
||||
end:
|
||||
m_free(tmppath);
|
||||
|
||||
return ret;
|
||||
|
||||
#endif /* HAVE_STAT && !HAVE_DOSISH_SYSTEM */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Special warning for the IDEA cipher */
|
||||
void
|
||||
idea_cipher_warn(int show)
|
||||
{
|
||||
static int warned=0;
|
||||
|
||||
if(!warned || show)
|
||||
{
|
||||
log_info(_("the IDEA cipher plugin is not present\n"));
|
||||
log_info(_("please see http://www.gnupg.org/why-not-idea.html "
|
||||
"for more information\n"));
|
||||
warned=1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Expand %-strings. Returns a string which must be m_freed. Returns
|
||||
NULL if the string cannot be expanded (too large). */
|
||||
char *
|
||||
pct_expando(const char *string,struct expando_args *args)
|
||||
{
|
||||
const char *ch=string;
|
||||
int idx=0,maxlen=0,done=0;
|
||||
u32 pk_keyid[2]={0,0},sk_keyid[2]={0,0};
|
||||
char *ret=NULL;
|
||||
|
||||
if(args->pk)
|
||||
keyid_from_pk(args->pk,pk_keyid);
|
||||
|
||||
if(args->sk)
|
||||
keyid_from_sk(args->sk,sk_keyid);
|
||||
|
||||
if(!args->pk && args->sk)
|
||||
keyid_from_sk(args->sk,pk_keyid);
|
||||
|
||||
while(*ch!='\0')
|
||||
{
|
||||
char *str=NULL;
|
||||
|
||||
if(!done)
|
||||
{
|
||||
/* 8192 is way bigger than we'll need here */
|
||||
if(maxlen>=8192)
|
||||
goto fail;
|
||||
|
||||
maxlen+=1024;
|
||||
ret=m_realloc(ret,maxlen);
|
||||
}
|
||||
|
||||
done=0;
|
||||
|
||||
if(*ch=='%')
|
||||
{
|
||||
switch(*(ch+1))
|
||||
{
|
||||
case 's': /* short key id */
|
||||
if(idx+8<maxlen)
|
||||
{
|
||||
sprintf(&ret[idx],"%08lX",(ulong)sk_keyid[1]);
|
||||
idx+=8;
|
||||
done=1;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'S': /* long key id */
|
||||
if(idx+16<maxlen)
|
||||
{
|
||||
sprintf(&ret[idx],"%08lX%08lX",
|
||||
(ulong)sk_keyid[0],(ulong)sk_keyid[1]);
|
||||
idx+=16;
|
||||
done=1;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'k': /* short key id */
|
||||
if(idx+8<maxlen)
|
||||
{
|
||||
sprintf(&ret[idx],"%08lX",(ulong)pk_keyid[1]);
|
||||
idx+=8;
|
||||
done=1;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'K': /* long key id */
|
||||
if(idx+16<maxlen)
|
||||
{
|
||||
sprintf(&ret[idx],"%08lX%08lX",
|
||||
(ulong)pk_keyid[0],(ulong)pk_keyid[1]);
|
||||
idx+=16;
|
||||
done=1;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'f': /* fingerprint */
|
||||
{
|
||||
byte array[MAX_FINGERPRINT_LEN];
|
||||
size_t len;
|
||||
int i;
|
||||
|
||||
if(args->pk)
|
||||
fingerprint_from_pk(args->pk,array,&len);
|
||||
else
|
||||
memset(array,0,MAX_FINGERPRINT_LEN);
|
||||
|
||||
if(idx+(len*2)<maxlen)
|
||||
{
|
||||
for(i=0;i<len;i++)
|
||||
{
|
||||
sprintf(&ret[idx],"%02X",array[i]);
|
||||
idx+=2;
|
||||
}
|
||||
done=1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 't': /* e.g. "jpg" */
|
||||
str=image_type_to_string(args->imagetype,0);
|
||||
/* fall through */
|
||||
|
||||
case 'T': /* e.g. "image/jpeg" */
|
||||
if(str==NULL)
|
||||
str=image_type_to_string(args->imagetype,2);
|
||||
|
||||
if(idx+strlen(str)<maxlen)
|
||||
{
|
||||
strcpy(&ret[idx],str);
|
||||
idx+=strlen(str);
|
||||
done=1;
|
||||
}
|
||||
break;
|
||||
|
||||
case '%':
|
||||
if(idx+1<maxlen)
|
||||
{
|
||||
ret[idx++]='%';
|
||||
ret[idx]='\0';
|
||||
done=1;
|
||||
}
|
||||
break;
|
||||
|
||||
/* Any unknown %-keys (like %i, %o, %I, and %O) are
|
||||
passed through for later expansion. Note this also
|
||||
handles the case where the last character in the
|
||||
string is a '%' - the terminating \0 will end up here
|
||||
and properly terminate the string. */
|
||||
default:
|
||||
if(idx+2<maxlen)
|
||||
{
|
||||
ret[idx++]='%';
|
||||
ret[idx++]=*(ch+1);
|
||||
ret[idx]='\0';
|
||||
done=1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if(done)
|
||||
ch++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(idx+1<maxlen)
|
||||
{
|
||||
ret[idx++]=*ch;
|
||||
ret[idx]='\0';
|
||||
done=1;
|
||||
}
|
||||
}
|
||||
|
||||
if(done)
|
||||
ch++;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
fail:
|
||||
m_free(ret);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
hextobyte( const char *s )
|
||||
{
|
||||
int c;
|
||||
|
||||
if( *s >= '0' && *s <= '9' )
|
||||
c = 16 * (*s - '0');
|
||||
else if( *s >= 'A' && *s <= 'F' )
|
||||
c = 16 * (10 + *s - 'A');
|
||||
else if( *s >= 'a' && *s <= 'f' )
|
||||
c = 16 * (10 + *s - 'a');
|
||||
else
|
||||
return 0;
|
||||
|
||||
if ( rc )
|
||||
BUG ();
|
||||
|
||||
nbits = gcry_pk_get_nbits( sexp );
|
||||
gcry_sexp_release( sexp );
|
||||
return nbits;
|
||||
return -1;
|
||||
s++;
|
||||
if( *s >= '0' && *s <= '9' )
|
||||
c += *s - '0';
|
||||
else if( *s >= 'A' && *s <= 'F' )
|
||||
c += 10 + *s - 'A';
|
||||
else if( *s >= 'a' && *s <= 'f' )
|
||||
c += 10 + *s - 'a';
|
||||
else
|
||||
return -1;
|
||||
return c;
|
||||
}
|
||||
|
||||
void
|
||||
deprecated_warning(const char *configname,unsigned int configlineno,
|
||||
const char *option,const char *repl1,const char *repl2)
|
||||
{
|
||||
if(configname)
|
||||
{
|
||||
if(strncmp("--",option,2)==0)
|
||||
option+=2;
|
||||
|
||||
if(strncmp("--",repl1,2)==0)
|
||||
repl1+=2;
|
||||
|
||||
log_info(_("%s:%d: deprecated option \"%s\"\n"),
|
||||
configname,configlineno,option);
|
||||
}
|
||||
else
|
||||
log_info(_("WARNING: \"%s\" is a deprecated option\n"),option);
|
||||
|
||||
log_info(_("please use \"%s%s\" instead\n"),repl1,repl2);
|
||||
}
|
||||
|
||||
const char *
|
||||
compress_algo_to_string(int algo)
|
||||
{
|
||||
const char *s="?";
|
||||
|
||||
switch(algo)
|
||||
{
|
||||
case 0:
|
||||
s="Uncompressed";
|
||||
break;
|
||||
|
||||
case 1:
|
||||
s="ZIP";
|
||||
break;
|
||||
|
||||
case 2:
|
||||
s="ZLIB";
|
||||
break;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
int
|
||||
check_compress_algo(int algo)
|
||||
{
|
||||
if(algo>=0 && algo<=2)
|
||||
return 0;
|
||||
|
||||
return G10ERR_COMPR_ALGO;
|
||||
}
|
||||
|
98
g10/mkdtemp.c
Normal file
98
g10/mkdtemp.c
Normal file
@ -0,0 +1,98 @@
|
||||
/* mkdtemp.c - libc replacement function
|
||||
* Copyright (C) 2001 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
* GnuPG is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GnuPG is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
/* This is a replacement function for mkdtemp in case the platform
|
||||
we're building on (like mine!) doesn't have it. */
|
||||
|
||||
#include <config.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include "types.h"
|
||||
#include "cipher.h"
|
||||
|
||||
#ifdef MKDIR_TAKES_ONE_ARG
|
||||
# undef mkdir
|
||||
# define mkdir(a,b) mkdir(a)
|
||||
#endif
|
||||
|
||||
char *mkdtemp(char *template)
|
||||
{
|
||||
int attempts,idx,count=0;
|
||||
byte *ch;
|
||||
|
||||
idx=strlen(template);
|
||||
|
||||
/* Walk backwards to count all the Xes */
|
||||
while(idx>0 && template[idx-1]=='X')
|
||||
{
|
||||
count++;
|
||||
idx--;
|
||||
}
|
||||
|
||||
if(count==0)
|
||||
{
|
||||
errno=EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ch=&template[idx];
|
||||
|
||||
/* Try 4 times to make the temp directory */
|
||||
for(attempts=0;attempts<4;attempts++)
|
||||
{
|
||||
int remaining=count;
|
||||
char *marker=ch;
|
||||
byte *randombits;
|
||||
|
||||
idx=0;
|
||||
|
||||
/* Using really random bits is probably overkill here. The
|
||||
worst thing that can happen with a directory name collision
|
||||
is that the function will return an error. */
|
||||
|
||||
randombits=get_random_bits(4*remaining,0,0);
|
||||
|
||||
while(remaining>1)
|
||||
{
|
||||
sprintf(marker,"%02X",randombits[idx++]);
|
||||
marker+=2;
|
||||
remaining-=2;
|
||||
}
|
||||
|
||||
/* Any leftover Xes? get_random_bits rounds up to full bytes,
|
||||
so this is safe. */
|
||||
if(remaining>0)
|
||||
sprintf(marker,"%X",randombits[idx]&0xF);
|
||||
|
||||
m_free(randombits);
|
||||
|
||||
if(mkdir(template,0700)==0)
|
||||
break;
|
||||
}
|
||||
|
||||
if(attempts==4)
|
||||
return NULL; /* keeps the errno from mkdir, whatever it is */
|
||||
|
||||
return template;
|
||||
}
|
102
g10/openfile.c
102
g10/openfile.c
@ -1,5 +1,5 @@
|
||||
/* openfile.c
|
||||
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
|
||||
* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
@ -29,7 +29,7 @@
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include "util.h"
|
||||
#include <gcrypt.h>
|
||||
#include "memory.h"
|
||||
#include "ttyio.h"
|
||||
#include "options.h"
|
||||
#include "main.h"
|
||||
@ -39,11 +39,11 @@
|
||||
#ifdef USE_ONLY_8DOT3
|
||||
#define SKELEXT ".skl"
|
||||
#else
|
||||
#define SKELEXT ".skel"
|
||||
#define SKELEXT EXTSEP_S "skel"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_DRIVE_LETTERS
|
||||
#define CMP_FILENAME(a,b) stricmp( (a), (b) )
|
||||
#if defined (HAVE_DRIVE_LETTERS) || defined (__riscos__)
|
||||
#define CMP_FILENAME(a,b) ascii_strcasecmp( (a), (b) )
|
||||
#else
|
||||
#define CMP_FILENAME(a,b) strcmp( (a), (b) )
|
||||
#endif
|
||||
@ -99,24 +99,23 @@ make_outfile_name( const char *iname )
|
||||
size_t n;
|
||||
|
||||
if( (!iname || (*iname=='-' && !iname[1]) ))
|
||||
return gcry_xstrdup("-");
|
||||
return m_strdup("-");
|
||||
|
||||
n = strlen(iname);
|
||||
if( n > 4 && ( !CMP_FILENAME(iname+n-4,".gpg")
|
||||
|| !CMP_FILENAME(iname+n-4,".pgp")
|
||||
|| !CMP_FILENAME(iname+n-4,".sig")
|
||||
|| !CMP_FILENAME(iname+n-4,".asc") ) ) {
|
||||
char *buf = gcry_xstrdup( iname );
|
||||
if( n > 4 && ( !CMP_FILENAME(iname+n-4, EXTSEP_S "gpg")
|
||||
|| !CMP_FILENAME(iname+n-4, EXTSEP_S "pgp")
|
||||
|| !CMP_FILENAME(iname+n-4, EXTSEP_S "sig")
|
||||
|| !CMP_FILENAME(iname+n-4, EXTSEP_S "asc") ) ) {
|
||||
char *buf = m_strdup( iname );
|
||||
buf[n-4] = 0;
|
||||
return buf;
|
||||
}
|
||||
else if( n > 5 && !CMP_FILENAME(iname+n-5,".sign") ) {
|
||||
char *buf = gcry_xstrdup( iname );
|
||||
else if( n > 5 && !CMP_FILENAME(iname+n-5, EXTSEP_S "sign") ) {
|
||||
char *buf = m_strdup( iname );
|
||||
buf[n-5] = 0;
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
log_info(_("%s: unknown suffix\n"), iname );
|
||||
return NULL;
|
||||
}
|
||||
@ -143,19 +142,21 @@ ask_outfile_name( const char *name, size_t namelen )
|
||||
|
||||
n = strlen(s) + namelen + 10;
|
||||
defname = name && namelen? make_printable_string( name, namelen, 0): NULL;
|
||||
prompt = gcry_xmalloc(n);
|
||||
prompt = m_alloc(n);
|
||||
if( defname )
|
||||
sprintf(prompt, "%s [%s]: ", s, defname );
|
||||
else
|
||||
sprintf(prompt, "%s: ", s );
|
||||
fname = cpr_get("openfile.askoutname", prompt );
|
||||
cpr_kill_prompt();
|
||||
gcry_free(prompt);
|
||||
m_free(prompt);
|
||||
if( !*fname ) {
|
||||
gcry_free( fname ); fname = NULL;
|
||||
m_free( fname ); fname = NULL;
|
||||
fname = defname; defname = NULL;
|
||||
}
|
||||
gcry_free(defname);
|
||||
m_free(defname);
|
||||
if (fname)
|
||||
trim_spaces (fname);
|
||||
return fname;
|
||||
}
|
||||
|
||||
@ -177,7 +178,7 @@ open_outfile( const char *iname, int mode, IOBUF *a )
|
||||
if( (!iname || (*iname=='-' && !iname[1])) && !opt.outfile ) {
|
||||
if( !(*a = iobuf_create(NULL)) ) {
|
||||
log_error(_("%s: can't open: %s\n"), "[stdout]", strerror(errno) );
|
||||
rc = GPGERR_CREATE_FILE;
|
||||
rc = G10ERR_CREATE_FILE;
|
||||
}
|
||||
else if( opt.verbose )
|
||||
log_info(_("writing to stdout\n"));
|
||||
@ -203,7 +204,7 @@ open_outfile( const char *iname, int mode, IOBUF *a )
|
||||
const char *newsfx = mode==1 ? ".asc" :
|
||||
mode==2 ? ".sig" : ".gpg";
|
||||
|
||||
buf = gcry_xmalloc(strlen(iname)+4+1);
|
||||
buf = m_alloc(strlen(iname)+4+1);
|
||||
strcpy(buf,iname);
|
||||
dot = strchr(buf, '.' );
|
||||
if( dot && dot > buf && dot[1] && strlen(dot) <= 4
|
||||
@ -215,24 +216,34 @@ open_outfile( const char *iname, int mode, IOBUF *a )
|
||||
else
|
||||
strcat( buf, newsfx );
|
||||
#else
|
||||
buf = gcry_xmalloc(strlen(iname)+4+1);
|
||||
strcpy(stpcpy(buf,iname), mode==1 ? ".asc" :
|
||||
mode==2 ? ".sig" : ".gpg");
|
||||
buf = m_alloc(strlen(iname)+4+1);
|
||||
strcpy(stpcpy(buf,iname), mode==1 ? EXTSEP_S "asc" :
|
||||
mode==2 ? EXTSEP_S "sig" : EXTSEP_S "gpg");
|
||||
#endif
|
||||
name = buf;
|
||||
}
|
||||
|
||||
if( overwrite_filep( name ) ) {
|
||||
rc = 0;
|
||||
while( !overwrite_filep (name) ) {
|
||||
char *tmp = ask_outfile_name (NULL, 0);
|
||||
if ( !tmp || !*tmp ) {
|
||||
m_free (tmp);
|
||||
rc = G10ERR_FILE_EXISTS;
|
||||
break;
|
||||
}
|
||||
m_free (buf);
|
||||
name = buf = tmp;
|
||||
}
|
||||
|
||||
if( !rc ) {
|
||||
if( !(*a = iobuf_create( name )) ) {
|
||||
log_error(_("%s: can't create: %s\n"), name, strerror(errno) );
|
||||
rc = GPGERR_CREATE_FILE;
|
||||
rc = G10ERR_CREATE_FILE;
|
||||
}
|
||||
else if( opt.verbose )
|
||||
log_info(_("writing to `%s'\n"), name );
|
||||
}
|
||||
else
|
||||
rc = GPGERR_FILE_EXISTS;
|
||||
gcry_free(buf);
|
||||
m_free(buf);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
@ -251,16 +262,16 @@ open_sigfile( const char *iname )
|
||||
|
||||
if( iname && !(*iname == '-' && !iname[1]) ) {
|
||||
len = strlen(iname);
|
||||
if( len > 4 && ( !strcmp(iname + len - 4, ".sig")
|
||||
|| ( len > 5 && !strcmp(iname + len - 5, ".sign") )
|
||||
|| !strcmp(iname + len - 4, ".asc")) ) {
|
||||
if( len > 4 && ( !strcmp(iname + len - 4, EXTSEP_S "sig")
|
||||
|| ( len > 5 && !strcmp(iname + len - 5, EXTSEP_S "sign") )
|
||||
|| !strcmp(iname + len - 4, EXTSEP_S "asc")) ) {
|
||||
char *buf;
|
||||
buf = gcry_xstrdup(iname);
|
||||
buf[len-4] = 0 ;
|
||||
buf = m_strdup(iname);
|
||||
buf[len-(buf[len-1]=='n'?5:4)] = 0 ;
|
||||
a = iobuf_open( buf );
|
||||
if( opt.verbose )
|
||||
if( a && opt.verbose )
|
||||
log_info(_("assuming signed data in `%s'\n"), buf );
|
||||
gcry_free(buf);
|
||||
m_free(buf);
|
||||
}
|
||||
}
|
||||
return a;
|
||||
@ -282,20 +293,20 @@ copy_options_file( const char *destdir )
|
||||
if( opt.dry_run )
|
||||
return;
|
||||
|
||||
fname = gcry_xmalloc( strlen(datadir) + strlen(destdir) + 15 );
|
||||
strcpy(stpcpy(fname, datadir), "/options" SKELEXT );
|
||||
fname = m_alloc( strlen(datadir) + strlen(destdir) + 15 );
|
||||
strcpy(stpcpy(fname, datadir), DIRSEP_S "options" SKELEXT );
|
||||
src = fopen( fname, "r" );
|
||||
if( !src ) {
|
||||
log_error(_("%s: can't open: %s\n"), fname, strerror(errno) );
|
||||
gcry_free(fname);
|
||||
m_free(fname);
|
||||
return;
|
||||
}
|
||||
strcpy(stpcpy(fname, destdir), "/options" );
|
||||
strcpy(stpcpy(fname, destdir), DIRSEP_S "options" );
|
||||
dst = fopen( fname, "w" );
|
||||
if( !dst ) {
|
||||
log_error(_("%s: can't create: %s\n"), fname, strerror(errno) );
|
||||
fclose( src );
|
||||
gcry_free(fname);
|
||||
m_free(fname);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -310,7 +321,7 @@ copy_options_file( const char *destdir )
|
||||
fclose( dst );
|
||||
fclose( src );
|
||||
log_info(_("%s: new options file created\n"), fname );
|
||||
gcry_free(fname);
|
||||
m_free(fname);
|
||||
}
|
||||
|
||||
|
||||
@ -325,12 +336,12 @@ try_make_homedir( const char *fname )
|
||||
* To cope with HOME, we do compare only the suffix if we see that
|
||||
* the default homedir does start with a tilde.
|
||||
*/
|
||||
if( opt.dry_run )
|
||||
if( opt.dry_run || opt.no_homedir_creation )
|
||||
return;
|
||||
|
||||
if ( ( *defhome == '~'
|
||||
&& ( strlen(fname) >= strlen (defhome+1)
|
||||
&& !strcmp(fname+strlen(defhome+1)-strlen(defhome+1),
|
||||
&& !strcmp(fname+strlen(fname)-strlen(defhome+1),
|
||||
defhome+1 ) ))
|
||||
|| ( *defhome != '~'
|
||||
&& !compare_filenames( fname, defhome ) )
|
||||
@ -343,9 +354,6 @@ try_make_homedir( const char *fname )
|
||||
copy_options_file( fname );
|
||||
log_info(_("you have to start GnuPG again, "
|
||||
"so it can read the new options file\n") );
|
||||
gpg_exit(1);
|
||||
g10_exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
103
g10/options.h
103
g10/options.h
@ -1,5 +1,5 @@
|
||||
/* options.h
|
||||
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
|
||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
@ -17,52 +17,82 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifndef GPG_OPTIONS_H
|
||||
#define GPG_OPTIONS_H
|
||||
#ifndef G10_OPTIONS_H
|
||||
#define G10_OPTIONS_H
|
||||
|
||||
#include <types.h>
|
||||
#include "main.h"
|
||||
#include "packet.h"
|
||||
|
||||
#undef ENABLE_COMMENT_PACKETS /* don't create comment packets */
|
||||
|
||||
#ifndef EXTERN_UNLESS_MAIN_MODULE
|
||||
/* Norcraft can't cope with common symbols */
|
||||
#if defined (__riscos__) && !defined (INCLUDED_BY_MAIN_MODULE)
|
||||
#define EXTERN_UNLESS_MAIN_MODULE extern
|
||||
#else
|
||||
#define EXTERN_UNLESS_MAIN_MODULE
|
||||
#endif
|
||||
#endif
|
||||
|
||||
EXTERN_UNLESS_MAIN_MODULE
|
||||
struct {
|
||||
int verbose;
|
||||
int quiet;
|
||||
unsigned int debug;
|
||||
unsigned debug;
|
||||
int armor;
|
||||
int compress;
|
||||
char *outfile;
|
||||
int dry_run;
|
||||
int list_only;
|
||||
int textmode;
|
||||
int expert;
|
||||
int ask_sig_expire;
|
||||
int ask_cert_expire;
|
||||
int batch; /* run in batch mode */
|
||||
int answer_yes; /* answer yes on most questions */
|
||||
int answer_no; /* answer no on most questions */
|
||||
int check_sigs; /* check key signatures */
|
||||
int with_colons;
|
||||
int with_key_data;
|
||||
int with_fingerprint; /* opt --with-fingerprint active */
|
||||
int fingerprint; /* list fingerprints */
|
||||
int list_sigs; /* list signatures */
|
||||
int no_armor;
|
||||
int list_packets; /* list-packets mode */
|
||||
int list_packets; /* list-packets mode: 1=normal, 2=invoked by command*/
|
||||
int def_cipher_algo;
|
||||
int force_v3_sigs;
|
||||
int force_v4_certs;
|
||||
int force_mdc;
|
||||
int disable_mdc;
|
||||
int def_digest_algo;
|
||||
int cert_digest_algo;
|
||||
int def_compress_algo;
|
||||
const char *def_secret_key;
|
||||
char *def_recipient;
|
||||
int def_recipient_self;
|
||||
int no_comment;
|
||||
int def_cert_check_level;
|
||||
int sk_comments;
|
||||
int no_version;
|
||||
int marginals_needed;
|
||||
int completes_needed;
|
||||
int max_cert_depth;
|
||||
const char *homedir;
|
||||
|
||||
char *display; /* 5 options to be passed to the gpg-agent */
|
||||
char *ttyname;
|
||||
char *ttytype;
|
||||
char *lc_ctype;
|
||||
char *lc_messages;
|
||||
|
||||
int skip_verify;
|
||||
int compress_keys;
|
||||
int compress_sigs;
|
||||
int always_trust;
|
||||
int pgp2;
|
||||
int pgp6;
|
||||
int pgp7; /* if we get any more of these, it's time to look at a
|
||||
special emulate_pgp variable... */
|
||||
int rfc1991;
|
||||
int rfc2440;
|
||||
int pgp2_workarounds;
|
||||
@ -71,33 +101,77 @@ struct {
|
||||
const char *set_filename;
|
||||
const char *comment_string;
|
||||
int throw_keyid;
|
||||
int show_photos;
|
||||
const char *photo_viewer;
|
||||
int s2k_mode;
|
||||
int s2k_digest_algo;
|
||||
int s2k_cipher_algo;
|
||||
int simple_sk_checksum; /* create the deprecated rfc2440 secret
|
||||
key protection*/
|
||||
int not_dash_escaped;
|
||||
int escape_from;
|
||||
int lock_once;
|
||||
const char *keyserver_name;
|
||||
char *keyserver_scheme;
|
||||
char *keyserver_host;
|
||||
char *keyserver_port;
|
||||
struct
|
||||
{
|
||||
int verbose;
|
||||
int include_revoked;
|
||||
int include_disabled;
|
||||
int include_subkeys;
|
||||
int honor_http_proxy;
|
||||
int broken_http_proxy;
|
||||
int use_temp_files;
|
||||
int keep_temp_files;
|
||||
int fake_v3_keyids;
|
||||
int auto_key_retrieve;
|
||||
STRLIST other;
|
||||
} keyserver_options;
|
||||
int exec_disable;
|
||||
char *def_preference_list;
|
||||
prefitem_t *personal_cipher_prefs,
|
||||
*personal_digest_prefs,
|
||||
*personal_compress_prefs;
|
||||
int no_perm_warn;
|
||||
char *temp_dir;
|
||||
int no_encrypt_to;
|
||||
int interactive;
|
||||
STRLIST notation_data;
|
||||
const char *set_policy_url;
|
||||
STRLIST sig_notation_data;
|
||||
STRLIST cert_notation_data;
|
||||
int show_notation;
|
||||
STRLIST sig_policy_url;
|
||||
STRLIST cert_policy_url;
|
||||
int show_policy_url;
|
||||
int use_embedded_filename;
|
||||
int allow_non_selfsigned_uid;
|
||||
int allow_freeform_uid;
|
||||
int no_literal;
|
||||
ulong set_filesize;
|
||||
int honor_http_proxy;
|
||||
int fast_list_mode;
|
||||
int fixed_list_mode;
|
||||
int ignore_time_conflict;
|
||||
int ignore_valid_from;
|
||||
int ignore_crc_error;
|
||||
int command_fd;
|
||||
int auto_key_retrieve;
|
||||
const char *override_session_key;
|
||||
int show_session_key;
|
||||
int use_agent;
|
||||
const char *gpg_agent_info;
|
||||
int merge_only;
|
||||
int try_all_secrets;
|
||||
int no_expensive_trust_checks;
|
||||
int no_sig_cache;
|
||||
int no_sig_create_check;
|
||||
int no_auto_check_trustdb;
|
||||
int preserve_permissions;
|
||||
int no_homedir_creation;
|
||||
int show_keyring;
|
||||
struct groupitem *grouplist;
|
||||
} opt;
|
||||
|
||||
|
||||
#define EMUBUG_GPGCHKSUM 1
|
||||
#define EMUBUG_3DESS2K 2
|
||||
#define EMUBUG_MDENCODE 4
|
||||
|
||||
@ -112,14 +186,15 @@ struct {
|
||||
#define DBG_MEMSTAT_VALUE 128 /* show memory statistics */
|
||||
#define DBG_TRUST_VALUE 256 /* debug the trustdb */
|
||||
#define DBG_HASHING_VALUE 512 /* debug hashing operations */
|
||||
#define DBG_EXTPROG_VALUE 1024 /* debug external program calls */
|
||||
|
||||
|
||||
#define DBG_PACKET (opt.debug & DBG_PACKET_VALUE)
|
||||
#define DBG_FILTER (opt.debug & DBG_FILTER_VALUE)
|
||||
#define DBG_MEMORY (opt.debug & DBG_MEMORY_VALUE)
|
||||
#define DBG_CACHE (opt.debug & DBG_CACHE_VALUE)
|
||||
#define DBG_TRUST (opt.debug & DBG_TRUST_VALUE)
|
||||
#define DBG_CIPHER (opt.debug & DBG_CIPHER_VALUE)
|
||||
#define DBG_HASHING (opt.debug & DBG_HASHING_VALUE)
|
||||
#define DBG_EXTPROG (opt.debug & DBG_EXTPROG_VALUE)
|
||||
|
||||
#endif /*GPG_OPTIONS_H*/
|
||||
|
||||
#endif /*G10_OPTIONS_H*/
|
||||
|
176
g10/options.skel
176
g10/options.skel
@ -2,6 +2,15 @@ These first three lines are not copied to the options file in
|
||||
the users home directory.
|
||||
$Id$
|
||||
# Options for GnuPG
|
||||
# Copyright 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; as a special exception the author gives
|
||||
# unlimited permission to copy and/or distribute it, with or without
|
||||
# modifications, as long as this notice is preserved.
|
||||
#
|
||||
# This file is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
|
||||
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
#
|
||||
# Unless you you specify which option file to use (with the
|
||||
# commandline option "--options filename"), GnuPG uses the
|
||||
@ -22,6 +31,7 @@ $Id$
|
||||
|
||||
#default-key 621CC013
|
||||
|
||||
|
||||
# If you do not pass a recipient to gpg, it will ask for one.
|
||||
# Using this option you can encrypt to a default key. key validation
|
||||
# will not be done in this case.
|
||||
@ -30,31 +40,32 @@ $Id$
|
||||
#default-recipient some-user-id
|
||||
#default-recipient-self
|
||||
|
||||
|
||||
# The next option is enabled because this one is needed for interoperation
|
||||
# with PGP 5 users. To enable full OpenPGP compliance you have to remove
|
||||
# this option.
|
||||
|
||||
force-v3-sigs
|
||||
# By default GnuPG creates version 3 signatures for data files. This
|
||||
# is not OpenPGP compliant but PGP 6 requires them. To disable it,
|
||||
# you may use this option or --openpgp.
|
||||
#no-force-v3-sigs
|
||||
|
||||
# Because some mailers change lines starting with "From " to ">From "
|
||||
# it is good to handle such lines in a special way when creating
|
||||
# cleartext signatures; all other PGP versions it this way too.
|
||||
# To enable full OpenPGP compliance you have to remove this option.
|
||||
# cleartext signatures; all other PGP versions do it this way too.
|
||||
# To enable full OpenPGP compliance you may want to use this option.
|
||||
#no-escape-from-lines
|
||||
|
||||
escape-from-lines
|
||||
# If you do not use the Latin-1 (ISO-8859-1) charset, you should tell
|
||||
# GnuPG which is the native character set. Please check the man page
|
||||
# for supported character sets. This character set is only used for
|
||||
# Meta data and not for the actual message which does not undergo any
|
||||
# translation. Note that future version of GnuPG will change to UTF-8
|
||||
# as default character set.
|
||||
#charset utf-8
|
||||
|
||||
# If you do not use the Latin-1 (ISO-8859-1) charset, you should
|
||||
# tell GnuPG which is the native character set. Please check
|
||||
# the man page for supported character sets.
|
||||
#charset koi8-r
|
||||
|
||||
|
||||
# You may define aliases like this:
|
||||
# alias mynames -u 0x12345678 -u 0x456789ab -z 9
|
||||
# everytime you use --mynames, it will be expanded to the options
|
||||
# in the above defintion. The name of the alias may not be abbreviated.
|
||||
# NOTE: This is not yet implemented
|
||||
# Group names may be defined like this:
|
||||
# group mynames paige 0x12345678 joe patti
|
||||
#
|
||||
# Any time "mynames" is a receipient (-r or --recipient), it will be
|
||||
# expanded to the names "paige", "joe", and "patti", and the key ID
|
||||
# "0x12345678". Note there is only one level of expansion - you
|
||||
# cannot make an group that points to another group.
|
||||
|
||||
# lock the file only once for the lifetime of a process.
|
||||
# if you do not define this, the lock will be obtained and released
|
||||
@ -70,17 +81,122 @@ lock-once
|
||||
#load-extension rndunix
|
||||
#load-extension rndegd
|
||||
|
||||
# GnuPG can send and receive keys to and from a keyserver. These
|
||||
# servers can be HKP, email, or LDAP (if GnuPG is built with LDAP
|
||||
# support).
|
||||
#
|
||||
# Example HKP keyserver:
|
||||
# x-hkp://keyserver.cryptnet.net
|
||||
#
|
||||
# Example email keyserver:
|
||||
# mailto:pgp-public-keys@keys.nl.pgp.net
|
||||
#
|
||||
# Example LDAP keyserver:
|
||||
# ldap://pgp.surfnet.nl:11370
|
||||
#
|
||||
# Regular URL syntax applies, and you can set an alternate port
|
||||
# through the usual method:
|
||||
# x-hkp://keyserver.example.net:22742
|
||||
#
|
||||
# If you have problems connecting to a HKP server through a buggy http
|
||||
# proxy, you can use keyserver option broken-http-proxy (see below),
|
||||
# but first you should make sure that you have read the man page
|
||||
# regarding proxies (keyserver option honor-http-proxy)
|
||||
#
|
||||
# Most users just set the name and type of their preferred keyserver.
|
||||
# Most servers do synchronize with each other and DNS round-robin may
|
||||
# give you a quasi-random server each time.
|
||||
|
||||
# GnuPG can import a key from a HKP keyerver if one is missing
|
||||
# for sercain operations. Is you set this option to a keyserver
|
||||
# you will be asked in such a case whether GnuPG should try to
|
||||
# import the key from that server (server do syncronize with each
|
||||
# others and DNS Round-Robin may give you a random server each time).
|
||||
# Use "host -l pgp.net | grep www" to figure out a keyserver.
|
||||
#keyserver wwwkeys.eu.pgp.net
|
||||
#keyserver x-hkp://keyserver.cryptnet.net
|
||||
#keyserver mailto:pgp-public-keys@keys.nl.pgp.net
|
||||
#keyserver ldap://pgp.surfnet.nl:11370
|
||||
|
||||
# The environment variable http_proxy is only used when the
|
||||
# this option is set.
|
||||
# Options for keyserver functions
|
||||
#
|
||||
# include-disabled = when searching, include keys marked as "disabled"
|
||||
# on the keyserver (not all keyservers support this).
|
||||
#
|
||||
# include-revoked = when searching, include keys marked as "revoked"
|
||||
# on the keyserver.
|
||||
#
|
||||
# verbose = show more information as the keys are fetched.
|
||||
# Can be used more than once to increase the amount
|
||||
# of information shown.
|
||||
#
|
||||
# use-temp-files = use temporary files instead of a pipe to talk to the
|
||||
# keyserver. Some platforms (Win32 for one) always
|
||||
# have this on.
|
||||
#
|
||||
# keep-temp-files = do not delete temporary files after using them
|
||||
# (really only useful for debugging)
|
||||
#
|
||||
# honor-http-proxy = if the keyserver uses HTTP, honor the http_proxy
|
||||
# environment variable
|
||||
#
|
||||
# broken-http-proxy = try to work around a buggy HTTP proxy
|
||||
#
|
||||
# auto-key-retrieve = automatically fetch keys as needed from the
|
||||
# keyserver when verifying signatures or when importing
|
||||
# keys that have been revoked by a revocation key that
|
||||
# is not present on the keyring.
|
||||
|
||||
honor-http-proxy
|
||||
#keyserver-options auto-key-retrieve include-disabled include-revoked
|
||||
|
||||
# Uncomment this line to display photo user IDs in key listings
|
||||
#show-photos
|
||||
|
||||
# Use this program to display photo user IDs
|
||||
#
|
||||
# %i is expanded to a temporary file that contains the photo.
|
||||
# %I is the same as %i, but the file isn't deleted afterwards by GnuPG.
|
||||
# %k is expanded to the key ID of the key.
|
||||
# %K is expanded to the long OpenPGP key ID of the key.
|
||||
# %t is expanded to the extension of the image (e.g. "jpg").
|
||||
# %T is expanded to the MIME type of the image (e.g. "image/jpeg").
|
||||
# %f is expanded to the fingerprint of the key.
|
||||
# %% is %, of course.
|
||||
#
|
||||
# If %i or %I are not present, then the photo is supplied to the
|
||||
# viewer on standard input. If your platform supports it, standard
|
||||
# input is the best way to do this as it avoids the time and effort in
|
||||
# generating and then cleaning up a secure temp file.
|
||||
#
|
||||
# The default program is "xloadimage -fork -quiet -title 'KeyID 0x%k' stdin"
|
||||
#
|
||||
# Some other viewers:
|
||||
# photo-viewer "qiv %i"
|
||||
# photo-viewer "ee %i"
|
||||
# photo-viewer "display -title 'KeyID 0x%k'"
|
||||
#
|
||||
# This one saves a copy of the photo ID in your home directory:
|
||||
# photo-viewer "cat > ~/photoid-for-key-%k.%t"
|
||||
#
|
||||
# Use your MIME handler to view photos:
|
||||
# photo-viewer "metamail -q -d -b -c %T -s 'KeyID 0x%k' -f GnuPG"
|
||||
#
|
||||
# Use the Win32 registry to pick a viewer for you:
|
||||
# On Win95/98/Me (also the default on Win32):
|
||||
# photo-viewer "start /w"
|
||||
# On NT/2k/XP:
|
||||
# photo-viewer "cmd /c start /w"
|
||||
|
||||
|
||||
# Passphrase agent
|
||||
#
|
||||
# We support the old experimental passphrase agent protocol as well
|
||||
# as the new Assuan based one (currently available in the "newpg" package
|
||||
# at ftp.gnupg.org/gcrypt/alpha/aegypten/). To make use of the agent, you have
|
||||
# to run an agent as daemon and use the option
|
||||
#
|
||||
# use-agent
|
||||
#
|
||||
# which tries to use the agent but will fallback to the regular mode
|
||||
# if there is a problem connecting to the agent. The normal way to
|
||||
# locate the agent is by looking at the environment variable
|
||||
# GPG_AGENT_INFO which should have been set during gpg-agent startup.
|
||||
# In certain situations the use of this variable is not possible, thus
|
||||
# the option
|
||||
#
|
||||
# --gpg-agent-info=<path>:<pid>:1
|
||||
#
|
||||
# may be used to override it.
|
||||
|
239
g10/packet.h
239
g10/packet.h
@ -1,5 +1,5 @@
|
||||
/* packet.h - packet read/write stuff
|
||||
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
|
||||
/* packet.h - packet definitions
|
||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
@ -18,22 +18,15 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
#ifndef GPG_PACKET_H
|
||||
#define GPG_PACKET_H
|
||||
#ifndef G10_PACKET_H
|
||||
#define G10_PACKET_H
|
||||
|
||||
#include "types.h"
|
||||
#include "iobuf.h"
|
||||
#include "mpi.h"
|
||||
#include "cipher.h"
|
||||
#include "filter.h"
|
||||
|
||||
#ifndef DID_MPI_TYPEDEF
|
||||
typedef struct gcry_mpi *MPI;
|
||||
#define DID_MPI_TYPEDEF
|
||||
#endif
|
||||
|
||||
#define GNUPG_MAX_NPKEY 4
|
||||
#define GNUPG_MAX_NSKEY 6
|
||||
#define GNUPG_MAX_NSIG 2
|
||||
#define GNUPG_MAX_NENC 2
|
||||
#include "global.h"
|
||||
|
||||
#define DEBUG_PARSE_PACKET 1
|
||||
|
||||
@ -54,14 +47,34 @@ typedef enum {
|
||||
PKT_USER_ID =13, /* user id packet */
|
||||
PKT_PUBLIC_SUBKEY =14, /* public subkey (OpenPGP) */
|
||||
PKT_OLD_COMMENT =16, /* comment packet from an OpenPGP draft */
|
||||
PKT_PHOTO_ID =17, /* PGP's photo ID */
|
||||
PKT_ATTRIBUTE =17, /* PGP's attribute packet */
|
||||
PKT_ENCRYPTED_MDC =18, /* integrity protected encrypted data */
|
||||
PKT_MDC =19, /* manipulaion detection code packet */
|
||||
PKT_COMMENT =61, /* new comment packet (private) */
|
||||
PKT_GPG_CONTROL =63 /* internal control packet */
|
||||
} pkttype_t;
|
||||
|
||||
typedef struct packet_struct PACKET;
|
||||
|
||||
/* PKT_GPG_CONTROL types */
|
||||
typedef enum {
|
||||
CTRLPKT_CLEARSIGN_START = 1,
|
||||
CTRLPKT_PIPEMODE = 2,
|
||||
CTRLPKT_PLAINTEXT_MARK =3
|
||||
} ctrlpkttype_t;
|
||||
|
||||
typedef enum {
|
||||
PREFTYPE_NONE = 0,
|
||||
PREFTYPE_SYM = 1,
|
||||
PREFTYPE_HASH = 2,
|
||||
PREFTYPE_ZIP = 3
|
||||
} preftype_t;
|
||||
|
||||
typedef struct {
|
||||
byte type;
|
||||
byte value;
|
||||
} prefitem_t;
|
||||
|
||||
typedef struct {
|
||||
int mode;
|
||||
byte hash_algo;
|
||||
@ -82,7 +95,7 @@ typedef struct {
|
||||
byte version;
|
||||
byte pubkey_algo; /* algorithm used for public key scheme */
|
||||
byte throw_keyid;
|
||||
MPI data[GNUPG_MAX_NENC];
|
||||
MPI data[PUBKEY_MAX_NENC];
|
||||
} PKT_pubkey_enc;
|
||||
|
||||
|
||||
@ -95,26 +108,75 @@ typedef struct {
|
||||
} PKT_onepass_sig;
|
||||
|
||||
|
||||
typedef struct {
|
||||
size_t size; /* allocated */
|
||||
size_t len; /* used */
|
||||
byte data[1];
|
||||
} subpktarea_t;
|
||||
|
||||
struct revocation_key {
|
||||
byte class;
|
||||
byte algid;
|
||||
byte fpr[MAX_FINGERPRINT_LEN];
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
ulong local_id; /* internal use, valid if > 0 */
|
||||
struct {
|
||||
unsigned checked:1; /* signature has been checked */
|
||||
unsigned valid:1; /* signature is good (if checked is set) */
|
||||
unsigned unknown_critical:1;
|
||||
unsigned exportable:1;
|
||||
unsigned revocable:1;
|
||||
unsigned policy_url:1; /* Policy URL is present */
|
||||
unsigned notation:1; /* At least one notation is present */
|
||||
unsigned expired:1;
|
||||
} flags;
|
||||
u32 keyid[2]; /* 64 bit keyid */
|
||||
u32 timestamp; /* signature made */
|
||||
u32 expiredate; /* expires at this date or 0 if not at all */
|
||||
byte version;
|
||||
byte sig_class; /* sig classification, append for MD calculation*/
|
||||
byte pubkey_algo; /* algorithm used for public key scheme */
|
||||
/* (GCRY_PK_xxx) */
|
||||
byte digest_algo; /* algorithm used for digest (DIGEST_ALGO_xxxx) */
|
||||
byte *hashed_data; /* all subpackets with hashed data (v4 only) */
|
||||
byte *unhashed_data; /* ditto for unhashed data */
|
||||
/* (PUBKEY_ALGO_xxx) */
|
||||
byte digest_algo; /* algorithm used for digest (DIGEST_ALGO_xxxx) */
|
||||
struct revocation_key **revkey;
|
||||
int numrevkeys;
|
||||
subpktarea_t *hashed; /* all subpackets with hashed data (v4 only) */
|
||||
subpktarea_t *unhashed; /* ditto for unhashed data */
|
||||
byte digest_start[2]; /* first 2 bytes of the digest */
|
||||
MPI data[GNUPG_MAX_NSIG];
|
||||
MPI data[PUBKEY_MAX_NSIG];
|
||||
} PKT_signature;
|
||||
|
||||
#define ATTRIB_IMAGE 1
|
||||
|
||||
/* This is the cooked form of attributes */
|
||||
struct user_attribute {
|
||||
byte type;
|
||||
const byte *data;
|
||||
unsigned long len;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
int ref; /* reference counter */
|
||||
int len; /* length of the name */
|
||||
struct user_attribute *attribs;
|
||||
int numattribs;
|
||||
byte *attrib_data; /* if this is not NULL, the packet is an attribute */
|
||||
unsigned long attrib_len;
|
||||
int help_key_usage;
|
||||
u32 help_key_expire;
|
||||
int is_primary;
|
||||
int is_revoked;
|
||||
int is_expired;
|
||||
u32 expiredate; /* expires at this date or 0 if not at all */
|
||||
prefitem_t *prefs; /* list of preferences (may be NULL)*/
|
||||
int mdc_feature;
|
||||
u32 created; /* according to the self-signature */
|
||||
byte selfsigversion;
|
||||
char name[1];
|
||||
} PKT_user_id;
|
||||
|
||||
|
||||
/****************
|
||||
* Note about the pkey/skey elements: We assume that the secret keys
|
||||
@ -125,31 +187,38 @@ typedef struct {
|
||||
typedef struct {
|
||||
u32 timestamp; /* key made */
|
||||
u32 expiredate; /* expires at this date or 0 if not at all */
|
||||
u32 max_expiredate; /* must not expire past this date */
|
||||
byte hdrbytes; /* number of header bytes */
|
||||
byte version;
|
||||
byte selfsigversion; /* highest version of all of the self-sigs */
|
||||
byte pubkey_algo; /* algorithm used for public key scheme */
|
||||
byte pubkey_usage; /* the actual allowed usage as set by getkey() */
|
||||
u32 created; /* according to the self-signature */
|
||||
byte pubkey_usage; /* for now only used to pass it to getkey() */
|
||||
byte req_usage; /* hack to pass a request to getkey() */
|
||||
byte req_algo; /* Ditto */
|
||||
u32 has_expired; /* set to the expiration date if expired */
|
||||
int is_revoked; /* key has been revoked */
|
||||
int is_valid; /* key (especially subkey) is valid */
|
||||
int dont_cache; /* do not cache this */
|
||||
ulong local_id; /* internal use, valid if > 0 */
|
||||
u32 main_keyid[2]; /* keyid of the primary key */
|
||||
u32 keyid[2]; /* calculated by keyid_from_pk() */
|
||||
prefitem_t *prefs; /* list of preferences (may be NULL) */
|
||||
int mdc_feature; /* mdc feature set */
|
||||
byte *namehash; /* if != NULL: found by this name */
|
||||
MPI pkey[GNUPG_MAX_NPKEY];
|
||||
PKT_user_id *user_id; /* if != NULL: found by that uid */
|
||||
struct revocation_key *revkey;
|
||||
int numrevkeys;
|
||||
MPI pkey[PUBKEY_MAX_NPKEY];
|
||||
} PKT_public_key;
|
||||
|
||||
typedef struct {
|
||||
u32 timestamp; /* key made */
|
||||
u32 expiredate; /* expires at this date or 0 if not at all */
|
||||
u32 max_expiredate; /* must not expire past this date */
|
||||
byte hdrbytes; /* number of header bytes */
|
||||
byte version;
|
||||
byte pubkey_algo; /* algorithm used for public key scheme */
|
||||
byte pubkey_usage;
|
||||
u32 created; /* according to the self-signature */
|
||||
byte req_usage;
|
||||
byte req_algo;
|
||||
u32 has_expired; /* set to the expiration date if expired */
|
||||
@ -164,11 +233,12 @@ typedef struct {
|
||||
/* and should never be passed to a mpi_xxx() */
|
||||
struct {
|
||||
byte algo; /* cipher used to protect the secret information*/
|
||||
byte sha1chk; /* SHA1 is used instead of a 16 bit checksum */
|
||||
STRING2KEY s2k;
|
||||
byte ivlen; /* used length of the iv */
|
||||
byte iv[16]; /* initialization vector for CFB mode */
|
||||
} protect;
|
||||
MPI skey[GNUPG_MAX_NSKEY];
|
||||
MPI skey[PUBKEY_MAX_NSKEY];
|
||||
u16 csum; /* checksum */
|
||||
} PKT_secret_key;
|
||||
|
||||
@ -178,19 +248,6 @@ typedef struct {
|
||||
char data[1];
|
||||
} PKT_comment;
|
||||
|
||||
typedef struct {
|
||||
ulong stored_at; /* the stream offset where it was stored
|
||||
* by build-packet */
|
||||
int len; /* length of the name */
|
||||
char *photo; /* if this is not NULL, the packet is a photo ID */
|
||||
int photolen; /* and the length of the photo */
|
||||
int help_key_usage;
|
||||
u32 help_key_expire;
|
||||
int is_primary;
|
||||
u32 created; /* according to the self-signature */
|
||||
char name[1];
|
||||
} PKT_user_id;
|
||||
|
||||
typedef struct {
|
||||
u32 len; /* reserved */
|
||||
byte new_ctb;
|
||||
@ -200,6 +257,7 @@ typedef struct {
|
||||
|
||||
typedef struct {
|
||||
u32 len; /* length of encrypted data */
|
||||
int extralen; /* this is (blocksize+2) */
|
||||
byte new_ctb; /* uses a new CTB */
|
||||
byte mdc_method; /* > 0: integrity protected encrypted data packet */
|
||||
IOBUF buf; /* IOBUF reference */
|
||||
@ -211,18 +269,25 @@ typedef struct {
|
||||
|
||||
typedef struct {
|
||||
unsigned int trustval;
|
||||
unsigned int sigcache;
|
||||
} PKT_ring_trust;
|
||||
|
||||
typedef struct {
|
||||
u32 len; /* length of encrypted data */
|
||||
IOBUF buf; /* IOBUF reference */
|
||||
byte new_ctb;
|
||||
byte is_partial; /* partial length encoded */
|
||||
int mode;
|
||||
u32 timestamp;
|
||||
int namelen;
|
||||
char name[1];
|
||||
} PKT_plaintext;
|
||||
|
||||
typedef struct {
|
||||
int control;
|
||||
size_t datalen;
|
||||
char data[1];
|
||||
} PKT_gpg_control;
|
||||
|
||||
/* combine all packets into a union */
|
||||
struct packet_struct {
|
||||
@ -242,6 +307,7 @@ struct packet_struct {
|
||||
PKT_mdc *mdc; /* PKT_MDC */
|
||||
PKT_ring_trust *ring_trust; /* PKT_RING_TRUST */
|
||||
PKT_plaintext *plaintext; /* PKT_PLAINTEXT */
|
||||
PKT_gpg_control *gpg_control; /* PKT_GPG_CONTROL */
|
||||
} pkt;
|
||||
};
|
||||
|
||||
@ -276,7 +342,7 @@ typedef enum {
|
||||
SIGSUBPKT_SIGNERS_UID =28, /* signer's user id */
|
||||
SIGSUBPKT_REVOC_REASON =29, /* reason for revocation */
|
||||
SIGSUBPKT_FEATURES =30, /* feature flags */
|
||||
SIGSUBPKT_PRIV_ADD_SIG =101,/* signatur is also valid for this uid */
|
||||
SIGSUBPKT_PRIV_VERIFY_CACHE =101, /* cache verification result (obsolete)*/
|
||||
|
||||
SIGSUBPKT_FLAG_CRITICAL=128
|
||||
} sigsubpkttype_t;
|
||||
@ -293,39 +359,62 @@ int list_packets( IOBUF a );
|
||||
int set_packet_list_mode( int mode );
|
||||
|
||||
#if DEBUG_PARSE_PACKET
|
||||
int dbg_search_packet( IOBUF inp, PACKET *pkt, int pkttype, ulong *retpos, const char* file, int lineno );
|
||||
int dbg_parse_packet( IOBUF inp, PACKET *ret_pkt, ulong *pos,
|
||||
int dbg_search_packet( IOBUF inp, PACKET *pkt, off_t *retpos, int with_uid,
|
||||
const char* file, int lineno );
|
||||
int dbg_parse_packet( IOBUF inp, PACKET *ret_pkt,
|
||||
const char* file, int lineno );
|
||||
int dbg_copy_all_packets( IOBUF inp, IOBUF out, const char* file, int lineno );
|
||||
int dbg_copy_some_packets( IOBUF inp, IOBUF out, ulong stopoff, const char* file, int lineno );
|
||||
int dbg_skip_some_packets( IOBUF inp, unsigned n, const char* file, int lineno );
|
||||
#define search_packet( a,b,c,d ) dbg_search_packet( (a), (b), (c), (d), __FILE__, __LINE__ )
|
||||
#define parse_packet( a, b, c ) dbg_parse_packet( (a), (b), (c), __FILE__, __LINE__ )
|
||||
#define copy_all_packets( a,b ) dbg_copy_all_packets((a),(b), __FILE__, __LINE__ )
|
||||
#define copy_some_packets( a,b,c ) dbg_copy_some_packets((a),(b),(c), __FILE__, __LINE__ )
|
||||
#define skip_some_packets( a,b ) dbg_skip_some_packets((a),(b), __FILE__, __LINE__ )
|
||||
int dbg_copy_all_packets( IOBUF inp, IOBUF out,
|
||||
const char* file, int lineno );
|
||||
int dbg_copy_some_packets( IOBUF inp, IOBUF out, off_t stopoff,
|
||||
const char* file, int lineno );
|
||||
int dbg_skip_some_packets( IOBUF inp, unsigned n,
|
||||
const char* file, int lineno );
|
||||
#define search_packet( a,b,c,d ) \
|
||||
dbg_search_packet( (a), (b), (c), (d), __FILE__, __LINE__ )
|
||||
#define parse_packet( a, b ) \
|
||||
dbg_parse_packet( (a), (b), __FILE__, __LINE__ )
|
||||
#define copy_all_packets( a,b ) \
|
||||
dbg_copy_all_packets((a),(b), __FILE__, __LINE__ )
|
||||
#define copy_some_packets( a,b,c ) \
|
||||
dbg_copy_some_packets((a),(b),(c), __FILE__, __LINE__ )
|
||||
#define skip_some_packets( a,b ) \
|
||||
dbg_skip_some_packets((a),(b), __FILE__, __LINE__ )
|
||||
#else
|
||||
int search_packet( IOBUF inp, PACKET *pkt, int pkttype, ulong *retpos );
|
||||
int parse_packet( IOBUF inp, PACKET *ret_pkt, ulong *retpos);
|
||||
int search_packet( IOBUF inp, PACKET *pkt, off_t *retpos, int with_uid );
|
||||
int parse_packet( IOBUF inp, PACKET *ret_pkt);
|
||||
int copy_all_packets( IOBUF inp, IOBUF out );
|
||||
int copy_some_packets( IOBUF inp, IOBUF out, ulong stopoff );
|
||||
int copy_some_packets( IOBUF inp, IOBUF out, off_t stopoff );
|
||||
int skip_some_packets( IOBUF inp, unsigned n );
|
||||
#endif
|
||||
|
||||
const byte *enum_sig_subpkt( const byte *buffer, sigsubpkttype_t reqtype,
|
||||
size_t *ret_n, int *start );
|
||||
const byte *parse_sig_subpkt( const byte *buffer, sigsubpkttype_t reqtype,
|
||||
size_t *ret_n );
|
||||
const byte *parse_sig_subpkt2( PKT_signature *sig,
|
||||
sigsubpkttype_t reqtype, size_t *ret_n );
|
||||
const byte *enum_sig_subpkt ( const subpktarea_t *subpkts,
|
||||
sigsubpkttype_t reqtype,
|
||||
size_t *ret_n, int *start, int *critical );
|
||||
const byte *parse_sig_subpkt ( const subpktarea_t *buffer,
|
||||
sigsubpkttype_t reqtype,
|
||||
size_t *ret_n );
|
||||
const byte *parse_sig_subpkt2 ( PKT_signature *sig,
|
||||
sigsubpkttype_t reqtype,
|
||||
size_t *ret_n );
|
||||
int parse_one_sig_subpkt( const byte *buffer, size_t n, int type );
|
||||
void parse_revkeys(PKT_signature *sig);
|
||||
int parse_attribute_subpkts(PKT_user_id *uid);
|
||||
void make_attribute_uidname(PKT_user_id *uid);
|
||||
PACKET *create_gpg_control ( ctrlpkttype_t type,
|
||||
const byte *data,
|
||||
size_t datalen );
|
||||
|
||||
/*-- build-packet.c --*/
|
||||
int build_packet( IOBUF inp, PACKET *pkt );
|
||||
u32 calc_packet_length( PACKET *pkt );
|
||||
void hash_public_key( GCRY_MD_HD md, PKT_public_key *pk );
|
||||
void hash_public_key( MD_HANDLE md, PKT_public_key *pk );
|
||||
void build_sig_subpkt( PKT_signature *sig, sigsubpkttype_t type,
|
||||
const byte *buffer, size_t buflen );
|
||||
void build_sig_subpkt_from_sig( PKT_signature *sig );
|
||||
int delete_sig_subpkt(subpktarea_t *buffer, sigsubpkttype_t type );
|
||||
void build_attribute_subpkt(PKT_user_id *uid,byte type,
|
||||
const void *buf,int buflen,
|
||||
const void *header,int headerlen);
|
||||
|
||||
/*-- free-packet.c --*/
|
||||
void free_symkey_enc( PKT_symkey_enc *enc );
|
||||
@ -336,18 +425,16 @@ void release_public_key_parts( PKT_public_key *pk );
|
||||
void free_public_key( PKT_public_key *key );
|
||||
void release_secret_key_parts( PKT_secret_key *sk );
|
||||
void free_secret_key( PKT_secret_key *sk );
|
||||
void free_attributes(PKT_user_id *uid);
|
||||
void free_user_id( PKT_user_id *uid );
|
||||
void free_comment( PKT_comment *rem );
|
||||
void free_packet( PACKET *pkt );
|
||||
prefitem_t *copy_prefs (const prefitem_t *prefs);
|
||||
PKT_public_key *copy_public_key( PKT_public_key *d, PKT_public_key *s );
|
||||
PKT_public_key *copy_public_key_new_namehash( PKT_public_key *d,
|
||||
PKT_public_key *s,
|
||||
const byte *namehash );
|
||||
void copy_public_parts_to_secret_key( PKT_public_key *pk,
|
||||
PKT_secret_key *sk );
|
||||
void copy_public_parts_to_secret_key( PKT_public_key *pk, PKT_secret_key *sk );
|
||||
PKT_secret_key *copy_secret_key( PKT_secret_key *d, PKT_secret_key *s );
|
||||
PKT_signature *copy_signature( PKT_signature *d, PKT_signature *s );
|
||||
PKT_user_id *copy_user_id( PKT_user_id *d, PKT_user_id *s );
|
||||
PKT_user_id *scopy_user_id (PKT_user_id *sd );
|
||||
int cmp_public_keys( PKT_public_key *a, PKT_public_key *b );
|
||||
int cmp_secret_keys( PKT_secret_key *a, PKT_secret_key *b );
|
||||
int cmp_signatures( PKT_signature *a, PKT_signature *b );
|
||||
@ -356,7 +443,9 @@ int cmp_user_ids( PKT_user_id *a, PKT_user_id *b );
|
||||
|
||||
|
||||
/*-- sig-check.c --*/
|
||||
int signature_check( PKT_signature *sig, GCRY_MD_HD digest );
|
||||
int signature_check( PKT_signature *sig, MD_HANDLE digest );
|
||||
int signature_check2( PKT_signature *sig, MD_HANDLE digest,
|
||||
u32 *r_expiredate, int *r_expired );
|
||||
|
||||
/*-- seckey-cert.c --*/
|
||||
int is_secret_key_protected( PKT_secret_key *sk );
|
||||
@ -365,6 +454,7 @@ int protect_secret_key( PKT_secret_key *sk, DEK *dek );
|
||||
|
||||
/*-- pubkey-enc.c --*/
|
||||
int get_session_key( PKT_pubkey_enc *k, DEK *dek );
|
||||
int get_override_session_key( DEK *dek, const char *string );
|
||||
|
||||
/*-- compress.c --*/
|
||||
int handle_compressed( void *ctx, PKT_compressed *cd,
|
||||
@ -376,7 +466,7 @@ int decrypt_data( void *ctx, PKT_encrypted *ed, DEK *dek );
|
||||
/*-- plaintext.c --*/
|
||||
int handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx,
|
||||
int nooutput, int clearsig );
|
||||
int ask_for_detached_datafile( GCRY_MD_HD md, GCRY_MD_HD md2,
|
||||
int ask_for_detached_datafile( MD_HANDLE md, MD_HANDLE md2,
|
||||
const char *inname, int textmode );
|
||||
|
||||
/*-- comment.c --*/
|
||||
@ -385,12 +475,19 @@ int write_comment( IOBUF out, const char *s );
|
||||
/*-- sign.c --*/
|
||||
int make_keysig_packet( PKT_signature **ret_sig, PKT_public_key *pk,
|
||||
PKT_user_id *uid, PKT_public_key *subpk,
|
||||
PKT_secret_key *sk,
|
||||
int sigclass, int digest_algo,
|
||||
PKT_secret_key *sk, int sigclass, int digest_algo,
|
||||
int sigversion, u32 timestamp, u32 duration,
|
||||
int (*mksubpkt)(PKT_signature *, void *),
|
||||
void *opaque );
|
||||
int update_keysig_packet( PKT_signature **ret_sig,
|
||||
PKT_signature *orig_sig,
|
||||
PKT_public_key *pk,
|
||||
PKT_user_id *uid,
|
||||
PKT_secret_key *sk,
|
||||
int (*mksubpkt)(PKT_signature *, void *),
|
||||
void *opaque );
|
||||
|
||||
/*-- keygen.c --*/
|
||||
PKT_user_id *generate_user_id(void);
|
||||
|
||||
#endif /*GPG_PACKET_H*/
|
||||
#endif /*G10_PACKET_H*/
|
||||
|
File diff suppressed because it is too large
Load Diff
1002
g10/passphrase.c
1002
g10/passphrase.c
File diff suppressed because it is too large
Load Diff
320
g10/photoid.c
Normal file
320
g10/photoid.c
Normal file
@ -0,0 +1,320 @@
|
||||
/* photoid.c - photo ID handling code
|
||||
* Copyright (C) 2001, 2002 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
* GnuPG is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GnuPG is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#ifdef HAVE_DOSISH_SYSTEM
|
||||
#include <windows.h>
|
||||
#endif
|
||||
#include "packet.h"
|
||||
#include "status.h"
|
||||
#include "exec.h"
|
||||
#include "keydb.h"
|
||||
#include "util.h"
|
||||
#include "i18n.h"
|
||||
#include "iobuf.h"
|
||||
#include "memory.h"
|
||||
#include "options.h"
|
||||
#include "main.h"
|
||||
#include "photoid.h"
|
||||
|
||||
/* Generate a new photo id packet, or return NULL if canceled */
|
||||
PKT_user_id *generate_photo_id(PKT_public_key *pk)
|
||||
{
|
||||
PKT_user_id *uid;
|
||||
int error=1,i;
|
||||
unsigned int len;
|
||||
char *filename=NULL;
|
||||
byte *photo=NULL;
|
||||
byte header[16];
|
||||
IOBUF file;
|
||||
|
||||
header[0]=0x10; /* little side of photo header length */
|
||||
header[1]=0; /* big side of photo header length */
|
||||
header[2]=1; /* 1 == version of photo header */
|
||||
header[3]=1; /* 1 == JPEG */
|
||||
|
||||
for(i=4;i<16;i++) /* The reserved bytes */
|
||||
header[i]=0;
|
||||
|
||||
uid=m_alloc_clear(sizeof(*uid)+50);
|
||||
|
||||
printf(_("\nPick an image to use for your photo ID. "
|
||||
"The image must be a JPEG file.\n"
|
||||
"Remember that the image is stored within your public key. "
|
||||
"If you use a\n"
|
||||
"very large picture, your key will become very large as well!\n"
|
||||
"Keeping the image close to 240x288 is a good size to use.\n"));
|
||||
|
||||
while(photo==NULL)
|
||||
{
|
||||
printf("\n");
|
||||
|
||||
m_free(filename);
|
||||
|
||||
filename=cpr_get("photoid.jpeg.add",
|
||||
_("Enter JPEG filename for photo ID: "));
|
||||
|
||||
if(strlen(filename)==0)
|
||||
goto scram;
|
||||
|
||||
file=iobuf_open(filename);
|
||||
if(!file)
|
||||
{
|
||||
log_error(_("Unable to open photo \"%s\": %s\n"),
|
||||
filename,strerror(errno));
|
||||
continue;
|
||||
}
|
||||
|
||||
len=iobuf_get_filelength(file);
|
||||
if(len>6144)
|
||||
{
|
||||
printf("This JPEG is really large (%d bytes) !\n",len);
|
||||
if(!cpr_get_answer_is_yes("photoid.jpeg.size",
|
||||
_("Are you sure you want to use it (y/N)? ")))
|
||||
{
|
||||
iobuf_close(file);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
photo=m_alloc(len);
|
||||
iobuf_read(file,photo,len);
|
||||
iobuf_close(file);
|
||||
|
||||
/* Is it a JPEG? */
|
||||
if(photo[0]!=0xFF || photo[1]!=0xD8 ||
|
||||
photo[6]!='J' || photo[7]!='F' || photo[8]!='I' || photo[9]!='F')
|
||||
{
|
||||
log_error(_("\"%s\" is not a JPEG file\n"),filename);
|
||||
m_free(photo);
|
||||
photo=NULL;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Build the packet */
|
||||
build_attribute_subpkt(uid,1,photo,len,header,16);
|
||||
parse_attribute_subpkts(uid);
|
||||
make_attribute_uidname(uid);
|
||||
|
||||
/* Showing the photo is not safe when noninteractive since the
|
||||
"user" may not be able to dismiss a viewer window! */
|
||||
if(opt.command_fd==-1)
|
||||
{
|
||||
show_photos(uid->attribs,uid->numattribs,pk,NULL);
|
||||
switch(cpr_get_answer_yes_no_quit("photoid.jpeg.okay",
|
||||
_("Is this photo correct (y/N/q)? ")))
|
||||
{
|
||||
case -1:
|
||||
goto scram;
|
||||
case 0:
|
||||
free_attributes(uid);
|
||||
m_free(photo);
|
||||
photo=NULL;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
error=0;
|
||||
uid->ref=1;
|
||||
|
||||
scram:
|
||||
m_free(filename);
|
||||
m_free(photo);
|
||||
|
||||
if(error)
|
||||
{
|
||||
free_attributes(uid);
|
||||
m_free(uid);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return uid;
|
||||
}
|
||||
|
||||
/* Returns 0 for error, 1 for valid */
|
||||
int parse_image_header(const struct user_attribute *attr,byte *type,u32 *len)
|
||||
{
|
||||
int headerlen;
|
||||
|
||||
if(attr->len<3)
|
||||
return 0;
|
||||
|
||||
/* For historical reasons (i.e. "oops!"), the header length is
|
||||
little endian. */
|
||||
headerlen=(attr->data[1]<<8) | attr->data[0];
|
||||
|
||||
if(headerlen>attr->len)
|
||||
return 0;
|
||||
|
||||
if(type && attr->len>=4)
|
||||
{
|
||||
if(attr->data[2]==1) /* header version 1 */
|
||||
*type=attr->data[3];
|
||||
else
|
||||
*type=0;
|
||||
}
|
||||
|
||||
*len=attr->len-headerlen;
|
||||
|
||||
if(*len==0)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* style==0 for extension, 1 for name, 2 for MIME type. Remember that
|
||||
the "name" style string could be used in a user ID name field, so
|
||||
make sure it is not too big (see
|
||||
parse-packet.c:parse_attribute). */
|
||||
char *image_type_to_string(byte type,int style)
|
||||
{
|
||||
char *string;
|
||||
|
||||
switch(type)
|
||||
{
|
||||
case 1: /* jpeg */
|
||||
if(style==0)
|
||||
string="jpg";
|
||||
else if(style==1)
|
||||
string="jpeg";
|
||||
else
|
||||
string="image/jpeg";
|
||||
break;
|
||||
|
||||
default:
|
||||
if(style==0)
|
||||
string="bin";
|
||||
else if(style==1)
|
||||
string="unknown";
|
||||
else
|
||||
string="image/x-unknown";
|
||||
break;
|
||||
}
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
static const char *get_default_photo_command(void)
|
||||
{
|
||||
#if defined(HAVE_DOSISH_SYSTEM)
|
||||
OSVERSIONINFO osvi;
|
||||
|
||||
memset(&osvi,0,sizeof(osvi));
|
||||
osvi.dwOSVersionInfoSize=sizeof(osvi);
|
||||
GetVersionEx(&osvi);
|
||||
|
||||
if(osvi.dwPlatformId==VER_PLATFORM_WIN32_WINDOWS)
|
||||
return "start /w %i";
|
||||
else
|
||||
return "cmd /c start /w %i";
|
||||
#elif defined(__APPLE__)
|
||||
/* OS X. This really needs more than just __APPLE__. */
|
||||
return "open %I";
|
||||
#elif defined(__riscos__)
|
||||
return "Filer_Run %I";
|
||||
#else
|
||||
return "xloadimage -fork -quiet -title 'KeyID 0x%k' stdin";
|
||||
#endif
|
||||
}
|
||||
|
||||
void show_photos(const struct user_attribute *attrs,
|
||||
int count,PKT_public_key *pk,PKT_secret_key *sk)
|
||||
{
|
||||
int i;
|
||||
struct expando_args args;
|
||||
u32 len;
|
||||
u32 kid[2]={0,0};
|
||||
|
||||
memset(&args,0,sizeof(args));
|
||||
args.pk=pk;
|
||||
args.sk=sk;
|
||||
|
||||
if(pk)
|
||||
keyid_from_pk(pk,kid);
|
||||
else if(sk)
|
||||
keyid_from_sk(sk,kid);
|
||||
|
||||
for(i=0;i<count;i++)
|
||||
if(attrs[i].type==ATTRIB_IMAGE &&
|
||||
parse_image_header(&attrs[i],&args.imagetype,&len))
|
||||
{
|
||||
char *command,*name;
|
||||
struct exec_info *spawn;
|
||||
int offset=attrs[i].len-len;
|
||||
|
||||
if(!opt.photo_viewer)
|
||||
opt.photo_viewer=get_default_photo_command();
|
||||
|
||||
/* make command grow */
|
||||
command=pct_expando(opt.photo_viewer,&args);
|
||||
if(!command)
|
||||
goto fail;
|
||||
|
||||
name=m_alloc(16+strlen(EXTSEP_S)+
|
||||
strlen(image_type_to_string(args.imagetype,0))+1);
|
||||
|
||||
/* Make the filename. Notice we are not using the image
|
||||
encoding type for more than cosmetics. Most external image
|
||||
viewers can handle a multitude of types, and even if one
|
||||
cannot understand a partcular type, we have no way to know
|
||||
which. The spec permits this, by the way. -dms */
|
||||
|
||||
#ifdef USE_ONLY_8DOT3
|
||||
sprintf(name,"%08lX" EXTSEP_S "%s",(ulong)kid[1],
|
||||
image_type_to_string(args.imagetype,0));
|
||||
#else
|
||||
sprintf(name,"%08lX%08lX" EXTSEP_S "%s",(ulong)kid[0],(ulong)kid[1],
|
||||
image_type_to_string(args.imagetype,0));
|
||||
#endif
|
||||
|
||||
if(exec_write(&spawn,NULL,command,name,1,1)!=0)
|
||||
{
|
||||
m_free(name);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
#ifdef __riscos__
|
||||
riscos_set_filetype(spawn->tempfile_in,
|
||||
image_type_to_string(args.imagetype,2));
|
||||
#endif
|
||||
|
||||
m_free(name);
|
||||
|
||||
fwrite(&attrs[i].data[offset],attrs[i].len-offset,1,spawn->tochild);
|
||||
|
||||
if(exec_read(spawn)!=0)
|
||||
{
|
||||
exec_finish(spawn);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if(exec_finish(spawn)!=0)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
fail:
|
||||
log_error("unable to display photo ID!\n");
|
||||
}
|
14
g10/photoid.h
Normal file
14
g10/photoid.h
Normal file
@ -0,0 +1,14 @@
|
||||
/* Photo ID functions */
|
||||
|
||||
#ifndef _PHOTOID_H_
|
||||
#define _PHOTOID_H_
|
||||
|
||||
#include "packet.h"
|
||||
|
||||
PKT_user_id *generate_photo_id(PKT_public_key *pk);
|
||||
int parse_image_header(const struct user_attribute *attr,byte *type,u32 *len);
|
||||
char *image_type_to_string(byte type,int style);
|
||||
void show_photos(const struct user_attribute *attrs,
|
||||
int count,PKT_public_key *pk,PKT_secret_key *sk);
|
||||
|
||||
#endif /* !_PHOTOID_H_ */
|
317
g10/pipemode.c
Normal file
317
g10/pipemode.c
Normal file
@ -0,0 +1,317 @@
|
||||
/* pipemode.c - pipemode handler
|
||||
* Copyright (C) 1998, 1990, 2000, 2001 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
* GnuPG is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GnuPG is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "options.h"
|
||||
#include "packet.h"
|
||||
#include "errors.h"
|
||||
#include "iobuf.h"
|
||||
#include "keydb.h"
|
||||
#include "memory.h"
|
||||
#include "util.h"
|
||||
#include "main.h"
|
||||
#include "status.h"
|
||||
#include "filter.h"
|
||||
|
||||
|
||||
#define CONTROL_PACKET_SPACE 30
|
||||
#define FAKED_LITERAL_PACKET_SPACE (9+2+2)
|
||||
|
||||
|
||||
enum pipemode_state_e {
|
||||
STX_init = 0,
|
||||
STX_wait_operation,
|
||||
STX_begin,
|
||||
STX_text,
|
||||
STX_detached_signature,
|
||||
STX_detached_signature_wait_text,
|
||||
STX_signed_data,
|
||||
STX_wait_init
|
||||
};
|
||||
|
||||
struct pipemode_context_s {
|
||||
enum pipemode_state_e state;
|
||||
int operation;
|
||||
int stop;
|
||||
int block_mode;
|
||||
UnarmorPump unarmor_ctx;
|
||||
};
|
||||
|
||||
|
||||
static size_t
|
||||
make_control ( byte *buf, int code, int operation )
|
||||
{
|
||||
const byte *sesmark;
|
||||
size_t sesmarklen, n=0;;
|
||||
|
||||
sesmark = get_session_marker( &sesmarklen );
|
||||
if ( sesmarklen > 20 )
|
||||
BUG();
|
||||
|
||||
buf[n++] = 0xff; /* new format, type 63, 1 length byte */
|
||||
n++; /* length will fixed below */
|
||||
memcpy(buf+n, sesmark, sesmarklen ); n+= sesmarklen;
|
||||
buf[n++] = CTRLPKT_PIPEMODE;
|
||||
buf[n++] = code;
|
||||
buf[n++] = operation;
|
||||
buf[1] = n-2;
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int
|
||||
pipemode_filter( void *opaque, int control,
|
||||
IOBUF a, byte *buf, size_t *ret_len)
|
||||
{
|
||||
size_t size = *ret_len;
|
||||
struct pipemode_context_s *stx = opaque;
|
||||
int rc=0;
|
||||
size_t n = 0;
|
||||
int esc = 0;
|
||||
|
||||
if( control == IOBUFCTRL_UNDERFLOW ) {
|
||||
*ret_len = 0;
|
||||
/* reserve some space for one control packet */
|
||||
if ( size <= CONTROL_PACKET_SPACE+FAKED_LITERAL_PACKET_SPACE )
|
||||
BUG();
|
||||
size -= CONTROL_PACKET_SPACE+FAKED_LITERAL_PACKET_SPACE;
|
||||
|
||||
if ( stx->block_mode ) {
|
||||
/* reserve 2 bytes for the block length */
|
||||
buf[n++] = 0;
|
||||
buf[n++] = 0;
|
||||
}
|
||||
|
||||
|
||||
while ( n < size ) {
|
||||
/* FIXME: we have to make sure that we have a large enough
|
||||
* buffer for a control packet even after we already read
|
||||
* something. The easest way to do this is probably by ungetting
|
||||
* the control sequence and returning the buffer we have
|
||||
* already assembled */
|
||||
int c = iobuf_get (a);
|
||||
if (c == -1) {
|
||||
if ( stx->state != STX_init ) {
|
||||
log_error ("EOF encountered at wrong state\n");
|
||||
stx->stop = 1;
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if ( esc ) {
|
||||
switch (c) {
|
||||
case '@':
|
||||
if ( stx->state == STX_text ) {
|
||||
buf[n++] = c;
|
||||
break;
|
||||
}
|
||||
else if ( stx->state == STX_detached_signature ) {
|
||||
esc = 0;
|
||||
goto do_unarmor; /* not a very elegant solution */
|
||||
}
|
||||
else if ( stx->state == STX_detached_signature_wait_text) {
|
||||
esc = 0;
|
||||
break; /* just ignore it in this state */
|
||||
}
|
||||
log_error ("@@ not allowed in current state\n");
|
||||
return -1;
|
||||
case '<': /* begin of stream part */
|
||||
if ( stx->state != STX_init ) {
|
||||
log_error ("nested begin of stream\n");
|
||||
stx->stop = 1;
|
||||
return -1;
|
||||
}
|
||||
stx->state = STX_wait_operation;
|
||||
stx->block_mode = 0;
|
||||
unarmor_pump_release (stx->unarmor_ctx);
|
||||
stx->unarmor_ctx = NULL;
|
||||
break;
|
||||
case '>': /* end of stream part */
|
||||
if ( stx->state != STX_wait_init ) {
|
||||
log_error ("invalid state for @>\n");
|
||||
stx->stop = 1;
|
||||
return -1;
|
||||
}
|
||||
stx->state = STX_init;
|
||||
break;
|
||||
case 'V': /* operation = verify */
|
||||
case 'E': /* operation = encrypt */
|
||||
case 'S': /* operation = sign */
|
||||
case 'B': /* operation = detach sign */
|
||||
case 'C': /* operation = clearsign */
|
||||
case 'D': /* operation = decrypt */
|
||||
if ( stx->state != STX_wait_operation ) {
|
||||
log_error ("invalid state for operation code\n");
|
||||
stx->stop = 1;
|
||||
return -1;
|
||||
}
|
||||
stx->operation = c;
|
||||
if ( stx->operation == 'B') {
|
||||
stx->state = STX_detached_signature;
|
||||
if ( !opt.no_armor )
|
||||
stx->unarmor_ctx = unarmor_pump_new ();
|
||||
}
|
||||
else
|
||||
stx->state = STX_begin;
|
||||
n += make_control ( buf+n, 1, stx->operation );
|
||||
/* must leave after a control packet */
|
||||
goto leave;
|
||||
|
||||
case 't': /* plaintext text follows */
|
||||
if ( stx->state == STX_detached_signature_wait_text )
|
||||
stx->state = STX_detached_signature;
|
||||
if ( stx->state == STX_detached_signature ) {
|
||||
if ( stx->operation != 'B' ) {
|
||||
log_error ("invalid operation for this state\n");
|
||||
stx->stop = 1;
|
||||
return -1;
|
||||
}
|
||||
stx->state = STX_signed_data;
|
||||
n += make_control ( buf+n, 2, 'B' );
|
||||
/* and now we fake a literal data packet much the same
|
||||
* as in armor.c */
|
||||
buf[n++] = 0xaf; /* old packet format, type 11,
|
||||
var length */
|
||||
buf[n++] = 0; /* set the length header */
|
||||
buf[n++] = 6;
|
||||
buf[n++] = 'b'; /* we ignore it anyway */
|
||||
buf[n++] = 0; /* namelength */
|
||||
memset(buf+n, 0, 4); /* timestamp */
|
||||
n += 4;
|
||||
/* and return now so that we are sure to have
|
||||
* more space in the bufer for the next control
|
||||
* packet */
|
||||
stx->block_mode = 1;
|
||||
goto leave2;
|
||||
}
|
||||
else {
|
||||
log_error ("invalid state for @t\n");
|
||||
stx->stop = 1;
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case '.': /* ready */
|
||||
if ( stx->state == STX_signed_data ) {
|
||||
if (stx->block_mode) {
|
||||
buf[0] = (n-2) >> 8;
|
||||
buf[1] = (n-2);
|
||||
if ( buf[0] || buf[1] ) {
|
||||
/* end of blocks marker */
|
||||
buf[n++] = 0;
|
||||
buf[n++] = 0;
|
||||
}
|
||||
stx->block_mode = 0;
|
||||
}
|
||||
n += make_control ( buf+n, 3, 'B' );
|
||||
}
|
||||
else {
|
||||
log_error ("invalid state for @.\n");
|
||||
stx->stop = 1;
|
||||
return -1;
|
||||
}
|
||||
stx->state = STX_wait_init;
|
||||
goto leave;
|
||||
|
||||
default:
|
||||
log_error ("invalid escape sequence 0x%02x in stream\n",
|
||||
c);
|
||||
stx->stop = 1;
|
||||
return -1;
|
||||
}
|
||||
esc = 0;
|
||||
}
|
||||
else if (c == '@')
|
||||
esc = 1;
|
||||
else if (stx->unarmor_ctx) {
|
||||
do_unarmor: /* used to handle a @@ */
|
||||
c = unarmor_pump (stx->unarmor_ctx, c);
|
||||
if ( !(c & ~255) )
|
||||
buf[n++] = c;
|
||||
else if ( c < 0 ) {
|
||||
/* end of armor or error - we don't care becuase
|
||||
the armor can be modified anyway. The unarmored
|
||||
stuff should stand for itself. */
|
||||
unarmor_pump_release (stx->unarmor_ctx);
|
||||
stx->unarmor_ctx = NULL;
|
||||
stx->state = STX_detached_signature_wait_text;
|
||||
}
|
||||
}
|
||||
else if (stx->state == STX_detached_signature_wait_text)
|
||||
; /* just wait */
|
||||
else
|
||||
buf[n++] = c;
|
||||
}
|
||||
|
||||
leave:
|
||||
if ( !n ) {
|
||||
stx->stop = 1;
|
||||
rc = -1; /* eof */
|
||||
}
|
||||
if ( stx->block_mode ) {
|
||||
/* fixup the block length */
|
||||
buf[0] = (n-2) >> 8;
|
||||
buf[1] = (n-2);
|
||||
}
|
||||
leave2:
|
||||
/*log_hexdump ("pipemode:", buf, n );*/
|
||||
*ret_len = n;
|
||||
}
|
||||
else if( control == IOBUFCTRL_DESC )
|
||||
*(char**)buf = "pipemode_filter";
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
run_in_pipemode(void)
|
||||
{
|
||||
IOBUF fp;
|
||||
armor_filter_context_t afx;
|
||||
struct pipemode_context_s stx;
|
||||
int rc;
|
||||
|
||||
memset( &afx, 0, sizeof afx);
|
||||
memset( &stx, 0, sizeof stx);
|
||||
|
||||
fp = iobuf_open("-");
|
||||
iobuf_push_filter (fp, pipemode_filter, &stx );
|
||||
|
||||
do {
|
||||
write_status (STATUS_BEGIN_STREAM);
|
||||
rc = proc_packets( NULL, fp );
|
||||
write_status (STATUS_END_STREAM);
|
||||
} while ( !stx.stop );
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
1094
g10/pkclist.c
1094
g10/pkclist.c
File diff suppressed because it is too large
Load Diff
135
g10/plaintext.c
135
g10/plaintext.c
@ -1,5 +1,5 @@
|
||||
/* plaintext.c - process an plaintext packet
|
||||
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
|
||||
/* plaintext.c - process plaintext packets
|
||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
@ -29,7 +29,7 @@
|
||||
#endif
|
||||
|
||||
#include "util.h"
|
||||
#include <gcrypt.h>
|
||||
#include "memory.h"
|
||||
#include "options.h"
|
||||
#include "packet.h"
|
||||
#include "ttyio.h"
|
||||
@ -60,7 +60,7 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx,
|
||||
if( nooutput )
|
||||
;
|
||||
else if( opt.outfile ) {
|
||||
fname = gcry_xmalloc( strlen( opt.outfile ) + 1);
|
||||
fname = m_alloc( strlen( opt.outfile ) + 1);
|
||||
strcpy(fname, opt.outfile );
|
||||
}
|
||||
else if( pt->namelen == 8 && !memcmp( pt->name, "_CONSOLE", 8 ) ) {
|
||||
@ -72,7 +72,7 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx,
|
||||
if( !fname )
|
||||
fname = ask_outfile_name( pt->name, pt->namelen );
|
||||
if( !fname ) {
|
||||
rc = GPGERR_CREATE_FILE;
|
||||
rc = G10ERR_CREATE_FILE;
|
||||
goto leave;
|
||||
}
|
||||
}
|
||||
@ -89,31 +89,44 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx,
|
||||
setmode ( fileno(fp) , O_BINARY );
|
||||
#endif
|
||||
}
|
||||
else if( !overwrite_filep( fname ) ) {
|
||||
rc = GPGERR_CREATE_FILE;
|
||||
goto leave;
|
||||
else {
|
||||
while( !overwrite_filep (fname) ) {
|
||||
char *tmp = ask_outfile_name (NULL, 0);
|
||||
if ( !tmp || !*tmp ) {
|
||||
m_free (tmp);
|
||||
rc = G10ERR_CREATE_FILE;
|
||||
goto leave;
|
||||
}
|
||||
m_free (fname);
|
||||
fname = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
if( fp || nooutput )
|
||||
;
|
||||
else if( !(fp = fopen(fname,"wb")) ) {
|
||||
log_error("Error creating `%s': %s\n", fname, strerror(errno) );
|
||||
rc = GPGERR_CREATE_FILE;
|
||||
log_error(_("error creating `%s': %s\n"), fname, strerror(errno) );
|
||||
rc = G10ERR_CREATE_FILE;
|
||||
#ifdef __riscos__
|
||||
if (errno == 106)
|
||||
log_info("perhaps the output file has the same name as the input file?\n");
|
||||
#endif /* __riscos__ */
|
||||
goto leave;
|
||||
}
|
||||
|
||||
if( pt->len ) {
|
||||
if( !pt->is_partial ) {
|
||||
/* we have an actual length (which might be zero). */
|
||||
assert( !clearsig );
|
||||
if( convert ) { /* text mode */
|
||||
for( ; pt->len; pt->len-- ) {
|
||||
if( (c = iobuf_get(pt->buf)) == -1 ) {
|
||||
log_error("Problem reading source (%u bytes remaining)\n",
|
||||
(unsigned)pt->len);
|
||||
rc = GPGERR_READ_FILE;
|
||||
rc = G10ERR_READ_FILE;
|
||||
goto leave;
|
||||
}
|
||||
if( mfx->md )
|
||||
gcry_md_putc(mfx->md, c );
|
||||
md_putc(mfx->md, c );
|
||||
#ifndef HAVE_DOSISH_SYSTEM
|
||||
if( c == '\r' ) /* convert to native line ending */
|
||||
continue; /* fixme: this hack might be too simple */
|
||||
@ -122,45 +135,45 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx,
|
||||
if( putc( c, fp ) == EOF ) {
|
||||
log_error("Error writing to `%s': %s\n",
|
||||
fname, strerror(errno) );
|
||||
rc = GPGERR_WRITE_FILE;
|
||||
rc = G10ERR_WRITE_FILE;
|
||||
goto leave;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else { /* binary mode */
|
||||
byte *buffer = gcry_xmalloc( 32768 );
|
||||
byte *buffer = m_alloc( 32768 );
|
||||
while( pt->len ) {
|
||||
int len = pt->len > 32768 ? 32768 : pt->len;
|
||||
len = iobuf_read( pt->buf, buffer, len );
|
||||
if( len == -1 ) {
|
||||
log_error("Problem reading source (%u bytes remaining)\n",
|
||||
(unsigned)pt->len);
|
||||
rc = GPGERR_READ_FILE;
|
||||
gcry_free( buffer );
|
||||
rc = G10ERR_READ_FILE;
|
||||
m_free( buffer );
|
||||
goto leave;
|
||||
}
|
||||
if( mfx->md )
|
||||
gcry_md_write( mfx->md, buffer, len );
|
||||
md_write( mfx->md, buffer, len );
|
||||
if( fp ) {
|
||||
if( fwrite( buffer, 1, len, fp ) != len ) {
|
||||
log_error("Error writing to `%s': %s\n",
|
||||
fname, strerror(errno) );
|
||||
rc = GPGERR_WRITE_FILE;
|
||||
gcry_free( buffer );
|
||||
rc = G10ERR_WRITE_FILE;
|
||||
m_free( buffer );
|
||||
goto leave;
|
||||
}
|
||||
}
|
||||
pt->len -= len;
|
||||
}
|
||||
gcry_free( buffer );
|
||||
m_free( buffer );
|
||||
}
|
||||
}
|
||||
else if( !clearsig ) {
|
||||
if( convert ) { /* text mode */
|
||||
while( (c = iobuf_get(pt->buf)) != -1 ) {
|
||||
if( mfx->md )
|
||||
gcry_md_putc(mfx->md, c );
|
||||
md_putc(mfx->md, c );
|
||||
#ifndef HAVE_DOSISH_SYSTEM
|
||||
if( convert && c == '\r' )
|
||||
continue; /* fixme: this hack might be too simple */
|
||||
@ -169,14 +182,14 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx,
|
||||
if( putc( c, fp ) == EOF ) {
|
||||
log_error("Error writing to `%s': %s\n",
|
||||
fname, strerror(errno) );
|
||||
rc = GPGERR_WRITE_FILE;
|
||||
rc = G10ERR_WRITE_FILE;
|
||||
goto leave;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else { /* binary mode */
|
||||
byte *buffer = gcry_xmalloc( 32768 );
|
||||
byte *buffer = m_alloc( 32768 );
|
||||
int eof;
|
||||
for( eof=0; !eof; ) {
|
||||
/* Why do we check for len < 32768:
|
||||
@ -191,18 +204,18 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx,
|
||||
if( len < 32768 )
|
||||
eof = 1;
|
||||
if( mfx->md )
|
||||
gcry_md_write( mfx->md, buffer, len );
|
||||
md_write( mfx->md, buffer, len );
|
||||
if( fp ) {
|
||||
if( fwrite( buffer, 1, len, fp ) != len ) {
|
||||
log_error("Error writing to `%s': %s\n",
|
||||
fname, strerror(errno) );
|
||||
rc = GPGERR_WRITE_FILE;
|
||||
gcry_free( buffer );
|
||||
rc = G10ERR_WRITE_FILE;
|
||||
m_free( buffer );
|
||||
goto leave;
|
||||
}
|
||||
}
|
||||
}
|
||||
gcry_free( buffer );
|
||||
m_free( buffer );
|
||||
}
|
||||
pt->buf = NULL;
|
||||
}
|
||||
@ -214,15 +227,15 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx,
|
||||
if( putc( c, fp ) == EOF ) {
|
||||
log_error("Error writing to `%s': %s\n",
|
||||
fname, strerror(errno) );
|
||||
rc = GPGERR_WRITE_FILE;
|
||||
rc = G10ERR_WRITE_FILE;
|
||||
goto leave;
|
||||
}
|
||||
}
|
||||
if( !mfx->md )
|
||||
continue;
|
||||
if( state == 2 ) {
|
||||
gcry_md_putc(mfx->md, '\r' );
|
||||
gcry_md_putc(mfx->md, '\n' );
|
||||
md_putc(mfx->md, '\r' );
|
||||
md_putc(mfx->md, '\n' );
|
||||
state = 0;
|
||||
}
|
||||
if( !state ) {
|
||||
@ -231,18 +244,18 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx,
|
||||
else if( c == '\n' )
|
||||
state = 2;
|
||||
else
|
||||
gcry_md_putc(mfx->md, c );
|
||||
md_putc(mfx->md, c );
|
||||
}
|
||||
else if( state == 1 ) {
|
||||
if( c == '\n' )
|
||||
state = 2;
|
||||
else {
|
||||
gcry_md_putc(mfx->md, '\r' );
|
||||
md_putc(mfx->md, '\r' );
|
||||
if( c == '\r' )
|
||||
state = 1;
|
||||
else {
|
||||
state = 0;
|
||||
gcry_md_putc(mfx->md, c );
|
||||
md_putc(mfx->md, c );
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -253,7 +266,7 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx,
|
||||
if( fp && fp != stdout && fclose(fp) ) {
|
||||
log_error("Error closing `%s': %s\n", fname, strerror(errno) );
|
||||
fp = NULL;
|
||||
rc = GPGERR_WRITE_FILE;
|
||||
rc = G10ERR_WRITE_FILE;
|
||||
goto leave;
|
||||
}
|
||||
fp = NULL;
|
||||
@ -261,12 +274,12 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx,
|
||||
leave:
|
||||
if( fp && fp != stdout )
|
||||
fclose(fp);
|
||||
gcry_free(fname);
|
||||
m_free(fname);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void
|
||||
do_hash( GCRY_MD_HD md, GCRY_MD_HD md2, IOBUF fp, int textmode )
|
||||
do_hash( MD_HANDLE md, MD_HANDLE md2, IOBUF fp, int textmode )
|
||||
{
|
||||
text_filter_context_t tfx;
|
||||
int c;
|
||||
@ -280,27 +293,27 @@ do_hash( GCRY_MD_HD md, GCRY_MD_HD md2, IOBUF fp, int textmode )
|
||||
int lc = -1;
|
||||
while( (c = iobuf_get(fp)) != -1 ) {
|
||||
if( c == '\n' && lc == '\r' )
|
||||
gcry_md_putc(md2, c);
|
||||
md_putc(md2, c);
|
||||
else if( c == '\n' ) {
|
||||
gcry_md_putc(md2, '\r');
|
||||
gcry_md_putc(md2, c);
|
||||
md_putc(md2, '\r');
|
||||
md_putc(md2, c);
|
||||
}
|
||||
else if( c != '\n' && lc == '\r' ) {
|
||||
gcry_md_putc(md2, '\n');
|
||||
gcry_md_putc(md2, c);
|
||||
md_putc(md2, '\n');
|
||||
md_putc(md2, c);
|
||||
}
|
||||
else
|
||||
gcry_md_putc(md2, c);
|
||||
md_putc(md2, c);
|
||||
|
||||
if( md )
|
||||
gcry_md_putc(md, c );
|
||||
md_putc(md, c );
|
||||
lc = c;
|
||||
}
|
||||
}
|
||||
else {
|
||||
while( (c = iobuf_get(fp)) != -1 ) {
|
||||
if( md )
|
||||
gcry_md_putc(md, c );
|
||||
md_putc(md, c );
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -311,7 +324,7 @@ do_hash( GCRY_MD_HD md, GCRY_MD_HD md2, IOBUF fp, int textmode )
|
||||
* INFILE is the name of the input file.
|
||||
*/
|
||||
int
|
||||
ask_for_detached_datafile( GCRY_MD_HD md, GCRY_MD_HD md2,
|
||||
ask_for_detached_datafile( MD_HANDLE md, MD_HANDLE md2,
|
||||
const char *inname, int textmode )
|
||||
{
|
||||
char *answer = NULL;
|
||||
@ -323,12 +336,12 @@ ask_for_detached_datafile( GCRY_MD_HD md, GCRY_MD_HD md2,
|
||||
int any=0;
|
||||
tty_printf(_("Detached signature.\n"));
|
||||
do {
|
||||
gcry_free(answer);
|
||||
m_free(answer);
|
||||
answer = cpr_get("detached_signature.filename",
|
||||
_("Please enter name of data file: "));
|
||||
cpr_kill_prompt();
|
||||
if( any && !*answer ) {
|
||||
rc = GPGERR_READ_FILE;
|
||||
rc = G10ERR_READ_FILE;
|
||||
goto leave;
|
||||
}
|
||||
fp = iobuf_open(answer);
|
||||
@ -338,7 +351,7 @@ ask_for_detached_datafile( GCRY_MD_HD md, GCRY_MD_HD md2,
|
||||
}
|
||||
else if( !fp ) {
|
||||
log_error("can't open `%s': %s\n", answer, strerror(errno) );
|
||||
rc = GPGERR_READ_FILE;
|
||||
rc = G10ERR_READ_FILE;
|
||||
goto leave;
|
||||
}
|
||||
} while( !fp );
|
||||
@ -355,7 +368,7 @@ ask_for_detached_datafile( GCRY_MD_HD md, GCRY_MD_HD md2,
|
||||
|
||||
|
||||
leave:
|
||||
gcry_free(answer);
|
||||
m_free(answer);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -366,11 +379,11 @@ ask_for_detached_datafile( GCRY_MD_HD md, GCRY_MD_HD md2,
|
||||
* If FILES is NULL, hash stdin.
|
||||
*/
|
||||
int
|
||||
hash_datafiles( GCRY_MD_HD md, GCRY_MD_HD md2, STRLIST files,
|
||||
hash_datafiles( MD_HANDLE md, MD_HANDLE md2, STRLIST files,
|
||||
const char *sigfilename, int textmode )
|
||||
{
|
||||
IOBUF fp;
|
||||
STRLIST sl=NULL;
|
||||
STRLIST sl;
|
||||
|
||||
if( !files ) {
|
||||
/* check whether we can open the signed material */
|
||||
@ -380,28 +393,26 @@ hash_datafiles( GCRY_MD_HD md, GCRY_MD_HD md2, STRLIST files,
|
||||
iobuf_close(fp);
|
||||
return 0;
|
||||
}
|
||||
/* no we can't (no sigfile) - read signed stuff from stdin */
|
||||
add_to_strlist( &sl, "-");
|
||||
log_error (_("no signed data\n"));
|
||||
return G10ERR_OPEN_FILE;
|
||||
}
|
||||
else
|
||||
sl = files;
|
||||
|
||||
for( ; sl; sl = sl->next ) {
|
||||
|
||||
for (sl=files; sl; sl = sl->next ) {
|
||||
fp = iobuf_open( sl->d );
|
||||
if( !fp ) {
|
||||
log_error(_("can't open signed data `%s'\n"),
|
||||
print_fname_stdin(sl->d));
|
||||
if( !files )
|
||||
free_strlist(sl);
|
||||
return GPGERR_OPEN_FILE;
|
||||
return G10ERR_OPEN_FILE;
|
||||
}
|
||||
do_hash( md, md2, fp, textmode );
|
||||
iobuf_close(fp);
|
||||
}
|
||||
|
||||
if( !files )
|
||||
free_strlist(sl);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
225
g10/pubkey-enc.c
225
g10/pubkey-enc.c
@ -1,5 +1,5 @@
|
||||
/* pubkey-enc.c - public key encoded packet handling
|
||||
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
|
||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
@ -23,12 +23,13 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <gcrypt.h>
|
||||
#include "util.h"
|
||||
#include "memory.h"
|
||||
#include "packet.h"
|
||||
#include "mpi.h"
|
||||
#include "keydb.h"
|
||||
#include "trustdb.h"
|
||||
#include "cipher.h"
|
||||
#include "status.h"
|
||||
#include "options.h"
|
||||
#include "main.h"
|
||||
@ -38,66 +39,31 @@ static int get_it( PKT_pubkey_enc *k,
|
||||
DEK *dek, PKT_secret_key *sk, u32 *keyid );
|
||||
|
||||
|
||||
/****************
|
||||
* Emulate our old PK interface here - sometime in the future we might
|
||||
* change the internal design to directly fit to libgcrypt.
|
||||
*/
|
||||
/* check that the given algo is mentioned in one of the valid user IDs */
|
||||
static int
|
||||
pk_decrypt( int algo, MPI *result, MPI *data, MPI *skey )
|
||||
is_algo_in_prefs ( KBNODE keyblock, preftype_t type, int algo )
|
||||
{
|
||||
GCRY_SEXP s_skey, s_data, s_plain;
|
||||
int rc;
|
||||
KBNODE k;
|
||||
|
||||
*result = NULL;
|
||||
/* make a sexp from skey */
|
||||
if( algo == GCRY_PK_ELG || algo == GCRY_PK_ELG_E ) {
|
||||
rc = gcry_sexp_build ( &s_skey, NULL,
|
||||
"(private-key(elg(p%m)(g%m)(y%m)(x%m)))",
|
||||
skey[0], skey[1], skey[2], skey[3] );
|
||||
for (k=keyblock; k; k=k->next) {
|
||||
if (k->pkt->pkttype == PKT_USER_ID) {
|
||||
PKT_user_id *uid = k->pkt->pkt.user_id;
|
||||
prefitem_t *prefs = uid->prefs;
|
||||
|
||||
if (uid->created && prefs &&
|
||||
!uid->is_revoked && !uid->is_expired ) {
|
||||
for (; prefs->type; prefs++ )
|
||||
if (prefs->type == type && prefs->value == algo)
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( algo == GCRY_PK_RSA ) {
|
||||
rc = gcry_sexp_build ( &s_skey, NULL,
|
||||
"(private-key(rsa(n%m)(e%m)(d%m)(p%m)(q%m)(u%m)))",
|
||||
skey[0], skey[1], skey[2], skey[3], skey[4], skey[5] );
|
||||
}
|
||||
else
|
||||
return GPGERR_PUBKEY_ALGO;
|
||||
|
||||
if ( rc )
|
||||
BUG ();
|
||||
|
||||
/* put data into a S-Exp s_data */
|
||||
if( algo == GCRY_PK_ELG || algo == GCRY_PK_ELG_E ) {
|
||||
rc = gcry_sexp_build ( &s_data, NULL,
|
||||
"(enc-val(elg(a%m)(b%m)))", data[0], data[1] );
|
||||
}
|
||||
else if( algo == GCRY_PK_RSA ) {
|
||||
rc = gcry_sexp_build ( &s_data, NULL,
|
||||
"(enc-val(rsa(a%m)))", data[0] );
|
||||
}
|
||||
else
|
||||
BUG();
|
||||
|
||||
if ( rc )
|
||||
BUG ();
|
||||
|
||||
rc = gcry_pk_decrypt( &s_plain, s_data, s_skey );
|
||||
gcry_sexp_release( s_skey );
|
||||
gcry_sexp_release( s_data);
|
||||
if( rc )
|
||||
return rc;
|
||||
|
||||
*result = gcry_sexp_nth_mpi( s_plain, 0, 0 );
|
||||
gcry_sexp_release( s_plain );
|
||||
if( !*result )
|
||||
return -1; /* oops */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
* Get the session key from a pubkey enc paket and return
|
||||
* Get the session key from a pubkey enc packet and return
|
||||
* it in DEK, which should have been allocated in secure memory.
|
||||
*/
|
||||
int
|
||||
@ -106,12 +72,12 @@ get_session_key( PKT_pubkey_enc *k, DEK *dek )
|
||||
PKT_secret_key *sk = NULL;
|
||||
int rc;
|
||||
|
||||
rc = openpgp_pk_test_algo( k->pubkey_algo, 0 );
|
||||
rc = check_pubkey_algo2 (k->pubkey_algo, PUBKEY_USAGE_ENC);
|
||||
if( rc )
|
||||
goto leave;
|
||||
|
||||
if( (k->keyid[0] || k->keyid[1]) && !opt.try_all_secrets ) {
|
||||
sk = gcry_xcalloc( 1, sizeof *sk );
|
||||
sk = m_alloc_clear( sizeof *sk );
|
||||
sk->pubkey_algo = k->pubkey_algo; /* we want a pubkey with this algo*/
|
||||
if( !(rc = get_seckey( sk, k->keyid )) )
|
||||
rc = get_it( k, dek, sk, k->keyid );
|
||||
@ -123,17 +89,17 @@ get_session_key( PKT_pubkey_enc *k, DEK *dek )
|
||||
for(;;) {
|
||||
if( sk )
|
||||
free_secret_key( sk );
|
||||
sk = gcry_xcalloc( 1, sizeof *sk );
|
||||
sk = m_alloc_clear( sizeof *sk );
|
||||
rc=enum_secret_keys( &enum_context, sk, 1);
|
||||
if( rc ) {
|
||||
rc = GPGERR_NO_SECKEY;
|
||||
rc = G10ERR_NO_SECKEY;
|
||||
break;
|
||||
}
|
||||
if( sk->pubkey_algo != k->pubkey_algo )
|
||||
continue;
|
||||
keyid_from_sk( sk, keyid );
|
||||
log_info(_("anonymous receiver; trying secret key %08lX ...\n"),
|
||||
(ulong)keyid[1] );
|
||||
log_info(_("anonymous recipient; trying secret key %08lX ...\n"),
|
||||
(ulong)keyid[1] );
|
||||
rc = check_secret_key( sk, 1 ); /* ask only once */
|
||||
if( !rc )
|
||||
rc = get_it( k, dek, sk, keyid );
|
||||
@ -153,22 +119,19 @@ get_session_key( PKT_pubkey_enc *k, DEK *dek )
|
||||
|
||||
|
||||
static int
|
||||
get_it( PKT_pubkey_enc *k, DEK *dek, PKT_secret_key *sk, u32 *keyid )
|
||||
get_it( PKT_pubkey_enc *enc, DEK *dek, PKT_secret_key *sk, u32 *keyid )
|
||||
{
|
||||
int rc;
|
||||
MPI plain_dek = NULL;
|
||||
byte *frame = NULL;
|
||||
unsigned int n;
|
||||
size_t nframe;
|
||||
unsigned n, nframe;
|
||||
u16 csum, csum2;
|
||||
|
||||
rc = pk_decrypt(sk->pubkey_algo, &plain_dek, k->data, sk->skey );
|
||||
rc = pubkey_decrypt(sk->pubkey_algo, &plain_dek, enc->data, sk->skey );
|
||||
if( rc )
|
||||
goto leave;
|
||||
if( gcry_mpi_aprint( GCRYMPI_FMT_USG, &frame, &nframe, plain_dek ) )
|
||||
BUG();
|
||||
|
||||
mpi_release( plain_dek ); plain_dek = NULL;
|
||||
frame = mpi_get_buffer( plain_dek, &nframe, NULL );
|
||||
mpi_free( plain_dek ); plain_dek = NULL;
|
||||
|
||||
/* Now get the DEK (data encryption key) from the frame
|
||||
*
|
||||
@ -180,8 +143,7 @@ get_it( PKT_pubkey_enc *k, DEK *dek, PKT_secret_key *sk, u32 *keyid )
|
||||
*
|
||||
* 0 2 RND(n bytes) 0 A DEK(k bytes) CSUM(2 bytes)
|
||||
*
|
||||
* (mpi_get_buffer already removed the leading zero - still true
|
||||
* for gcry_mpi_aprint(0 which is used now?)
|
||||
* (mpi_get_buffer already removed the leading zero).
|
||||
*
|
||||
* RND are non-zero randow bytes.
|
||||
* A is the cipher algorithm
|
||||
@ -192,35 +154,37 @@ get_it( PKT_pubkey_enc *k, DEK *dek, PKT_secret_key *sk, u32 *keyid )
|
||||
log_hexdump("DEK frame:", frame, nframe );
|
||||
n=0;
|
||||
if( n + 7 > nframe )
|
||||
{ rc = GPGERR_WRONG_SECKEY; goto leave; }
|
||||
{ rc = G10ERR_WRONG_SECKEY; goto leave; }
|
||||
if( frame[n] == 1 && frame[nframe-1] == 2 ) {
|
||||
log_info(_("old encoding of the DEK is not supported\n"));
|
||||
rc = GPGERR_CIPHER_ALGO;
|
||||
rc = G10ERR_CIPHER_ALGO;
|
||||
goto leave;
|
||||
}
|
||||
if( frame[n] != 2 ) /* somethink is wrong */
|
||||
{ rc = GPGERR_WRONG_SECKEY; goto leave; }
|
||||
{ rc = G10ERR_WRONG_SECKEY; goto leave; }
|
||||
for(n++; n < nframe && frame[n]; n++ ) /* skip the random bytes */
|
||||
;
|
||||
n++; /* and the zero byte */
|
||||
if( n + 4 > nframe )
|
||||
{ rc = GPGERR_WRONG_SECKEY; goto leave; }
|
||||
{ rc = G10ERR_WRONG_SECKEY; goto leave; }
|
||||
|
||||
dek->keylen = nframe - (n+1) - 2;
|
||||
dek->algo = frame[n++];
|
||||
if( dek->algo == GCRY_CIPHER_IDEA )
|
||||
if( dek->algo == CIPHER_ALGO_IDEA )
|
||||
write_status(STATUS_RSA_OR_IDEA);
|
||||
rc = openpgp_cipher_test_algo( dek->algo );
|
||||
rc = check_cipher_algo( dek->algo );
|
||||
if( rc ) {
|
||||
if( !opt.quiet && rc == GPGERR_CIPHER_ALGO ) {
|
||||
log_info(_("cipher algorithm %d is unknown or disabled\n"),
|
||||
dek->algo);
|
||||
if( !opt.quiet && rc == G10ERR_CIPHER_ALGO ) {
|
||||
log_info(_("cipher algorithm %d%s is unknown or disabled\n"),
|
||||
dek->algo, dek->algo == CIPHER_ALGO_IDEA? " (IDEA)":"");
|
||||
if(dek->algo==CIPHER_ALGO_IDEA)
|
||||
idea_cipher_warn(0);
|
||||
}
|
||||
dek->algo = 0;
|
||||
goto leave;
|
||||
}
|
||||
if( dek->keylen != gcry_cipher_get_algo_keylen( dek->algo ) ) {
|
||||
rc = GPGERR_WRONG_SECKEY;
|
||||
if( (dek->keylen*8) != cipher_get_keylen( dek->algo ) ) {
|
||||
rc = G10ERR_WRONG_SECKEY;
|
||||
goto leave;
|
||||
}
|
||||
|
||||
@ -231,53 +195,102 @@ get_it( PKT_pubkey_enc *k, DEK *dek, PKT_secret_key *sk, u32 *keyid )
|
||||
for( csum2=0, n=0; n < dek->keylen; n++ )
|
||||
csum2 += dek->key[n];
|
||||
if( csum != csum2 ) {
|
||||
rc = GPGERR_WRONG_SECKEY;
|
||||
rc = G10ERR_WRONG_SECKEY;
|
||||
goto leave;
|
||||
}
|
||||
if( DBG_CIPHER )
|
||||
log_hexdump("DEK is:", dek->key, dek->keylen );
|
||||
/* check that the algo is in the preferences and whether it has expired */
|
||||
{
|
||||
PKT_public_key *pk = gcry_xcalloc( 1, sizeof *pk );
|
||||
if( (rc = get_pubkey( pk, keyid )) )
|
||||
log_error("public key problem: %s\n", gpg_errstr(rc) );
|
||||
else if( !pk->local_id && query_trust_record(pk) )
|
||||
log_error("can't check algorithm against preferences\n");
|
||||
else if( dek->algo != GCRY_CIPHER_3DES
|
||||
&& !is_algo_in_prefs( pk->local_id, PREFTYPE_SYM, dek->algo ) ) {
|
||||
PKT_public_key *pk = NULL;
|
||||
KBNODE pkb = get_pubkeyblock (keyid);
|
||||
|
||||
if( !pkb ) {
|
||||
rc = -1;
|
||||
log_error("oops: public key not found for preference check\n");
|
||||
}
|
||||
else if( pkb->pkt->pkt.public_key->selfsigversion > 3
|
||||
&& dek->algo != CIPHER_ALGO_3DES
|
||||
&& !is_algo_in_prefs( pkb, PREFTYPE_SYM, dek->algo ) ) {
|
||||
/* Don't print a note while we are not on verbose mode,
|
||||
* the cipher is blowfish and the preferences have twofish
|
||||
* listed */
|
||||
if( opt.verbose || dek->algo != GCRY_CIPHER_BLOWFISH
|
||||
|| !is_algo_in_prefs( pk->local_id, PREFTYPE_SYM,
|
||||
GCRY_CIPHER_TWOFISH ) )
|
||||
if( opt.verbose || dek->algo != CIPHER_ALGO_BLOWFISH
|
||||
|| !is_algo_in_prefs( pkb, PREFTYPE_SYM, CIPHER_ALGO_TWOFISH))
|
||||
log_info(_(
|
||||
"NOTE: cipher algorithm %d not found in preferences\n"),
|
||||
dek->algo );
|
||||
}
|
||||
|
||||
if (!rc) {
|
||||
KBNODE k;
|
||||
|
||||
for (k=pkb; k; k = k->next) {
|
||||
if (k->pkt->pkttype == PKT_PUBLIC_KEY
|
||||
|| k->pkt->pkttype == PKT_PUBLIC_SUBKEY){
|
||||
u32 aki[2];
|
||||
keyid_from_pk(k->pkt->pkt.public_key, aki);
|
||||
|
||||
if( !rc && pk->expiredate && pk->expiredate <= make_timestamp() ) {
|
||||
log_info(_("NOTE: secret key %08lX expired at %s\n"),
|
||||
(ulong)keyid[1], asctimestamp( pk->expiredate) );
|
||||
}
|
||||
if (aki[0]==keyid[0] && aki[1]==keyid[1]) {
|
||||
pk = k->pkt->pkt.public_key;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!pk)
|
||||
BUG ();
|
||||
if ( pk->expiredate && pk->expiredate <= make_timestamp() ) {
|
||||
log_info(_("NOTE: secret key %08lX expired at %s\n"),
|
||||
(ulong)keyid[1], asctimestamp( pk->expiredate) );
|
||||
}
|
||||
}
|
||||
|
||||
/* FIXME: check wheter the key has been revoked and display
|
||||
* the revocation reason. Actually the user should know this himself,
|
||||
* but the sender might not know already and therefor the user
|
||||
* should get a notice that an revoked key has been used to decode
|
||||
* the message. The user can than watch out for snakes send by
|
||||
* one of those Eves outside his paradise :-)
|
||||
*/
|
||||
free_public_key( pk );
|
||||
if ( pk->is_revoked ) {
|
||||
log_info( _("NOTE: key has been revoked") );
|
||||
putc( '\n', log_stream() );
|
||||
show_revocation_reason( pk, 1 );
|
||||
}
|
||||
|
||||
release_kbnode (pkb);
|
||||
rc = 0;
|
||||
}
|
||||
|
||||
|
||||
leave:
|
||||
mpi_release(plain_dek);
|
||||
gcry_free(frame);
|
||||
mpi_free(plain_dek);
|
||||
m_free(frame);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
* Get the session key from the given string.
|
||||
* String is supposed to be formatted as this:
|
||||
* <algo-id>:<even-number-of-hex-digits>
|
||||
*/
|
||||
int
|
||||
get_override_session_key( DEK *dek, const char *string )
|
||||
{
|
||||
const char *s;
|
||||
int i;
|
||||
|
||||
if ( !string )
|
||||
return G10ERR_BAD_KEY;
|
||||
dek->algo = atoi(string);
|
||||
if ( dek->algo < 1 )
|
||||
return G10ERR_BAD_KEY;
|
||||
if ( !(s = strchr ( string, ':' )) )
|
||||
return G10ERR_BAD_KEY;
|
||||
s++;
|
||||
for(i=0; i < DIM(dek->key) && *s; i++, s +=2 ) {
|
||||
int c = hextobyte ( s );
|
||||
if (c == -1)
|
||||
return G10ERR_BAD_KEY;
|
||||
dek->key[i] = c;
|
||||
}
|
||||
if ( *s )
|
||||
return G10ERR_BAD_KEY;
|
||||
dek->keylen = i;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
374
g10/revoke.c
374
g10/revoke.c
@ -1,5 +1,5 @@
|
||||
/* revoke.c
|
||||
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
|
||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
@ -30,7 +30,7 @@
|
||||
#include "packet.h"
|
||||
#include "errors.h"
|
||||
#include "keydb.h"
|
||||
#include <gcrypt.h>
|
||||
#include "memory.h"
|
||||
#include "util.h"
|
||||
#include "main.h"
|
||||
#include "ttyio.h"
|
||||
@ -52,24 +52,273 @@ revocation_reason_build_cb( PKT_signature *sig, void *opaque )
|
||||
byte *buffer;
|
||||
size_t buflen = 1;
|
||||
|
||||
if(!reason)
|
||||
return 0;
|
||||
|
||||
if( reason->desc ) {
|
||||
ud = native_to_utf8( reason->desc );
|
||||
buflen += strlen(ud);
|
||||
}
|
||||
buffer = gcry_xmalloc( buflen );
|
||||
buffer = m_alloc( buflen );
|
||||
*buffer = reason->code;
|
||||
if( ud ) {
|
||||
memcpy(buffer+1, ud, strlen(ud) );
|
||||
gcry_free( ud );
|
||||
m_free( ud );
|
||||
}
|
||||
|
||||
build_sig_subpkt( sig, SIGSUBPKT_REVOC_REASON, buffer, buflen );
|
||||
gcry_free( buffer );
|
||||
m_free( buffer );
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/****************
|
||||
* Generate a revocation certificate for UNAME via a designated revoker
|
||||
*/
|
||||
int
|
||||
gen_desig_revoke( const char *uname )
|
||||
{
|
||||
int rc = 0;
|
||||
armor_filter_context_t afx;
|
||||
PACKET pkt;
|
||||
PKT_public_key *pk = NULL;
|
||||
PKT_secret_key *sk = NULL;
|
||||
PKT_signature *sig = NULL;
|
||||
IOBUF out = NULL;
|
||||
struct revocation_reason_info *reason = NULL;
|
||||
KEYDB_HANDLE kdbhd;
|
||||
KEYDB_SEARCH_DESC desc;
|
||||
KBNODE keyblock=NULL,node;
|
||||
u32 keyid[2];
|
||||
int i,any=0;
|
||||
|
||||
if( opt.batch ) {
|
||||
log_error(_("sorry, can't do this in batch mode\n"));
|
||||
return G10ERR_GENERAL;
|
||||
}
|
||||
|
||||
memset( &afx, 0, sizeof afx);
|
||||
|
||||
kdbhd = keydb_new (0);
|
||||
classify_user_id (uname, &desc);
|
||||
rc = desc.mode? keydb_search (kdbhd, &desc, 1) : G10ERR_INV_USER_ID;
|
||||
if (rc) {
|
||||
log_error (_("key `%s' not found: %s\n"),uname, g10_errstr (rc));
|
||||
goto leave;
|
||||
}
|
||||
|
||||
rc = keydb_get_keyblock (kdbhd, &keyblock );
|
||||
if( rc ) {
|
||||
log_error (_("error reading keyblock: %s\n"), g10_errstr(rc) );
|
||||
goto leave;
|
||||
}
|
||||
|
||||
/* To parse the revkeys */
|
||||
merge_keys_and_selfsig(keyblock);
|
||||
|
||||
/* get the key from the keyblock */
|
||||
node = find_kbnode( keyblock, PKT_PUBLIC_KEY );
|
||||
if( !node )
|
||||
BUG ();
|
||||
|
||||
pk=node->pkt->pkt.public_key;
|
||||
|
||||
keyid_from_pk(pk,keyid);
|
||||
|
||||
/* Are we a designated revoker for this key? */
|
||||
|
||||
if(!pk->revkey && pk->numrevkeys)
|
||||
BUG();
|
||||
|
||||
for(i=0;i<pk->numrevkeys;i++)
|
||||
{
|
||||
if(sk)
|
||||
free_secret_key(sk);
|
||||
|
||||
sk=m_alloc_clear(sizeof(*sk));
|
||||
|
||||
rc=get_seckey_byfprint(sk,pk->revkey[i].fpr,MAX_FINGERPRINT_LEN);
|
||||
|
||||
/* We have the revocation key */
|
||||
if(!rc)
|
||||
{
|
||||
size_t n;
|
||||
char *p;
|
||||
u32 sk_keyid[2];
|
||||
PKT_user_id *uid=NULL;
|
||||
PKT_signature *selfsig=NULL;
|
||||
|
||||
any=1;
|
||||
keyid_from_sk(sk,sk_keyid);
|
||||
|
||||
tty_printf("\npub %4u%c/%08lX %s ",
|
||||
nbits_from_pk( pk ),
|
||||
pubkey_letter( pk->pubkey_algo ),
|
||||
(ulong)keyid[1], datestr_from_pk(pk) );
|
||||
|
||||
p = get_user_id( keyid, &n );
|
||||
tty_print_utf8_string( p, n );
|
||||
m_free(p);
|
||||
tty_printf("\n\n");
|
||||
|
||||
tty_printf(_("To be revoked by:\n"));
|
||||
|
||||
tty_printf("\nsec %4u%c/%08lX %s ",
|
||||
nbits_from_sk( sk ),
|
||||
pubkey_letter( sk->pubkey_algo ),
|
||||
(ulong)sk_keyid[1], datestr_from_sk(sk) );
|
||||
|
||||
p = get_user_id( sk_keyid, &n );
|
||||
tty_print_utf8_string( p, n );
|
||||
m_free(p);
|
||||
tty_printf("\n\n");
|
||||
|
||||
if( !cpr_get_answer_is_yes("gen_desig_revoke.okay",
|
||||
_("Create a revocation certificate for this key? ")) )
|
||||
continue;
|
||||
|
||||
/* get the reason for the revocation (this is always v4) */
|
||||
reason = ask_revocation_reason( 1, 0, 1 );
|
||||
if( !reason )
|
||||
continue;
|
||||
|
||||
rc = check_secret_key( sk, 0 );
|
||||
if( rc )
|
||||
continue;
|
||||
|
||||
if( !opt.armor )
|
||||
tty_printf(_("ASCII armored output forced.\n"));
|
||||
|
||||
if( (rc = open_outfile( NULL, 0, &out )) )
|
||||
goto leave;
|
||||
|
||||
afx.what = 1;
|
||||
afx.hdrlines = "Comment: A revocation certificate should follow\n";
|
||||
iobuf_push_filter( out, armor_filter, &afx );
|
||||
|
||||
/* create it */
|
||||
rc = make_keysig_packet( &sig, pk, NULL, NULL, sk, 0x20, 0,
|
||||
0, 0, 0,
|
||||
revocation_reason_build_cb, reason );
|
||||
if( rc ) {
|
||||
log_error(_("make_keysig_packet failed: %s\n"), g10_errstr(rc));
|
||||
goto leave;
|
||||
}
|
||||
|
||||
/* Spit out a minimal pk as well, since otherwise there is
|
||||
no way to know which key to attach this revocation
|
||||
to. */
|
||||
|
||||
node=find_kbnode(keyblock,PKT_PUBLIC_KEY);
|
||||
if(!node)
|
||||
{
|
||||
rc=G10ERR_GENERAL;
|
||||
log_error(_("key %08lX incomplete\n"),(ulong)keyid[1]);
|
||||
goto leave;
|
||||
}
|
||||
|
||||
pkt = *node->pkt;
|
||||
rc=build_packet(out,&pkt);
|
||||
if( rc ) {
|
||||
log_error(_("build_packet failed: %s\n"), g10_errstr(rc) );
|
||||
goto leave;
|
||||
}
|
||||
|
||||
init_packet( &pkt );
|
||||
pkt.pkttype = PKT_SIGNATURE;
|
||||
pkt.pkt.signature = sig;
|
||||
|
||||
rc = build_packet( out, &pkt );
|
||||
if( rc ) {
|
||||
log_error(_("build_packet failed: %s\n"), g10_errstr(rc) );
|
||||
goto leave;
|
||||
}
|
||||
|
||||
while(!selfsig)
|
||||
{
|
||||
KBNODE signode;
|
||||
|
||||
node=find_next_kbnode(node,PKT_USER_ID);
|
||||
if(!node)
|
||||
{
|
||||
/* We're out of user IDs - none were
|
||||
self-signed. */
|
||||
if(uid)
|
||||
break;
|
||||
else
|
||||
{
|
||||
rc=G10ERR_GENERAL;
|
||||
log_error(_("key %08lX incomplete\n"),(ulong)keyid[1]);
|
||||
goto leave;
|
||||
}
|
||||
}
|
||||
|
||||
if(node->pkt->pkt.user_id->attrib_data)
|
||||
continue;
|
||||
|
||||
uid=node->pkt->pkt.user_id;
|
||||
signode=node;
|
||||
|
||||
while((signode=find_next_kbnode(signode,PKT_SIGNATURE)))
|
||||
{
|
||||
if(keyid[0]==signode->pkt->pkt.signature->keyid[0] &&
|
||||
keyid[1]==signode->pkt->pkt.signature->keyid[1] &&
|
||||
IS_UID_SIG(signode->pkt->pkt.signature))
|
||||
{
|
||||
selfsig=signode->pkt->pkt.signature;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pkt.pkttype = PKT_USER_ID;
|
||||
pkt.pkt.user_id = uid;
|
||||
|
||||
rc = build_packet( out, &pkt );
|
||||
if( rc ) {
|
||||
log_error(_("build_packet failed: %s\n"), g10_errstr(rc) );
|
||||
goto leave;
|
||||
}
|
||||
|
||||
if(selfsig)
|
||||
{
|
||||
pkt.pkttype = PKT_SIGNATURE;
|
||||
pkt.pkt.signature = selfsig;
|
||||
|
||||
rc = build_packet( out, &pkt );
|
||||
if( rc ) {
|
||||
log_error(_("build_packet failed: %s\n"), g10_errstr(rc) );
|
||||
goto leave;
|
||||
}
|
||||
}
|
||||
|
||||
/* and issue a usage notice */
|
||||
tty_printf(_("Revocation certificate created.\n"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!any)
|
||||
log_error(_("no revocation keys found for `%s'\n"),uname);
|
||||
|
||||
leave:
|
||||
if( pk )
|
||||
free_public_key( pk );
|
||||
if( sk )
|
||||
free_secret_key( sk );
|
||||
if( sig )
|
||||
free_seckey_enc( sig );
|
||||
|
||||
if( rc )
|
||||
iobuf_cancel(out);
|
||||
else
|
||||
iobuf_close(out);
|
||||
release_revocation_reason_info( reason );
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
* Generate a revocation certificate for UNAME
|
||||
*/
|
||||
@ -78,7 +327,6 @@ gen_revoke( const char *uname )
|
||||
{
|
||||
int rc = 0;
|
||||
armor_filter_context_t afx;
|
||||
compress_filter_context_t zfx;
|
||||
PACKET pkt;
|
||||
PKT_secret_key *sk; /* used as pointer into a kbnode */
|
||||
PKT_public_key *pk = NULL;
|
||||
@ -87,34 +335,40 @@ gen_revoke( const char *uname )
|
||||
IOBUF out = NULL;
|
||||
KBNODE keyblock = NULL;
|
||||
KBNODE node;
|
||||
KEYDB_HANDLE kdbhd;
|
||||
struct revocation_reason_info *reason = NULL;
|
||||
KEYDB_SEARCH_DESC desc;
|
||||
|
||||
if( opt.batch ) {
|
||||
log_error(_("sorry, can't do this in batch mode\n"));
|
||||
return GPGERR_GENERAL;
|
||||
return G10ERR_GENERAL;
|
||||
}
|
||||
|
||||
|
||||
memset( &afx, 0, sizeof afx);
|
||||
memset( &zfx, 0, sizeof zfx);
|
||||
init_packet( &pkt );
|
||||
|
||||
/* search the userid:
|
||||
* We don't want the whole getkey stuff here but the entire keyblock
|
||||
*/
|
||||
kdbhd = keydb_new (1);
|
||||
classify_user_id (uname, &desc);
|
||||
rc = desc.mode? keydb_search (kdbhd, &desc, 1) : G10ERR_INV_USER_ID;
|
||||
if (rc) {
|
||||
log_error (_("secret key `%s' not found: %s\n"),
|
||||
uname, g10_errstr (rc));
|
||||
goto leave;
|
||||
}
|
||||
|
||||
/* search the userid */
|
||||
rc = find_secret_keyblock_byname( &keyblock, uname );
|
||||
rc = keydb_get_keyblock (kdbhd, &keyblock );
|
||||
if( rc ) {
|
||||
log_error(_("secret key for user `%s' not found: %s\n"),
|
||||
uname, gpg_errstr(rc) );
|
||||
log_error (_("error reading keyblock: %s\n"), g10_errstr(rc) );
|
||||
goto leave;
|
||||
}
|
||||
|
||||
/* get the keyid from the keyblock */
|
||||
node = find_kbnode( keyblock, PKT_SECRET_KEY );
|
||||
if( !node ) { /* maybe better to use log_bug ? */
|
||||
log_error(_("Oops; secret key not found anymore!\n"));
|
||||
rc = GPGERR_GENERAL;
|
||||
goto leave;
|
||||
}
|
||||
if( !node )
|
||||
BUG ();
|
||||
|
||||
/* fixme: should make a function out of this stuff,
|
||||
* it's used all over the source */
|
||||
@ -123,23 +377,25 @@ gen_revoke( const char *uname )
|
||||
tty_printf("\nsec %4u%c/%08lX %s ",
|
||||
nbits_from_sk( sk ),
|
||||
pubkey_letter( sk->pubkey_algo ),
|
||||
sk_keyid[1], datestr_from_sk(sk) );
|
||||
(ulong)sk_keyid[1], datestr_from_sk(sk) );
|
||||
{
|
||||
size_t n;
|
||||
char *p = get_user_id( sk_keyid, &n );
|
||||
tty_print_utf8_string( p, n );
|
||||
gcry_free(p);
|
||||
m_free(p);
|
||||
tty_printf("\n");
|
||||
}
|
||||
pk = gcry_xcalloc( 1, sizeof *pk );
|
||||
pk = m_alloc_clear( sizeof *pk );
|
||||
|
||||
/* FIXME: We should get the public key direct from the secret one */
|
||||
rc = get_pubkey( pk, sk_keyid );
|
||||
if( rc ) {
|
||||
log_error(_("no corresponding public key: %s\n"), gpg_errstr(rc) );
|
||||
log_error(_("no corresponding public key: %s\n"), g10_errstr(rc) );
|
||||
goto leave;
|
||||
}
|
||||
if( cmp_public_secret_key( pk, sk ) ) {
|
||||
log_error(_("public key does not match secret key!\n") );
|
||||
rc = GPGERR_GENERAL;
|
||||
rc = G10ERR_GENERAL;
|
||||
goto leave;
|
||||
}
|
||||
|
||||
@ -150,17 +406,19 @@ gen_revoke( const char *uname )
|
||||
goto leave;
|
||||
}
|
||||
|
||||
/* get the reason for the revocation */
|
||||
reason = ask_revocation_reason( 1, 0, 1 );
|
||||
if( !reason ) { /* user decided to cancel */
|
||||
if(sk->version>=4 || opt.force_v4_certs) {
|
||||
/* get the reason for the revocation */
|
||||
reason = ask_revocation_reason( 1, 0, 1 );
|
||||
if( !reason ) { /* user decided to cancel */
|
||||
rc = 0;
|
||||
goto leave;
|
||||
}
|
||||
}
|
||||
|
||||
switch( is_secret_key_protected( sk ) ) {
|
||||
case -1:
|
||||
log_error(_("unknown protection algorithm\n"));
|
||||
rc = GPGERR_PUBKEY_ALGO;
|
||||
rc = G10ERR_PUBKEY_ALGO;
|
||||
break;
|
||||
case 0:
|
||||
tty_printf(_("NOTE: This key is not protected!\n"));
|
||||
@ -185,10 +443,10 @@ gen_revoke( const char *uname )
|
||||
|
||||
/* create it */
|
||||
rc = make_keysig_packet( &sig, pk, NULL, NULL, sk, 0x20, 0,
|
||||
revocation_reason_build_cb,
|
||||
reason );
|
||||
opt.force_v4_certs?4:0, 0, 0,
|
||||
revocation_reason_build_cb, reason );
|
||||
if( rc ) {
|
||||
log_error(_("make_keysig_packet failed: %s\n"), gpg_errstr(rc));
|
||||
log_error(_("make_keysig_packet failed: %s\n"), g10_errstr(rc));
|
||||
goto leave;
|
||||
}
|
||||
init_packet( &pkt );
|
||||
@ -197,7 +455,7 @@ gen_revoke( const char *uname )
|
||||
|
||||
rc = build_packet( out, &pkt );
|
||||
if( rc ) {
|
||||
log_error(_("build_packet failed: %s\n"), gpg_errstr(rc) );
|
||||
log_error(_("build_packet failed: %s\n"), g10_errstr(rc) );
|
||||
goto leave;
|
||||
}
|
||||
|
||||
@ -217,6 +475,7 @@ gen_revoke( const char *uname )
|
||||
if( sig )
|
||||
free_seckey_enc( sig );
|
||||
release_kbnode( keyblock );
|
||||
keydb_release (kdbhd);
|
||||
if( rc )
|
||||
iobuf_cancel(out);
|
||||
else
|
||||
@ -230,20 +489,22 @@ gen_revoke( const char *uname )
|
||||
struct revocation_reason_info *
|
||||
ask_revocation_reason( int key_rev, int cert_rev, int hint )
|
||||
{
|
||||
int code;
|
||||
int code=-1;
|
||||
char *description = NULL;
|
||||
struct revocation_reason_info *reason;
|
||||
const char *text_0 = _("No reason specified");
|
||||
const char *text_1 = _("Key has been compromised");
|
||||
const char *text_2 = _("Key is superseded");
|
||||
const char *text_3 = _("Key is no longer used");
|
||||
const char *text_4 = _("User ID is non longer valid");
|
||||
const char *text_4 = _("User ID is no longer valid");
|
||||
const char *code_text = NULL;
|
||||
|
||||
do {
|
||||
gcry_free(description);
|
||||
m_free(description);
|
||||
description = NULL;
|
||||
|
||||
tty_printf(_("Please select the reason for the revocation:\n"));
|
||||
tty_printf( " 0 = %s\n", text_0 );
|
||||
if( key_rev )
|
||||
tty_printf(" 1 = %s\n", text_1 );
|
||||
if( key_rev )
|
||||
@ -252,29 +513,31 @@ ask_revocation_reason( int key_rev, int cert_rev, int hint )
|
||||
tty_printf(" 3 = %s\n", text_3 );
|
||||
if( cert_rev )
|
||||
tty_printf(" 4 = %s\n", text_4 );
|
||||
tty_printf( " 0 = %s\n", _("Cancel") );
|
||||
tty_printf( " Q = %s\n", _("Cancel") );
|
||||
if( hint )
|
||||
tty_printf(_("(Probably you want to select %d here)\n"), hint );
|
||||
|
||||
for(code = 0; !code;) {
|
||||
while(code==-1) {
|
||||
int n;
|
||||
char *answer = cpr_get("ask_revocation_reason.code",
|
||||
_("Your decision? "));
|
||||
trim_spaces( answer );
|
||||
cpr_kill_prompt();
|
||||
if( *answer == 'q' || *answer == 'Q' )
|
||||
n = 0;
|
||||
else if( !isdigit( *answer ) )
|
||||
n = -1;
|
||||
else if( hint && !*answer )
|
||||
if( *answer == 'q' || *answer == 'Q')
|
||||
return NULL; /* cancel */
|
||||
if( hint && !*answer )
|
||||
n = hint;
|
||||
else if(!isdigit( *answer ) )
|
||||
n = -1;
|
||||
else
|
||||
n = atoi(answer);
|
||||
gcry_free(answer);
|
||||
if( !n )
|
||||
return NULL; /* cancel */
|
||||
m_free(answer);
|
||||
if( n == 0 ) {
|
||||
code = 0x00; /* no particular reason */
|
||||
code_text = text_0;
|
||||
}
|
||||
else if( key_rev && n == 1 ) {
|
||||
code = 0x02; /* key has been compromised */
|
||||
code = 0x02; /* key has been compromised */
|
||||
code_text = text_1;
|
||||
}
|
||||
else if( key_rev && n == 2 ) {
|
||||
@ -286,7 +549,7 @@ ask_revocation_reason( int key_rev, int cert_rev, int hint )
|
||||
code_text = text_3;
|
||||
}
|
||||
else if( cert_rev && n == 4 ) {
|
||||
code = 0x20; /* uid is non longer valid */
|
||||
code = 0x20; /* uid is no longer valid */
|
||||
code_text = text_4;
|
||||
}
|
||||
else
|
||||
@ -300,25 +563,25 @@ ask_revocation_reason( int key_rev, int cert_rev, int hint )
|
||||
trim_trailing_ws( answer, strlen(answer) );
|
||||
cpr_kill_prompt();
|
||||
if( !*answer ) {
|
||||
gcry_free(answer);
|
||||
m_free(answer);
|
||||
break;
|
||||
}
|
||||
|
||||
{
|
||||
char *p = make_printable_string( answer, strlen(answer), 0 );
|
||||
gcry_free(answer);
|
||||
m_free(answer);
|
||||
answer = p;
|
||||
}
|
||||
|
||||
if( !description )
|
||||
description = gcry_xstrdup(answer);
|
||||
description = m_strdup(answer);
|
||||
else {
|
||||
char *p = gcry_xmalloc( strlen(description) + strlen(answer) + 2 );
|
||||
char *p = m_alloc( strlen(description) + strlen(answer) + 2 );
|
||||
strcpy(stpcpy(stpcpy( p, description),"\n"),answer);
|
||||
gcry_free(description);
|
||||
m_free(description);
|
||||
description = p;
|
||||
}
|
||||
gcry_free(answer);
|
||||
m_free(answer);
|
||||
}
|
||||
|
||||
tty_printf(_("Reason for revocation: %s\n"), code_text );
|
||||
@ -330,7 +593,7 @@ ask_revocation_reason( int key_rev, int cert_rev, int hint )
|
||||
} while( !cpr_get_answer_is_yes("ask_revocation_reason.okay",
|
||||
_("Is this okay? ")) );
|
||||
|
||||
reason = gcry_xmalloc( sizeof *reason );
|
||||
reason = m_alloc( sizeof *reason );
|
||||
reason->code = code;
|
||||
reason->desc = description;
|
||||
return reason;
|
||||
@ -340,8 +603,7 @@ void
|
||||
release_revocation_reason_info( struct revocation_reason_info *reason )
|
||||
{
|
||||
if( reason ) {
|
||||
gcry_free( reason->desc );
|
||||
gcry_free( reason );
|
||||
m_free( reason->desc );
|
||||
m_free( reason );
|
||||
}
|
||||
}
|
||||
|
||||
|
1360
g10/ringedit.c
1360
g10/ringedit.c
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,5 @@
|
||||
/* seckey-cert.c - secret key certificate packet handling
|
||||
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
|
||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
@ -23,58 +23,22 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <gcrypt.h>
|
||||
#include "util.h"
|
||||
#include "memory.h"
|
||||
#include "packet.h"
|
||||
#include "mpi.h"
|
||||
#include "keydb.h"
|
||||
#include "cipher.h"
|
||||
#include "main.h"
|
||||
#include "options.h"
|
||||
#include "i18n.h"
|
||||
#include "status.h"
|
||||
|
||||
|
||||
/****************
|
||||
* Emulate our old PK interface here - sometime in the future we might
|
||||
* change the internal design to directly fit to libgcrypt.
|
||||
*/
|
||||
static int
|
||||
pk_check_secret_key( int algo, MPI *skey )
|
||||
{
|
||||
GCRY_SEXP s_skey;
|
||||
int rc;
|
||||
|
||||
/* make a sexp from skey */
|
||||
if( algo == GCRY_PK_DSA ) {
|
||||
rc = gcry_sexp_build ( &s_skey, NULL,
|
||||
"(private-key(dsa(p%m)(q%m)(g%m)(y%m)(x%m)))",
|
||||
skey[0], skey[1], skey[2], skey[3], skey[4] );
|
||||
}
|
||||
else if( algo == GCRY_PK_ELG || algo == GCRY_PK_ELG_E ) {
|
||||
rc = gcry_sexp_build ( &s_skey, NULL,
|
||||
"(private-key(elg(p%m)(g%m)(y%m)(x%m)))",
|
||||
skey[0], skey[1], skey[2], skey[3] );
|
||||
}
|
||||
else if( algo == GCRY_PK_RSA ) {
|
||||
rc = gcry_sexp_build ( &s_skey, NULL,
|
||||
"(private-key(rsa(n%m)(e%m)(d%m)(p%m)(q%m)(u%m)))",
|
||||
skey[0], skey[1], skey[2], skey[3], skey[4], skey[5] );
|
||||
}
|
||||
else
|
||||
return GPGERR_PUBKEY_ALGO;
|
||||
|
||||
if ( rc )
|
||||
BUG ();
|
||||
|
||||
rc = gcry_pk_testkey( s_skey );
|
||||
gcry_sexp_release( s_skey );
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
do_check( PKT_secret_key *sk )
|
||||
do_check( PKT_secret_key *sk, const char *tryagain_text )
|
||||
{
|
||||
byte *buffer;
|
||||
u16 csum=0;
|
||||
int i, res;
|
||||
unsigned nbytes;
|
||||
@ -82,19 +46,20 @@ do_check( PKT_secret_key *sk )
|
||||
if( sk->is_protected ) { /* remove the protection */
|
||||
DEK *dek = NULL;
|
||||
u32 keyid[4]; /* 4! because we need two of them */
|
||||
GCRY_CIPHER_HD cipher_hd=NULL;
|
||||
CIPHER_HANDLE cipher_hd=NULL;
|
||||
PKT_secret_key *save_sk;
|
||||
|
||||
if( sk->protect.s2k.mode == 1001 ) {
|
||||
log_info(_("secret key parts are not available\n"));
|
||||
return GPGERR_GENERAL;
|
||||
return G10ERR_GENERAL;
|
||||
}
|
||||
if( sk->protect.algo == GCRY_CIPHER_NONE )
|
||||
if( sk->protect.algo == CIPHER_ALGO_NONE )
|
||||
BUG();
|
||||
if( openpgp_cipher_test_algo( sk->protect.algo ) ) {
|
||||
log_info(_("protection algorithm %d is not supported\n"),
|
||||
sk->protect.algo );
|
||||
return GPGERR_CIPHER_ALGO;
|
||||
if( check_cipher_algo( sk->protect.algo ) ) {
|
||||
log_info(_("protection algorithm %d%s is not supported\n"),
|
||||
sk->protect.algo,sk->protect.algo==1?" (IDEA)":"" );
|
||||
idea_cipher_warn(0);
|
||||
return G10ERR_CIPHER_ALGO;
|
||||
}
|
||||
keyid_from_sk( sk, keyid );
|
||||
keyid[2] = keyid[3] = 0;
|
||||
@ -103,110 +68,115 @@ do_check( PKT_secret_key *sk )
|
||||
keyid[3] = sk->main_keyid[1];
|
||||
}
|
||||
dek = passphrase_to_dek( keyid, sk->pubkey_algo, sk->protect.algo,
|
||||
&sk->protect.s2k, 0 );
|
||||
/* Hmmm: Do we use sync mode here even for Twofish? */
|
||||
if( !(cipher_hd = gcry_cipher_open( sk->protect.algo,
|
||||
GCRY_CIPHER_MODE_CFB,
|
||||
GCRY_CIPHER_SECURE
|
||||
| (sk->protect.algo >= 100 ?
|
||||
0 : GCRY_CIPHER_ENABLE_SYNC) ) )
|
||||
) {
|
||||
BUG();
|
||||
}
|
||||
|
||||
if( gcry_cipher_setkey( cipher_hd, dek->key, dek->keylen ) )
|
||||
log_fatal("set key failed: %s\n", gcry_strerror(-1) );
|
||||
gcry_free(dek);
|
||||
&sk->protect.s2k, 0, tryagain_text );
|
||||
cipher_hd = cipher_open( sk->protect.algo,
|
||||
CIPHER_MODE_AUTO_CFB, 1);
|
||||
cipher_setkey( cipher_hd, dek->key, dek->keylen );
|
||||
m_free(dek);
|
||||
save_sk = copy_secret_key( NULL, sk );
|
||||
if( gcry_cipher_setiv( cipher_hd, sk->protect.iv, sk->protect.ivlen ))
|
||||
log_fatal("set IV failed: %s\n", gcry_strerror(-1) );
|
||||
cipher_setiv( cipher_hd, sk->protect.iv, sk->protect.ivlen );
|
||||
csum = 0;
|
||||
if( sk->version >= 4 ) {
|
||||
size_t ndata;
|
||||
unsigned int ndatabits;
|
||||
int ndata;
|
||||
byte *p, *data;
|
||||
u16 csumc = 0;
|
||||
|
||||
i = pubkey_get_npkey(sk->pubkey_algo);
|
||||
assert( gcry_mpi_get_flag( sk->skey[i], GCRYMPI_FLAG_OPAQUE ) );
|
||||
p = gcry_mpi_get_opaque( sk->skey[i], &ndatabits );
|
||||
ndata = (ndatabits+7)/8;
|
||||
assert( mpi_is_opaque( sk->skey[i] ) );
|
||||
p = mpi_get_opaque( sk->skey[i], &ndata );
|
||||
if ( ndata > 1 )
|
||||
csumc = p[ndata-2] << 8 | p[ndata-1];
|
||||
data = gcry_xmalloc_secure( ndata );
|
||||
gcry_cipher_decrypt( cipher_hd, data, ndata, p, ndata );
|
||||
mpi_release( sk->skey[i] ); sk->skey[i] = NULL ;
|
||||
data = m_alloc_secure( ndata );
|
||||
cipher_decrypt( cipher_hd, data, p, ndata );
|
||||
mpi_free( sk->skey[i] ); sk->skey[i] = NULL ;
|
||||
p = data;
|
||||
if( ndata < 2 ) {
|
||||
log_error("not enough bytes for checksum\n");
|
||||
sk->csum = 0;
|
||||
csum = 1;
|
||||
}
|
||||
else {
|
||||
csum = checksum( data, ndata-2);
|
||||
sk->csum = data[ndata-2] << 8 | data[ndata-1];
|
||||
if ( sk->csum != csum ) {
|
||||
/* This is a PGP 7.0.0 workaround */
|
||||
sk->csum = csumc; /* take the encrypted one */
|
||||
if (sk->protect.sha1chk) {
|
||||
/* This is the new SHA1 checksum method to detect
|
||||
tampering with the key as used by the Klima/Rosa
|
||||
attack */
|
||||
sk->csum = 0;
|
||||
csum = 1;
|
||||
if( ndata < 20 )
|
||||
log_error("not enough bytes for SHA-1 checksum\n");
|
||||
else {
|
||||
MD_HANDLE h = md_open (DIGEST_ALGO_SHA1, 1);
|
||||
if (!h)
|
||||
BUG(); /* algo not available */
|
||||
md_write (h, data, ndata - 20);
|
||||
md_final (h);
|
||||
if (!memcmp (md_read (h, DIGEST_ALGO_SHA1),
|
||||
data + ndata - 20, 20) ) {
|
||||
/* digest does match. We have to keep the old
|
||||
style checksum in sk->csum, so that the
|
||||
test used for unprotected keys does work.
|
||||
This test gets used when we are adding new
|
||||
keys. */
|
||||
sk->csum = csum = checksum (data, ndata-20);
|
||||
}
|
||||
md_close (h);
|
||||
}
|
||||
}
|
||||
/* must check it here otherwise the mpi_read_xx would fail
|
||||
* because the length may have an arbitrary value */
|
||||
if( sk->csum == csum ) {
|
||||
for( ; i < pubkey_get_nskey(sk->pubkey_algo); i++ ) {
|
||||
nbytes = ndata;
|
||||
assert( gcry_is_secure( p ) );
|
||||
res = gcry_mpi_scan( &sk->skey[i], GCRYMPI_FMT_PGP,
|
||||
p, &nbytes);
|
||||
if( res )
|
||||
log_bug("gcry_mpi_scan failed in do_check: rc=%d\n", res);
|
||||
|
||||
ndata -= nbytes;
|
||||
p += nbytes;
|
||||
}
|
||||
}
|
||||
gcry_free(data);
|
||||
}
|
||||
else {
|
||||
if( ndata < 2 ) {
|
||||
log_error("not enough bytes for checksum\n");
|
||||
sk->csum = 0;
|
||||
csum = 1;
|
||||
}
|
||||
else {
|
||||
csum = checksum( data, ndata-2);
|
||||
sk->csum = data[ndata-2] << 8 | data[ndata-1];
|
||||
if ( sk->csum != csum ) {
|
||||
/* This is a PGP 7.0.0 workaround */
|
||||
sk->csum = csumc; /* take the encrypted one */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* must check it here otherwise the mpi_read_xx would fail
|
||||
because the length may have an arbitrary value */
|
||||
if( sk->csum == csum ) {
|
||||
for( ; i < pubkey_get_nskey(sk->pubkey_algo); i++ ) {
|
||||
nbytes = ndata;
|
||||
sk->skey[i] = mpi_read_from_buffer(p, &nbytes, 1 );
|
||||
ndata -= nbytes;
|
||||
p += nbytes;
|
||||
}
|
||||
/* Note: at this point ndata should be 2 for a simple
|
||||
checksum or 20 for the sha1 digest */
|
||||
}
|
||||
m_free(data);
|
||||
}
|
||||
else {
|
||||
for(i=pubkey_get_npkey(sk->pubkey_algo);
|
||||
i < pubkey_get_nskey(sk->pubkey_algo); i++ ) {
|
||||
size_t ndata;
|
||||
unsigned int ndatabits;
|
||||
byte *p, *data;
|
||||
|
||||
assert( gcry_mpi_get_flag( sk->skey[i], GCRYMPI_FLAG_OPAQUE ) );
|
||||
p = gcry_mpi_get_opaque( sk->skey[i], &ndatabits );
|
||||
ndata = (ndatabits+7)/8;
|
||||
data = gcry_xmalloc_secure( ndata );
|
||||
gcry_cipher_sync( cipher_hd );
|
||||
gcry_cipher_decrypt( cipher_hd, data, ndata, p, ndata );
|
||||
mpi_release( sk->skey[i] ); sk->skey[i] = NULL ;
|
||||
|
||||
res = gcry_mpi_scan( &sk->skey[i], GCRYMPI_FMT_USG,
|
||||
data, &ndata );
|
||||
if( res )
|
||||
log_bug("gcry_mpi_scan failed in do_check: rc=%d\n", res);
|
||||
|
||||
buffer = mpi_get_secure_buffer( sk->skey[i], &nbytes, NULL );
|
||||
cipher_sync( cipher_hd );
|
||||
assert( mpi_is_protected(sk->skey[i]) );
|
||||
cipher_decrypt( cipher_hd, buffer, buffer, nbytes );
|
||||
mpi_set_buffer( sk->skey[i], buffer, nbytes, 0 );
|
||||
mpi_clear_protect_flag( sk->skey[i] );
|
||||
csum += checksum_mpi( sk->skey[i] );
|
||||
gcry_free( data );
|
||||
m_free( buffer );
|
||||
}
|
||||
if( opt.emulate_bugs & EMUBUG_GPGCHKSUM ) {
|
||||
csum = sk->csum;
|
||||
}
|
||||
}
|
||||
gcry_cipher_close( cipher_hd );
|
||||
cipher_close( cipher_hd );
|
||||
/* now let's see whether we have used the right passphrase */
|
||||
if( csum != sk->csum ) {
|
||||
copy_secret_key( sk, save_sk );
|
||||
passphrase_clear_cache ( keyid, sk->pubkey_algo );
|
||||
free_secret_key( save_sk );
|
||||
return GPGERR_BAD_PASS;
|
||||
return G10ERR_BAD_PASS;
|
||||
}
|
||||
/* the checksum may be correct in some cases,
|
||||
* so we also check the key itself */
|
||||
res = pk_check_secret_key( sk->pubkey_algo, sk->skey );
|
||||
/* the checksum may fail, so we also check the key itself */
|
||||
res = pubkey_check_secret_key( sk->pubkey_algo, sk->skey );
|
||||
if( res ) {
|
||||
copy_secret_key( sk, save_sk );
|
||||
passphrase_clear_cache ( keyid, sk->pubkey_algo );
|
||||
free_secret_key( save_sk );
|
||||
return GPGERR_BAD_PASS;
|
||||
return G10ERR_BAD_PASS;
|
||||
}
|
||||
free_secret_key( save_sk );
|
||||
sk->is_protected = 0;
|
||||
@ -215,11 +185,10 @@ do_check( PKT_secret_key *sk )
|
||||
csum = 0;
|
||||
for(i=pubkey_get_npkey(sk->pubkey_algo);
|
||||
i < pubkey_get_nskey(sk->pubkey_algo); i++ ) {
|
||||
assert( !gcry_mpi_get_flag( sk->skey[i], GCRYMPI_FLAG_OPAQUE ) );
|
||||
csum += checksum_mpi( sk->skey[i] );
|
||||
}
|
||||
if( csum != sk->csum )
|
||||
return GPGERR_CHECKSUM;
|
||||
return G10ERR_CHECKSUM;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -234,17 +203,20 @@ do_check( PKT_secret_key *sk )
|
||||
int
|
||||
check_secret_key( PKT_secret_key *sk, int n )
|
||||
{
|
||||
int rc = GPGERR_BAD_PASS;
|
||||
int rc = G10ERR_BAD_PASS;
|
||||
int i;
|
||||
|
||||
if( n < 1 )
|
||||
n = opt.batch? 1 : 3; /* use the default value */
|
||||
n = (opt.batch && !opt.use_agent)? 1 : 3; /* use the default value */
|
||||
|
||||
for(i=0; i < n && rc == GPGERR_BAD_PASS; i++ ) {
|
||||
if( i )
|
||||
log_info(_("Invalid passphrase; please try again ...\n"));
|
||||
rc = do_check( sk );
|
||||
if( rc == GPGERR_BAD_PASS && is_status_enabled() ) {
|
||||
for(i=0; i < n && rc == G10ERR_BAD_PASS; i++ ) {
|
||||
const char *tryagain = NULL;
|
||||
if (i) {
|
||||
tryagain = _("Invalid passphrase; please try again");
|
||||
log_info (_("%s ...\n"), tryagain);
|
||||
}
|
||||
rc = do_check( sk, tryagain );
|
||||
if( rc == G10ERR_BAD_PASS && is_status_enabled() ) {
|
||||
u32 kid[2];
|
||||
char buf[50];
|
||||
|
||||
@ -289,114 +261,103 @@ protect_secret_key( PKT_secret_key *sk, DEK *dek )
|
||||
return 0;
|
||||
|
||||
if( !sk->is_protected ) { /* okay, apply the protection */
|
||||
GCRY_CIPHER_HD cipher_hd=NULL;
|
||||
CIPHER_HANDLE cipher_hd=NULL;
|
||||
|
||||
if( openpgp_cipher_test_algo( sk->protect.algo ) )
|
||||
rc = GPGERR_CIPHER_ALGO; /* unsupport protection algorithm */
|
||||
if( check_cipher_algo( sk->protect.algo ) )
|
||||
rc = G10ERR_CIPHER_ALGO; /* unsupport protection algorithm */
|
||||
else {
|
||||
print_cipher_algo_note( sk->protect.algo );
|
||||
if( !(cipher_hd = gcry_cipher_open( sk->protect.algo,
|
||||
GCRY_CIPHER_MODE_CFB,
|
||||
GCRY_CIPHER_SECURE
|
||||
| (sk->protect.algo >= 100 ?
|
||||
0 : GCRY_CIPHER_ENABLE_SYNC) ))
|
||||
) {
|
||||
BUG();
|
||||
}
|
||||
rc = gcry_cipher_setkey( cipher_hd, dek->key, dek->keylen );
|
||||
if( rc == GCRYERR_WEAK_KEY ) {
|
||||
cipher_hd = cipher_open( sk->protect.algo,
|
||||
CIPHER_MODE_AUTO_CFB, 1 );
|
||||
if( cipher_setkey( cipher_hd, dek->key, dek->keylen ) )
|
||||
log_info(_("WARNING: Weak key detected"
|
||||
" - please change passphrase again.\n"));
|
||||
rc = 0;
|
||||
}
|
||||
else if( rc )
|
||||
BUG();
|
||||
|
||||
/* set the IV length */
|
||||
{ int blocksize = gcry_cipher_get_algo_blklen( sk->protect.algo );
|
||||
if( blocksize != 8 && blocksize != 16 )
|
||||
log_fatal("unsupported blocksize %d\n", blocksize );
|
||||
sk->protect.ivlen = blocksize;
|
||||
assert( sk->protect.ivlen <= DIM(sk->protect.iv) );
|
||||
}
|
||||
gcry_randomize(sk->protect.iv, sk->protect.ivlen,
|
||||
GCRY_STRONG_RANDOM);
|
||||
gcry_cipher_setiv( cipher_hd, sk->protect.iv, sk->protect.ivlen );
|
||||
|
||||
/* FIXME: replace set/get buffer */
|
||||
sk->protect.ivlen = cipher_get_blocksize( sk->protect.algo );
|
||||
assert( sk->protect.ivlen <= DIM(sk->protect.iv) );
|
||||
if( sk->protect.ivlen != 8 && sk->protect.ivlen != 16 )
|
||||
BUG(); /* yes, we are very careful */
|
||||
randomize_buffer(sk->protect.iv, sk->protect.ivlen, 1);
|
||||
cipher_setiv( cipher_hd, sk->protect.iv, sk->protect.ivlen );
|
||||
if( sk->version >= 4 ) {
|
||||
byte *bufarr[GNUPG_MAX_NSKEY];
|
||||
unsigned narr[GNUPG_MAX_NSKEY];
|
||||
unsigned nbits[GNUPG_MAX_NSKEY];
|
||||
byte *bufarr[PUBKEY_MAX_NSKEY];
|
||||
unsigned narr[PUBKEY_MAX_NSKEY];
|
||||
unsigned nbits[PUBKEY_MAX_NSKEY];
|
||||
int ndata=0;
|
||||
byte *p, *data;
|
||||
|
||||
for(j=0, i = pubkey_get_npkey(sk->pubkey_algo);
|
||||
i < pubkey_get_nskey(sk->pubkey_algo); i++, j++ ) {
|
||||
assert( !gcry_mpi_get_flag( sk->skey[i], GCRYMPI_FLAG_OPAQUE ) );
|
||||
|
||||
if( gcry_mpi_aprint( GCRYMPI_FMT_USG, (void**)bufarr+j,
|
||||
narr+j, sk->skey[i]))
|
||||
BUG();
|
||||
|
||||
nbits[j] = gcry_mpi_get_nbits( sk->skey[i] );
|
||||
assert( !mpi_is_opaque( sk->skey[i] ) );
|
||||
bufarr[j] = mpi_get_buffer( sk->skey[i], &narr[j], NULL );
|
||||
nbits[j] = mpi_get_nbits( sk->skey[i] );
|
||||
ndata += narr[j] + 2;
|
||||
}
|
||||
for( ; j < GNUPG_MAX_NSKEY; j++ )
|
||||
for( ; j < PUBKEY_MAX_NSKEY; j++ )
|
||||
bufarr[j] = NULL;
|
||||
ndata += 2; /* for checksum */
|
||||
ndata += opt.simple_sk_checksum? 2 : 20; /* for checksum */
|
||||
|
||||
data = gcry_xmalloc_secure( ndata );
|
||||
data = m_alloc_secure( ndata );
|
||||
p = data;
|
||||
for(j=0; j < GNUPG_MAX_NSKEY && bufarr[j]; j++ ) {
|
||||
for(j=0; j < PUBKEY_MAX_NSKEY && bufarr[j]; j++ ) {
|
||||
p[0] = nbits[j] >> 8 ;
|
||||
p[1] = nbits[j];
|
||||
p += 2;
|
||||
memcpy(p, bufarr[j], narr[j] );
|
||||
p += narr[j];
|
||||
gcry_free(bufarr[j]);
|
||||
m_free(bufarr[j]);
|
||||
}
|
||||
csum = checksum( data, ndata-2);
|
||||
sk->csum = csum;
|
||||
*p++ = csum >> 8;
|
||||
*p++ = csum;
|
||||
assert( p == data+ndata );
|
||||
gcry_cipher_encrypt( cipher_hd, data, ndata, NULL, 0 );
|
||||
|
||||
if (opt.simple_sk_checksum) {
|
||||
log_info (_("generating the deprecated 16-bit checksum"
|
||||
" for secret key protection\n"));
|
||||
csum = checksum( data, ndata-2);
|
||||
sk->csum = csum;
|
||||
*p++ = csum >> 8;
|
||||
*p++ = csum;
|
||||
sk->protect.sha1chk = 0;
|
||||
}
|
||||
else {
|
||||
MD_HANDLE h = md_open (DIGEST_ALGO_SHA1, 1);
|
||||
if (!h)
|
||||
BUG(); /* algo not available */
|
||||
md_write (h, data, ndata - 20);
|
||||
md_final (h);
|
||||
memcpy (p, md_read (h, DIGEST_ALGO_SHA1), 20);
|
||||
p += 20;
|
||||
md_close (h);
|
||||
sk->csum = csum = 0;
|
||||
sk->protect.sha1chk = 1;
|
||||
}
|
||||
assert( p == data+ndata );
|
||||
|
||||
cipher_encrypt( cipher_hd, data, data, ndata );
|
||||
for(i = pubkey_get_npkey(sk->pubkey_algo);
|
||||
i < pubkey_get_nskey(sk->pubkey_algo); i++ ) {
|
||||
mpi_release( sk->skey[i] );
|
||||
mpi_free( sk->skey[i] );
|
||||
sk->skey[i] = NULL;
|
||||
}
|
||||
i = pubkey_get_npkey(sk->pubkey_algo);
|
||||
sk->skey[i] = gcry_mpi_set_opaque(NULL, data, ndata*8 );
|
||||
sk->skey[i] = mpi_set_opaque(NULL, data, ndata );
|
||||
}
|
||||
else {
|
||||
/* NOTE: we always recalculate the checksum because there
|
||||
* are some test releases which calculated it wrong */
|
||||
/* FIXME: Replace this code -- Hmmm: why */
|
||||
csum = 0;
|
||||
for(i=pubkey_get_npkey(sk->pubkey_algo);
|
||||
i < pubkey_get_nskey(sk->pubkey_algo); i++ ) {
|
||||
csum += checksum_mpi( sk->skey[i] );
|
||||
|
||||
if( gcry_mpi_aprint( GCRYMPI_FMT_USG,
|
||||
&buffer, &nbytes, sk->skey[i] ) )
|
||||
BUG();
|
||||
|
||||
gcry_cipher_sync( cipher_hd );
|
||||
assert( !gcry_mpi_get_flag( sk->skey[i], GCRYMPI_FLAG_OPAQUE ) );
|
||||
gcry_cipher_encrypt( cipher_hd, buffer, nbytes, NULL, 0 );
|
||||
gcry_mpi_release( sk->skey[i] );
|
||||
if( gcry_mpi_scan( &sk->skey[i], GCRYMPI_FMT_USG,
|
||||
buffer,&nbytes ) )
|
||||
BUG();
|
||||
|
||||
gcry_free( buffer );
|
||||
csum += checksum_mpi_counted_nbits( sk->skey[i] );
|
||||
buffer = mpi_get_buffer( sk->skey[i], &nbytes, NULL );
|
||||
cipher_sync( cipher_hd );
|
||||
assert( !mpi_is_protected(sk->skey[i]) );
|
||||
cipher_encrypt( cipher_hd, buffer, buffer, nbytes );
|
||||
mpi_set_buffer( sk->skey[i], buffer, nbytes, 0 );
|
||||
mpi_set_protect_flag( sk->skey[i] );
|
||||
m_free( buffer );
|
||||
}
|
||||
sk->csum = csum;
|
||||
}
|
||||
sk->is_protected = 1;
|
||||
gcry_cipher_close( cipher_hd );
|
||||
cipher_close( cipher_hd );
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
|
104
g10/seskey.c
104
g10/seskey.c
@ -1,5 +1,5 @@
|
||||
/* seskey.c - make sesssion keys etc.
|
||||
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
|
||||
* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
@ -23,9 +23,9 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <gcrypt.h>
|
||||
#include "util.h"
|
||||
#include "cipher.h"
|
||||
#include "mpi.h"
|
||||
#include "main.h"
|
||||
#include "i18n.h"
|
||||
|
||||
@ -36,31 +36,22 @@
|
||||
void
|
||||
make_session_key( DEK *dek )
|
||||
{
|
||||
GCRY_CIPHER_HD chd;
|
||||
CIPHER_HANDLE chd;
|
||||
int i, rc;
|
||||
|
||||
dek->keylen = gcry_cipher_get_algo_keylen( dek->algo );
|
||||
dek->keylen = cipher_get_keylen( dek->algo ) / 8;
|
||||
|
||||
if( !(chd = gcry_cipher_open( dek->algo, GCRY_CIPHER_MODE_CFB,
|
||||
GCRY_CIPHER_SECURE
|
||||
| (dek->algo >= 100 ?
|
||||
0 : GCRY_CIPHER_ENABLE_SYNC) ))
|
||||
) {
|
||||
BUG();
|
||||
}
|
||||
|
||||
gcry_randomize( dek->key, dek->keylen, GCRY_STRONG_RANDOM );
|
||||
chd = cipher_open( dek->algo, CIPHER_MODE_AUTO_CFB, 1 );
|
||||
randomize_buffer( dek->key, dek->keylen, 1 );
|
||||
for(i=0; i < 16; i++ ) {
|
||||
rc = gcry_cipher_setkey( chd, dek->key, dek->keylen );
|
||||
rc = cipher_setkey( chd, dek->key, dek->keylen );
|
||||
if( !rc ) {
|
||||
gcry_cipher_close( chd );
|
||||
cipher_close( chd );
|
||||
return;
|
||||
}
|
||||
if( rc != GCRYERR_WEAK_KEY )
|
||||
BUG();
|
||||
log_info(_("weak key created - retrying\n") );
|
||||
/* Renew the session key until we get a non-weak key. */
|
||||
gcry_randomize( dek->key, dek->keylen, GCRY_STRONG_RANDOM );
|
||||
randomize_buffer( dek->key, dek->keylen, 1 );
|
||||
}
|
||||
log_fatal(_(
|
||||
"cannot avoid weak key for symmetric cipher; tried %d times!\n"),
|
||||
@ -108,13 +99,13 @@ encode_session_key( DEK *dek, unsigned nbits )
|
||||
for( p = dek->key, i=0; i < dek->keylen; i++ )
|
||||
csum += *p++;
|
||||
|
||||
frame = gcry_xmalloc_secure( nframe );
|
||||
frame = m_alloc_secure( nframe );
|
||||
n = 0;
|
||||
frame[n++] = 0;
|
||||
frame[n++] = 2;
|
||||
i = nframe - 6 - dek->keylen;
|
||||
assert( i > 0 );
|
||||
p = gcry_random_bytes_secure( i, GCRY_STRONG_RANDOM );
|
||||
p = get_random_bits( i*8, 1, 1 );
|
||||
/* replace zero bytes by new values */
|
||||
for(;;) {
|
||||
int j, k;
|
||||
@ -127,14 +118,14 @@ encode_session_key( DEK *dek, unsigned nbits )
|
||||
if( !k )
|
||||
break; /* okay: no zero bytes */
|
||||
k += k/128; /* better get some more */
|
||||
pp = gcry_random_bytes_secure( k, GCRY_STRONG_RANDOM);
|
||||
pp = get_random_bits( k*8, 1, 1);
|
||||
for(j=0; j < i && k ; j++ )
|
||||
if( !p[j] )
|
||||
p[j] = pp[--k];
|
||||
gcry_free(pp);
|
||||
m_free(pp);
|
||||
}
|
||||
memcpy( frame+n, p, i );
|
||||
gcry_free(p);
|
||||
m_free(p);
|
||||
n += i;
|
||||
frame[n++] = 0;
|
||||
frame[n++] = dek->algo;
|
||||
@ -142,16 +133,15 @@ encode_session_key( DEK *dek, unsigned nbits )
|
||||
frame[n++] = csum >>8;
|
||||
frame[n++] = csum;
|
||||
assert( n == nframe );
|
||||
if( gcry_mpi_scan( &a, GCRYMPI_FMT_USG, frame, &nframe ) )
|
||||
BUG();
|
||||
gcry_free(frame);
|
||||
|
||||
a = mpi_alloc_secure( (nframe+BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB );
|
||||
mpi_set_buffer( a, frame, nframe, 0 );
|
||||
m_free(frame);
|
||||
return a;
|
||||
}
|
||||
|
||||
|
||||
static MPI
|
||||
do_encode_md( GCRY_MD_HD md, int algo, size_t len, unsigned nbits,
|
||||
do_encode_md( MD_HANDLE md, int algo, size_t len, unsigned nbits,
|
||||
const byte *asn, size_t asnlen, int v3compathack )
|
||||
{
|
||||
int nframe = (nbits+7) / 8;
|
||||
@ -165,12 +155,11 @@ do_encode_md( GCRY_MD_HD md, int algo, size_t len, unsigned nbits,
|
||||
|
||||
/* We encode the MD in this way:
|
||||
*
|
||||
* 0 1 PAD(n bytes) 0 ASN(asnlen bytes) MD(len bytes)
|
||||
* 0 A PAD(n bytes) 0 ASN(asnlen bytes) MD(len bytes)
|
||||
*
|
||||
* PAD consists of FF bytes.
|
||||
*/
|
||||
frame = gcry_md_is_secure(md)? gcry_xmalloc_secure( nframe )
|
||||
: gcry_xmalloc( nframe );
|
||||
frame = md_is_secure(md)? m_alloc_secure( nframe ) : m_alloc( nframe );
|
||||
n = 0;
|
||||
frame[n++] = 0;
|
||||
frame[n++] = v3compathack? algo : 1; /* block type */
|
||||
@ -179,11 +168,13 @@ do_encode_md( GCRY_MD_HD md, int algo, size_t len, unsigned nbits,
|
||||
memset( frame+n, 0xff, i ); n += i;
|
||||
frame[n++] = 0;
|
||||
memcpy( frame+n, asn, asnlen ); n += asnlen;
|
||||
memcpy( frame+n, gcry_md_read(md, algo), len ); n += len;
|
||||
memcpy( frame+n, md_read(md, algo), len ); n += len;
|
||||
assert( n == nframe );
|
||||
if( gcry_mpi_scan( &a, GCRYMPI_FMT_USG, frame, &nframe ) )
|
||||
BUG();
|
||||
gcry_free(frame);
|
||||
a = md_is_secure(md)?
|
||||
mpi_alloc_secure( (nframe+BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB )
|
||||
: mpi_alloc( (nframe+BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB );
|
||||
mpi_set_buffer( a, frame, nframe, 0 );
|
||||
m_free(frame);
|
||||
return a;
|
||||
}
|
||||
|
||||
@ -192,36 +183,35 @@ do_encode_md( GCRY_MD_HD md, int algo, size_t len, unsigned nbits,
|
||||
* Encode a message digest into an MPI.
|
||||
* v3compathack is used to work around a bug in old GnuPG versions
|
||||
* which did put the algo identifier inseatd of the block type 1 into
|
||||
* the encoded value. setting this vare force the old behaviour.
|
||||
* the encoded value. Setting this flag forces the old behaviour.
|
||||
*/
|
||||
MPI
|
||||
encode_md_value( int pubkey_algo, GCRY_MD_HD md, int hash_algo,
|
||||
encode_md_value( int pubkey_algo, MD_HANDLE md, int hash_algo,
|
||||
unsigned nbits, int v3compathack )
|
||||
{
|
||||
int algo = hash_algo? hash_algo : gcry_md_get_algo(md);
|
||||
int algo = hash_algo? hash_algo : md_get_algo(md);
|
||||
const byte *asn;
|
||||
size_t asnlen, mdlen;
|
||||
MPI frame;
|
||||
|
||||
if( pubkey_algo == GCRY_PK_DSA ) {
|
||||
size_t n = gcry_md_get_algo_dlen(hash_algo);
|
||||
if( gcry_mpi_scan( &frame, GCRYMPI_FMT_USG,
|
||||
gcry_md_read(md, hash_algo), &n ) )
|
||||
BUG();
|
||||
if( pubkey_algo == PUBKEY_ALGO_DSA ) {
|
||||
mdlen = md_digest_length (hash_algo);
|
||||
if (mdlen != 20) {
|
||||
log_error (_("DSA requires the use of a 160 bit hash algorithm\n"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
frame = md_is_secure(md)? mpi_alloc_secure((md_digest_length(hash_algo)
|
||||
+BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB )
|
||||
: mpi_alloc((md_digest_length(hash_algo)
|
||||
+BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB );
|
||||
mpi_set_buffer( frame, md_read(md, hash_algo),
|
||||
md_digest_length(hash_algo), 0 );
|
||||
}
|
||||
else {
|
||||
byte *asn;
|
||||
size_t asnlen;
|
||||
|
||||
if( gcry_md_algo_info( algo, GCRYCTL_GET_ASNOID, NULL, &asnlen ) )
|
||||
log_fatal("can't get OID of algo %d: %s\n",
|
||||
algo, gcry_strerror(-1));
|
||||
asn = gcry_xmalloc( asnlen );
|
||||
if( gcry_md_algo_info( algo, GCRYCTL_GET_ASNOID, asn, &asnlen ) )
|
||||
BUG();
|
||||
frame = do_encode_md( md, algo, gcry_md_get_algo_dlen( algo ),
|
||||
nbits, asn, asnlen, v3compathack );
|
||||
gcry_free( asn );
|
||||
asn = md_asn_oid( algo, &asnlen, &mdlen );
|
||||
frame = do_encode_md( md, algo, mdlen, nbits, asn, asnlen, v3compathack);
|
||||
}
|
||||
return frame;
|
||||
}
|
||||
|
||||
|
||||
|
370
g10/sig-check.c
370
g10/sig-check.c
@ -1,5 +1,5 @@
|
||||
/* sig-check.c - Check a signature
|
||||
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
|
||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
@ -23,11 +23,12 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <gcrypt.h>
|
||||
#include "util.h"
|
||||
#include "packet.h"
|
||||
#include "memory.h"
|
||||
#include "mpi.h"
|
||||
#include "keydb.h"
|
||||
#include "cipher.h"
|
||||
#include "main.h"
|
||||
#include "status.h"
|
||||
#include "i18n.h"
|
||||
@ -35,108 +36,35 @@
|
||||
|
||||
struct cmp_help_context_s {
|
||||
PKT_signature *sig;
|
||||
GCRY_MD_HD md;
|
||||
MD_HANDLE md;
|
||||
};
|
||||
|
||||
|
||||
static int do_signature_check( PKT_signature *sig, GCRY_MD_HD digest,
|
||||
u32 *r_expiredate, int *r_expired );
|
||||
static int do_check( PKT_public_key *pk, PKT_signature *sig,
|
||||
GCRY_MD_HD digest, int *r_expired );
|
||||
|
||||
|
||||
|
||||
/****************
|
||||
* Emulate our old PK interface here - sometime in the future we might
|
||||
* change the internal design to directly fit to libgcrypt.
|
||||
*/
|
||||
static int
|
||||
pk_verify( int algo, MPI hash, MPI *data, MPI *pkey,
|
||||
int (*cmp)(void *, MPI), void *opaque )
|
||||
{
|
||||
GCRY_SEXP s_sig, s_hash, s_pkey;
|
||||
int rc;
|
||||
|
||||
/* forget about cmp and opaque - we never used it */
|
||||
|
||||
/* make a sexp from pkey */
|
||||
if( algo == GCRY_PK_DSA ) {
|
||||
rc = gcry_sexp_build ( &s_pkey, NULL,
|
||||
"(public-key(dsa(p%m)(q%m)(g%m)(y%m)))",
|
||||
pkey[0], pkey[1], pkey[2], pkey[3] );
|
||||
}
|
||||
else if( algo == GCRY_PK_ELG || algo == GCRY_PK_ELG_E ) {
|
||||
rc = gcry_sexp_build ( &s_pkey, NULL,
|
||||
"(public-key(elg(p%m)(g%m)(y%m)))",
|
||||
pkey[0], pkey[1], pkey[2] );
|
||||
}
|
||||
else if( algo == GCRY_PK_RSA ) {
|
||||
rc = gcry_sexp_build ( &s_pkey, NULL,
|
||||
"(public-key(rsa(n%m)(e%m)))",
|
||||
pkey[0], pkey[1] );
|
||||
}
|
||||
else
|
||||
return GPGERR_PUBKEY_ALGO;
|
||||
|
||||
if ( rc )
|
||||
BUG ();
|
||||
|
||||
/* put hash into a S-Exp s_hash */
|
||||
if ( gcry_sexp_build( &s_hash, NULL, "%m", hash ) )
|
||||
BUG ();
|
||||
|
||||
/* put data into a S-Exp s_sig */
|
||||
if( algo == GCRY_PK_DSA ) {
|
||||
rc = gcry_sexp_build ( &s_sig, NULL,
|
||||
"(sig-val(dsa(r%m)(s%m)))", data[0], data[1] );
|
||||
}
|
||||
else if( algo == GCRY_PK_ELG || algo == GCRY_PK_ELG_E ) {
|
||||
rc = gcry_sexp_build ( &s_sig, NULL,
|
||||
"(sig-val(elg(r%m)(s%m)))", data[0], data[1] );
|
||||
}
|
||||
else if( algo == GCRY_PK_RSA ) {
|
||||
rc = gcry_sexp_build ( &s_sig, NULL,
|
||||
"(sig-val(rsa(s%m)))", data[0] );
|
||||
}
|
||||
else
|
||||
BUG();
|
||||
|
||||
if ( rc )
|
||||
BUG ();
|
||||
|
||||
|
||||
rc = gcry_pk_verify( s_sig, s_hash, s_pkey );
|
||||
gcry_sexp_release( s_sig );
|
||||
gcry_sexp_release( s_hash );
|
||||
gcry_sexp_release( s_pkey );
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
MD_HANDLE digest, int *r_expired );
|
||||
|
||||
/****************
|
||||
* Check the signature which is contained in SIG.
|
||||
* The GCRY_MD_HD should be currently open, so that this function
|
||||
* The MD_HANDLE should be currently open, so that this function
|
||||
* is able to append some data, before finalizing the digest.
|
||||
*/
|
||||
int
|
||||
signature_check( PKT_signature *sig, GCRY_MD_HD digest )
|
||||
signature_check( PKT_signature *sig, MD_HANDLE digest )
|
||||
{
|
||||
u32 dummy;
|
||||
int dum2;
|
||||
return do_signature_check( sig, digest, &dummy, &dum2 );
|
||||
return signature_check2( sig, digest, &dummy, &dum2 );
|
||||
}
|
||||
|
||||
static int
|
||||
do_signature_check( PKT_signature *sig, GCRY_MD_HD digest,
|
||||
u32 *r_expiredate, int *r_expired )
|
||||
int
|
||||
signature_check2( PKT_signature *sig, MD_HANDLE digest,
|
||||
u32 *r_expiredate, int *r_expired )
|
||||
{
|
||||
PKT_public_key *pk = gcry_xcalloc( 1, sizeof *pk );
|
||||
PKT_public_key *pk = m_alloc_clear( sizeof *pk );
|
||||
int rc=0;
|
||||
|
||||
*r_expiredate = 0;
|
||||
if( get_pubkey( pk, sig->keyid ) )
|
||||
rc = GPGERR_NO_PUBKEY;
|
||||
rc = G10ERR_NO_PUBKEY;
|
||||
else {
|
||||
*r_expiredate = pk->expiredate;
|
||||
rc = do_check( pk, sig, digest, r_expired );
|
||||
@ -150,40 +78,38 @@ do_signature_check( PKT_signature *sig, GCRY_MD_HD digest,
|
||||
* this sig-id we could have also used the hash of the document
|
||||
* and the timestamp, but the drawback of this is, that it is
|
||||
* not possible to sign more than one identical document within
|
||||
* one second. Some remote bacth processing applications might
|
||||
* one second. Some remote batch processing applications might
|
||||
* like this feature here */
|
||||
GCRY_MD_HD md;
|
||||
MD_HANDLE md;
|
||||
u32 a = sig->timestamp;
|
||||
int i, nsig = pubkey_get_nsig( sig->pubkey_algo );
|
||||
byte *p, *buffer;
|
||||
|
||||
if( !(md = gcry_md_open( GCRY_MD_RMD160, 0)) )
|
||||
BUG();
|
||||
gcry_md_putc( digest, sig->pubkey_algo );
|
||||
gcry_md_putc( digest, sig->digest_algo );
|
||||
gcry_md_putc( digest, (a >> 24) & 0xff );
|
||||
gcry_md_putc( digest, (a >> 16) & 0xff );
|
||||
gcry_md_putc( digest, (a >> 8) & 0xff );
|
||||
gcry_md_putc( digest, a & 0xff );
|
||||
md = md_open( DIGEST_ALGO_RMD160, 0);
|
||||
md_putc( digest, sig->pubkey_algo );
|
||||
md_putc( digest, sig->digest_algo );
|
||||
md_putc( digest, (a >> 24) & 0xff );
|
||||
md_putc( digest, (a >> 16) & 0xff );
|
||||
md_putc( digest, (a >> 8) & 0xff );
|
||||
md_putc( digest, a & 0xff );
|
||||
for(i=0; i < nsig; i++ ) {
|
||||
size_t n = gcry_mpi_get_nbits( sig->data[i]);
|
||||
unsigned n = mpi_get_nbits( sig->data[i]);
|
||||
|
||||
gcry_md_putc( md, n>>8);
|
||||
gcry_md_putc( md, n );
|
||||
if( gcry_mpi_aprint( GCRYMPI_FMT_USG, &p, &n, sig->data[i] ) )
|
||||
BUG();
|
||||
gcry_md_write( md, p, n );
|
||||
gcry_free(p);
|
||||
md_putc( md, n>>8);
|
||||
md_putc( md, n );
|
||||
p = mpi_get_buffer( sig->data[i], &n, NULL );
|
||||
md_write( md, p, n );
|
||||
m_free(p);
|
||||
}
|
||||
gcry_md_final( md );
|
||||
p = make_radix64_string( gcry_md_read( md, 0 ), 20 );
|
||||
buffer = gcry_xmalloc( strlen(p) + 60 );
|
||||
md_final( md );
|
||||
p = make_radix64_string( md_read( md, 0 ), 20 );
|
||||
buffer = m_alloc( strlen(p) + 60 );
|
||||
sprintf( buffer, "%s %s %lu",
|
||||
p, strtimestamp( sig->timestamp ), (ulong)sig->timestamp );
|
||||
write_status_text( STATUS_SIG_ID, buffer );
|
||||
gcry_free(buffer);
|
||||
gcry_free(p);
|
||||
gcry_md_close(md);
|
||||
m_free(buffer);
|
||||
m_free(p);
|
||||
md_close(md);
|
||||
}
|
||||
|
||||
return rc;
|
||||
@ -203,7 +129,7 @@ cmp_help( void *opaque, MPI result )
|
||||
size_t mdlen, asnlen;
|
||||
struct cmp_help_context_s *ctx = opaque;
|
||||
PKT_signature *sig = ctx->sig;
|
||||
GCRY_MD_HD digest = ctx->md;
|
||||
MD_HANDLE digest = ctx->md;
|
||||
|
||||
old_enc = 0;
|
||||
for(i=j=0; (c=mpi_getbyte(result, i)) != -1; i++ ) {
|
||||
@ -226,7 +152,7 @@ cmp_help( void *opaque, MPI result )
|
||||
}
|
||||
if( old_enc ) {
|
||||
log_error("old encoding scheme is not supported\n");
|
||||
return GPGERR_GENERAL;
|
||||
return G10ERR_GENERAL;
|
||||
}
|
||||
|
||||
if( (rc=check_digest_algo(sig->digest_algo)) )
|
||||
@ -238,25 +164,25 @@ cmp_help( void *opaque, MPI result )
|
||||
if( asn[j] != c )
|
||||
break;
|
||||
if( j != -1 || mpi_getbyte(result, i) )
|
||||
return GPGERR_BAD_PUBKEY; /* ASN is wrong */
|
||||
return G10ERR_BAD_PUBKEY; /* ASN is wrong */
|
||||
for(i++; (c=mpi_getbyte(result, i)) != -1; i++ )
|
||||
if( c != 0xff )
|
||||
break;
|
||||
i++;
|
||||
if( c != sig->digest_algo || mpi_getbyte(result, i) ) {
|
||||
/* Padding or leading bytes in signature is wrong */
|
||||
return GPGERR_BAD_PUBKEY;
|
||||
return G10ERR_BAD_PUBKEY;
|
||||
}
|
||||
if( mpi_getbyte(result, mdlen-1) != sig->digest_start[0]
|
||||
|| mpi_getbyte(result, mdlen-2) != sig->digest_start[1] ) {
|
||||
/* Wrong key used to check the signature */
|
||||
return GPGERR_BAD_PUBKEY;
|
||||
return G10ERR_BAD_PUBKEY;
|
||||
}
|
||||
|
||||
dp = md_read( digest, sig->digest_algo );
|
||||
for(i=mdlen-1; i >= 0; i--, dp++ ) {
|
||||
if( mpi_getbyte( result, i ) != *dp )
|
||||
return GPGERR_BAD_SIGN;
|
||||
return G10ERR_BAD_SIGN;
|
||||
}
|
||||
return 0;
|
||||
#else
|
||||
@ -266,7 +192,7 @@ cmp_help( void *opaque, MPI result )
|
||||
|
||||
|
||||
static int
|
||||
do_check( PKT_public_key *pk, PKT_signature *sig, GCRY_MD_HD digest,
|
||||
do_check( PKT_public_key *pk, PKT_signature *sig, MD_HANDLE digest,
|
||||
int *r_expired )
|
||||
{
|
||||
MPI result = NULL;
|
||||
@ -275,10 +201,10 @@ do_check( PKT_public_key *pk, PKT_signature *sig, GCRY_MD_HD digest,
|
||||
u32 cur_time;
|
||||
|
||||
*r_expired = 0;
|
||||
if( pk->version == 4 && pk->pubkey_algo == GCRY_PK_ELG_E ) {
|
||||
if( pk->version == 4 && pk->pubkey_algo == PUBKEY_ALGO_ELGAMAL_E ) {
|
||||
log_info(_("this is a PGP generated "
|
||||
"ElGamal key which is NOT secure for signatures!\n"));
|
||||
return GPGERR_PUBKEY_ALGO;
|
||||
"ElGamal key which is NOT secure for signatures!\n"));
|
||||
return G10ERR_PUBKEY_ALGO;
|
||||
}
|
||||
|
||||
if( pk->timestamp > sig->timestamp ) {
|
||||
@ -288,7 +214,7 @@ do_check( PKT_public_key *pk, PKT_signature *sig, GCRY_MD_HD digest,
|
||||
: _("public key is %lu seconds newer than the signature\n"),
|
||||
d );
|
||||
if( !opt.ignore_time_conflict )
|
||||
return GPGERR_TIME_CONFLICT; /* pubkey newer than signature */
|
||||
return G10ERR_TIME_CONFLICT; /* pubkey newer than signature */
|
||||
}
|
||||
|
||||
cur_time = make_timestamp();
|
||||
@ -299,44 +225,55 @@ do_check( PKT_public_key *pk, PKT_signature *sig, GCRY_MD_HD digest,
|
||||
: _("key has been created %lu seconds "
|
||||
"in future (time warp or clock problem)\n"), d );
|
||||
if( !opt.ignore_time_conflict )
|
||||
return GPGERR_TIME_CONFLICT;
|
||||
return G10ERR_TIME_CONFLICT;
|
||||
}
|
||||
|
||||
if( pk->expiredate && pk->expiredate < cur_time ) {
|
||||
log_info(_("NOTE: signature key expired %s\n"),
|
||||
asctimestamp( pk->expiredate ) );
|
||||
char buf[11];
|
||||
if (opt.verbose) {
|
||||
u32 tmp_kid[2];
|
||||
|
||||
keyid_from_pk( pk, tmp_kid );
|
||||
log_info(_("NOTE: signature key %08lX expired %s\n"),
|
||||
(ulong)tmp_kid[1], asctimestamp( pk->expiredate ) );
|
||||
}
|
||||
/* SIGEXPIRED is deprecated. Use KEYEXPIRED. */
|
||||
sprintf(buf,"%lu",(ulong)pk->expiredate);
|
||||
write_status_text(STATUS_KEYEXPIRED,buf);
|
||||
write_status(STATUS_SIGEXPIRED);
|
||||
*r_expired = 1;
|
||||
}
|
||||
|
||||
|
||||
if( (rc=openpgp_md_test_algo(sig->digest_algo)) )
|
||||
if( (rc=check_digest_algo(sig->digest_algo)) )
|
||||
return rc;
|
||||
if( (rc=openpgp_pk_test_algo(sig->pubkey_algo, 0)) )
|
||||
if( (rc=check_pubkey_algo(sig->pubkey_algo)) )
|
||||
return rc;
|
||||
|
||||
/* make sure the digest algo is enabled (in case of a detached signature)*/
|
||||
gcry_md_enable( digest, sig->digest_algo );
|
||||
md_enable( digest, sig->digest_algo );
|
||||
|
||||
/* complete the digest */
|
||||
if( sig->version >= 4 )
|
||||
gcry_md_putc( digest, sig->version );
|
||||
gcry_md_putc( digest, sig->sig_class );
|
||||
md_putc( digest, sig->version );
|
||||
md_putc( digest, sig->sig_class );
|
||||
if( sig->version < 4 ) {
|
||||
u32 a = sig->timestamp;
|
||||
gcry_md_putc( digest, (a >> 24) & 0xff );
|
||||
gcry_md_putc( digest, (a >> 16) & 0xff );
|
||||
gcry_md_putc( digest, (a >> 8) & 0xff );
|
||||
gcry_md_putc( digest, a & 0xff );
|
||||
md_putc( digest, (a >> 24) & 0xff );
|
||||
md_putc( digest, (a >> 16) & 0xff );
|
||||
md_putc( digest, (a >> 8) & 0xff );
|
||||
md_putc( digest, a & 0xff );
|
||||
}
|
||||
else {
|
||||
byte buf[6];
|
||||
size_t n;
|
||||
gcry_md_putc( digest, sig->pubkey_algo );
|
||||
gcry_md_putc( digest, sig->digest_algo );
|
||||
if( sig->hashed_data ) {
|
||||
n = (sig->hashed_data[0] << 8) | sig->hashed_data[1];
|
||||
gcry_md_write( digest, sig->hashed_data, n+2 );
|
||||
md_putc( digest, sig->pubkey_algo );
|
||||
md_putc( digest, sig->digest_algo );
|
||||
if( sig->hashed ) {
|
||||
n = sig->hashed->len;
|
||||
md_putc (digest, (n >> 8) );
|
||||
md_putc (digest, n );
|
||||
md_write (digest, sig->hashed->data, n);
|
||||
n += 6;
|
||||
}
|
||||
else
|
||||
@ -348,57 +285,61 @@ do_check( PKT_public_key *pk, PKT_signature *sig, GCRY_MD_HD digest,
|
||||
buf[3] = n >> 16;
|
||||
buf[4] = n >> 8;
|
||||
buf[5] = n;
|
||||
gcry_md_write( digest, buf, 6 );
|
||||
md_write( digest, buf, 6 );
|
||||
}
|
||||
gcry_md_final( digest );
|
||||
md_final( digest );
|
||||
|
||||
result = encode_md_value( pk->pubkey_algo, digest, sig->digest_algo,
|
||||
gcry_mpi_get_nbits(pk->pkey[0]), 0);
|
||||
mpi_get_nbits(pk->pkey[0]), 0 );
|
||||
if (!result)
|
||||
return G10ERR_GENERAL;
|
||||
ctx.sig = sig;
|
||||
ctx.md = digest;
|
||||
rc = pk_verify( pk->pubkey_algo, result, sig->data, pk->pkey,
|
||||
rc = pubkey_verify( pk->pubkey_algo, result, sig->data, pk->pkey,
|
||||
cmp_help, &ctx );
|
||||
mpi_release( result );
|
||||
mpi_free( result );
|
||||
if( (opt.emulate_bugs & EMUBUG_MDENCODE)
|
||||
&& rc == GPGERR_BAD_SIGN && is_ELGAMAL(pk->pubkey_algo) ) {
|
||||
&& rc == G10ERR_BAD_SIGN && is_ELGAMAL(pk->pubkey_algo) ) {
|
||||
/* In this case we try again because old GnuPG versions didn't encode
|
||||
* the hash right. There is no problem with DSA however */
|
||||
result = encode_md_value( pk->pubkey_algo, digest, sig->digest_algo,
|
||||
gcry_mpi_get_nbits(pk->pkey[0]), (sig->version < 5) );
|
||||
ctx.sig = sig;
|
||||
ctx.md = digest;
|
||||
rc = pk_verify( pk->pubkey_algo, result, sig->data, pk->pkey,
|
||||
cmp_help, &ctx );
|
||||
mpi_get_nbits(pk->pkey[0]), (sig->version < 5) );
|
||||
if (!result)
|
||||
rc = G10ERR_GENERAL;
|
||||
else {
|
||||
ctx.sig = sig;
|
||||
ctx.md = digest;
|
||||
rc = pubkey_verify( pk->pubkey_algo, result, sig->data, pk->pkey,
|
||||
cmp_help, &ctx );
|
||||
}
|
||||
}
|
||||
|
||||
if( !rc && sig->flags.unknown_critical ) {
|
||||
log_info(_("assuming bad signature due to an unknown critical bit\n"));
|
||||
rc = GPGERR_BAD_SIGN;
|
||||
rc = G10ERR_BAD_SIGN;
|
||||
}
|
||||
sig->flags.checked = 1;
|
||||
sig->flags.valid = !rc;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
hash_uid_node( KBNODE unode, GCRY_MD_HD md, PKT_signature *sig )
|
||||
hash_uid_node( KBNODE unode, MD_HANDLE md, PKT_signature *sig )
|
||||
{
|
||||
PKT_user_id *uid = unode->pkt->pkt.user_id;
|
||||
|
||||
assert( unode->pkt->pkttype == PKT_USER_ID );
|
||||
if( uid->photo ) {
|
||||
if( uid->attrib_data ) {
|
||||
if( sig->version >=4 ) {
|
||||
byte buf[5];
|
||||
buf[0] = 0xd1; /* packet of type 17 */
|
||||
buf[1] = uid->photolen >> 24; /* always use 4 length bytes */
|
||||
buf[2] = uid->photolen >> 16;
|
||||
buf[3] = uid->photolen >> 8;
|
||||
buf[4] = uid->photolen;
|
||||
gcry_md_write( md, buf, 5 );
|
||||
buf[0] = 0xd1; /* packet of type 17 */
|
||||
buf[1] = uid->attrib_len >> 24; /* always use 4 length bytes */
|
||||
buf[2] = uid->attrib_len >> 16;
|
||||
buf[3] = uid->attrib_len >> 8;
|
||||
buf[4] = uid->attrib_len;
|
||||
md_write( md, buf, 5 );
|
||||
}
|
||||
gcry_md_write( md, uid->photo, uid->photolen );
|
||||
md_write( md, uid->attrib_data, uid->attrib_len );
|
||||
}
|
||||
else {
|
||||
if( sig->version >=4 ) {
|
||||
@ -408,9 +349,26 @@ hash_uid_node( KBNODE unode, GCRY_MD_HD md, PKT_signature *sig )
|
||||
buf[2] = uid->len >> 16;
|
||||
buf[3] = uid->len >> 8;
|
||||
buf[4] = uid->len;
|
||||
gcry_md_write( md, buf, 5 );
|
||||
md_write( md, buf, 5 );
|
||||
}
|
||||
gcry_md_write( md, uid->name, uid->len );
|
||||
md_write( md, uid->name, uid->len );
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
cache_sig_result ( PKT_signature *sig, int result )
|
||||
{
|
||||
if ( !result ) {
|
||||
sig->flags.checked = 1;
|
||||
sig->flags.valid = 1;
|
||||
}
|
||||
else if ( result == G10ERR_BAD_SIGN ) {
|
||||
sig->flags.checked = 1;
|
||||
sig->flags.valid = 0;
|
||||
}
|
||||
else {
|
||||
sig->flags.checked = 0;
|
||||
sig->flags.valid = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -431,7 +389,7 @@ int
|
||||
check_key_signature2( KBNODE root, KBNODE node, int *is_selfsig,
|
||||
u32 *r_expiredate, int *r_expired )
|
||||
{
|
||||
GCRY_MD_HD md;
|
||||
MD_HANDLE md;
|
||||
PKT_public_key *pk;
|
||||
PKT_signature *sig;
|
||||
int algo;
|
||||
@ -448,47 +406,49 @@ check_key_signature2( KBNODE root, KBNODE node, int *is_selfsig,
|
||||
sig = node->pkt->pkt.signature;
|
||||
algo = sig->digest_algo;
|
||||
|
||||
#if 0
|
||||
if( sig->flags.checked ) {
|
||||
log_debug("check_key_signature: already checked: %s\n",
|
||||
sig->flags.valid? "good":"bad" );
|
||||
if ( sig->flags.valid )
|
||||
return 0; /* shortcut already checked signatures */
|
||||
/* FIXME: We should also do this with bad signatures but here we
|
||||
* have to distinguish between several reasons; e.g. for a missing
|
||||
* public key. the key may now be available.
|
||||
* For now we simply don't shortcut bad signatures
|
||||
*/
|
||||
}
|
||||
#endif
|
||||
/* check whether we have cached the result of a previous signature check.*/
|
||||
if ( !opt.no_sig_cache ) {
|
||||
if (sig->flags.checked) { /*cached status available*/
|
||||
if( is_selfsig ) {
|
||||
u32 keyid[2];
|
||||
|
||||
if( (rc=openpgp_md_test_algo(algo)) )
|
||||
keyid_from_pk( pk, keyid );
|
||||
if( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1] )
|
||||
*is_selfsig = 1;
|
||||
}
|
||||
return sig->flags.valid? 0 : G10ERR_BAD_SIGN;
|
||||
}
|
||||
}
|
||||
|
||||
if( (rc=check_digest_algo(algo)) )
|
||||
return rc;
|
||||
|
||||
if( sig->sig_class == 0x20 ) {
|
||||
if( !(md = gcry_md_open( algo, 0 )) )
|
||||
BUG();
|
||||
if( sig->sig_class == 0x20 ) { /* key revocation */
|
||||
md = md_open( algo, 0 );
|
||||
hash_public_key( md, pk );
|
||||
rc = do_check( pk, sig, md, r_expired );
|
||||
gcry_md_close(md);
|
||||
cache_sig_result ( sig, rc );
|
||||
md_close(md);
|
||||
}
|
||||
else if( sig->sig_class == 0x28 ) { /* subkey revocation */
|
||||
KBNODE snode = find_prev_kbnode( root, node, PKT_PUBLIC_SUBKEY );
|
||||
|
||||
if( snode ) {
|
||||
if( !(md = gcry_md_open( algo, 0 )) )
|
||||
BUG();
|
||||
md = md_open( algo, 0 );
|
||||
hash_public_key( md, pk );
|
||||
hash_public_key( md, snode->pkt->pkt.public_key );
|
||||
rc = do_check( pk, sig, md, r_expired );
|
||||
gcry_md_close(md);
|
||||
cache_sig_result ( sig, rc );
|
||||
md_close(md);
|
||||
}
|
||||
else {
|
||||
log_error("no subkey for subkey revocation packet\n");
|
||||
rc = GPGERR_SIG_CLASS;
|
||||
if (!opt.quiet)
|
||||
log_info ("key %08lX: no subkey for subkey revocation packet\n",
|
||||
(ulong)keyid_from_pk (pk, NULL));
|
||||
rc = G10ERR_SIG_CLASS;
|
||||
}
|
||||
}
|
||||
else if( sig->sig_class == 0x18 ) {
|
||||
else if( sig->sig_class == 0x18 ) { /* key binding */
|
||||
KBNODE snode = find_prev_kbnode( root, node, PKT_PUBLIC_SUBKEY );
|
||||
|
||||
if( snode ) {
|
||||
@ -499,27 +459,35 @@ check_key_signature2( KBNODE root, KBNODE node, int *is_selfsig,
|
||||
if( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1] )
|
||||
*is_selfsig = 1;
|
||||
}
|
||||
if( !(md = gcry_md_open( algo, 0 )) )
|
||||
BUG();
|
||||
md = md_open( algo, 0 );
|
||||
hash_public_key( md, pk );
|
||||
hash_public_key( md, snode->pkt->pkt.public_key );
|
||||
rc = do_check( pk, sig, md, r_expired );
|
||||
gcry_md_close(md);
|
||||
cache_sig_result ( sig, rc );
|
||||
md_close(md);
|
||||
}
|
||||
else {
|
||||
log_error("no subkey for key signature packet\n");
|
||||
rc = GPGERR_SIG_CLASS;
|
||||
if (!opt.quiet)
|
||||
log_info ("key %08lX: no subkey for subkey binding packet\n",
|
||||
(ulong)keyid_from_pk (pk, NULL));
|
||||
rc = G10ERR_SIG_CLASS;
|
||||
}
|
||||
}
|
||||
else {
|
||||
else if( sig->sig_class == 0x1f ) { /* direct key signature */
|
||||
md = md_open( algo, 0 );
|
||||
hash_public_key( md, pk );
|
||||
rc = do_check( pk, sig, md, r_expired );
|
||||
cache_sig_result ( sig, rc );
|
||||
md_close(md);
|
||||
}
|
||||
else { /* all other classes */
|
||||
KBNODE unode = find_prev_kbnode( root, node, PKT_USER_ID );
|
||||
|
||||
if( unode ) {
|
||||
u32 keyid[2];
|
||||
|
||||
keyid_from_pk( pk, keyid );
|
||||
if( !(md = gcry_md_open( algo, 0 )) )
|
||||
BUG();
|
||||
md = md_open( algo, 0 );
|
||||
hash_public_key( md, pk );
|
||||
hash_uid_node( unode, md, sig );
|
||||
if( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1] ) {
|
||||
@ -528,13 +496,17 @@ check_key_signature2( KBNODE root, KBNODE node, int *is_selfsig,
|
||||
rc = do_check( pk, sig, md, r_expired );
|
||||
}
|
||||
else {
|
||||
rc = do_signature_check( sig, md, r_expiredate, r_expired );
|
||||
rc = signature_check2( sig, md, r_expiredate, r_expired );
|
||||
}
|
||||
gcry_md_close(md);
|
||||
cache_sig_result ( sig, rc );
|
||||
md_close(md);
|
||||
}
|
||||
else {
|
||||
log_error("no user ID for key signature packet\n");
|
||||
rc = GPGERR_SIG_CLASS;
|
||||
if (!opt.quiet)
|
||||
log_info ("key %08lX: no user ID for key signature packet "
|
||||
"of class %02x\n",
|
||||
(ulong)keyid_from_pk (pk, NULL), sig->sig_class );
|
||||
rc = G10ERR_SIG_CLASS;
|
||||
}
|
||||
}
|
||||
|
||||
|
1274
g10/sign.c
1274
g10/sign.c
File diff suppressed because it is too large
Load Diff
124
g10/signal.c
124
g10/signal.c
@ -1,5 +1,5 @@
|
||||
/* signal.c - signal handling
|
||||
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
|
||||
* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
@ -27,9 +27,9 @@
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <gcrypt.h>
|
||||
#include "options.h"
|
||||
#include "errors.h"
|
||||
#include "memory.h"
|
||||
#include "util.h"
|
||||
#include "main.h"
|
||||
#include "ttyio.h"
|
||||
@ -38,6 +38,36 @@
|
||||
static volatile int caught_fatal_sig = 0;
|
||||
static volatile int caught_sigusr1 = 0;
|
||||
|
||||
static void
|
||||
init_one_signal (int sig, RETSIGTYPE (*handler)(int), int check_ign )
|
||||
{
|
||||
#ifndef HAVE_DOSISH_SYSTEM
|
||||
#ifdef HAVE_SIGACTION
|
||||
struct sigaction oact, nact;
|
||||
|
||||
if (check_ign) {
|
||||
/* we don't want to change an IGN handler */
|
||||
sigaction (sig, NULL, &oact );
|
||||
if (oact.sa_handler == SIG_IGN )
|
||||
return;
|
||||
}
|
||||
|
||||
nact.sa_handler = handler;
|
||||
sigemptyset (&nact.sa_mask);
|
||||
nact.sa_flags = 0;
|
||||
sigaction ( sig, &nact, NULL);
|
||||
#else
|
||||
RETSIGTYPE (*ohandler)(int);
|
||||
|
||||
ohandler = signal (sig, handler);
|
||||
if (check_ign && ohandler == SIG_IGN) {
|
||||
/* Change it back if it was already set to IGN */
|
||||
signal (sig, SIG_IGN);
|
||||
}
|
||||
#endif
|
||||
#endif /*!HAVE_DOSISH_SYSTEM*/
|
||||
}
|
||||
|
||||
static const char *
|
||||
get_signal_name( int signum )
|
||||
{
|
||||
@ -58,23 +88,20 @@ got_fatal_signal( int sig )
|
||||
raise( sig );
|
||||
caught_fatal_sig = 1;
|
||||
|
||||
gcry_control( GCRYCTL_TERM_SECMEM );
|
||||
secmem_term();
|
||||
/* better don't transtale these messages */
|
||||
write(2, "\n", 1 );
|
||||
s = log_get_name(); if( s ) write(2, s, strlen(s) );
|
||||
write(2, ": ", 2 );
|
||||
s = get_signal_name(sig); write(2, s, strlen(s) );
|
||||
write(2, " caught ... exiting\n", 21 );
|
||||
write(2, " caught ... exiting\n", 20 );
|
||||
|
||||
#ifndef HAVE_DOSISH_SYSTEM
|
||||
{ /* reset action to default action and raise signal again */
|
||||
struct sigaction nact;
|
||||
nact.sa_handler = SIG_DFL;
|
||||
sigemptyset( &nact.sa_mask );
|
||||
nact.sa_flags = 0;
|
||||
sigaction( sig, &nact, NULL);
|
||||
}
|
||||
#endif
|
||||
/* reset action to default action and raise signal again */
|
||||
init_one_signal (sig, SIG_DFL, 0);
|
||||
remove_lockfiles ();
|
||||
#ifdef __riscos__
|
||||
close_fds ();
|
||||
#endif /* __riscos__ */
|
||||
raise( sig );
|
||||
}
|
||||
|
||||
@ -85,37 +112,18 @@ got_usr_signal( int sig )
|
||||
caught_sigusr1 = 1;
|
||||
}
|
||||
|
||||
#ifndef HAVE_DOSISH_SYSTEM
|
||||
static void
|
||||
do_sigaction( int sig, struct sigaction *nact )
|
||||
{
|
||||
struct sigaction oact;
|
||||
|
||||
sigaction( sig, NULL, &oact );
|
||||
if( oact.sa_handler != SIG_IGN )
|
||||
sigaction( sig, nact, NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
init_signals()
|
||||
{
|
||||
#ifndef HAVE_DOSISH_SYSTEM
|
||||
struct sigaction nact;
|
||||
|
||||
nact.sa_handler = got_fatal_signal;
|
||||
sigemptyset( &nact.sa_mask );
|
||||
nact.sa_flags = 0;
|
||||
|
||||
do_sigaction( SIGINT, &nact );
|
||||
do_sigaction( SIGHUP, &nact );
|
||||
do_sigaction( SIGTERM, &nact );
|
||||
do_sigaction( SIGQUIT, &nact );
|
||||
do_sigaction( SIGSEGV, &nact );
|
||||
nact.sa_handler = got_usr_signal;
|
||||
sigaction( SIGUSR1, &nact, NULL );
|
||||
nact.sa_handler = SIG_IGN;
|
||||
sigaction( SIGPIPE, &nact, NULL );
|
||||
init_one_signal (SIGINT, got_fatal_signal, 1 );
|
||||
init_one_signal (SIGHUP, got_fatal_signal, 1 );
|
||||
init_one_signal (SIGTERM, got_fatal_signal, 1 );
|
||||
init_one_signal (SIGQUIT, got_fatal_signal, 1 );
|
||||
init_one_signal (SIGSEGV, got_fatal_signal, 1 );
|
||||
init_one_signal (SIGUSR1, got_usr_signal, 0 );
|
||||
init_one_signal (SIGPIPE, SIG_IGN, 0 );
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -124,6 +132,7 @@ void
|
||||
pause_on_sigusr( int which )
|
||||
{
|
||||
#ifndef HAVE_DOSISH_SYSTEM
|
||||
#ifdef HAVE_SIGPROCMASK
|
||||
sigset_t mask, oldmask;
|
||||
|
||||
assert( which == 1 );
|
||||
@ -135,6 +144,14 @@ pause_on_sigusr( int which )
|
||||
sigsuspend( &oldmask );
|
||||
caught_sigusr1 = 0;
|
||||
sigprocmask( SIG_UNBLOCK, &mask, NULL );
|
||||
#else
|
||||
assert (which == 1);
|
||||
sighold (SIGUSR1);
|
||||
while (!caught_sigusr1)
|
||||
sigpause(SIGUSR1);
|
||||
caught_sigusr1 = 0;
|
||||
sigrelse(SIGUSR1); ????
|
||||
#endif /*!HAVE_SIGPROCMASK*/
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -142,12 +159,13 @@ pause_on_sigusr( int which )
|
||||
static void
|
||||
do_block( int block )
|
||||
{
|
||||
#ifndef HAVE_DOSISH_SYSTEM
|
||||
#ifndef HAVE_DOSISH_SYSTEM
|
||||
static int is_blocked;
|
||||
#ifdef HAVE_SIGPROCMASK
|
||||
static sigset_t oldmask;
|
||||
|
||||
if( block ) {
|
||||
sigset_t newmask;
|
||||
sigset_t newmask;
|
||||
|
||||
if( is_blocked )
|
||||
log_bug("signals are already blocked\n");
|
||||
@ -161,7 +179,28 @@ do_block( int block )
|
||||
sigprocmask( SIG_SETMASK, &oldmask, NULL );
|
||||
is_blocked = 0;
|
||||
}
|
||||
#endif /*HAVE_DOSISH_SYSTEM*/
|
||||
#else /*!HAVE_SIGPROCMASK*/
|
||||
static void (*disposition[MAXSIG])();
|
||||
int sig;
|
||||
|
||||
if( block ) {
|
||||
if( is_blocked )
|
||||
log_bug("signals are already blocked\n");
|
||||
for (sig=1; sig < MAXSIG; sig++) {
|
||||
disposition[sig] = sigset (sig, SIG_HOLD);
|
||||
}
|
||||
is_blocked = 1;
|
||||
}
|
||||
else {
|
||||
if( !is_blocked )
|
||||
log_bug("signals are not blocked\n");
|
||||
for (sig=1; sig < MAXSIG; sig++) {
|
||||
sigset (sig, disposition[sig]);
|
||||
}
|
||||
is_blocked = 0;
|
||||
}
|
||||
#endif /*!HAVE_SIGPROCMASK*/
|
||||
#endif /*HAVE_DOSISH_SYSTEM*/
|
||||
}
|
||||
|
||||
|
||||
@ -176,4 +215,3 @@ unblock_all_signals()
|
||||
{
|
||||
do_block(0);
|
||||
}
|
||||
|
||||
|
133
g10/skclist.c
133
g10/skclist.c
@ -1,5 +1,5 @@
|
||||
/* skclist.c
|
||||
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
|
||||
* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
@ -25,14 +25,14 @@
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <gcrypt.h>
|
||||
#include "options.h"
|
||||
#include "packet.h"
|
||||
#include "errors.h"
|
||||
#include "keydb.h"
|
||||
#include "memory.h"
|
||||
#include "util.h"
|
||||
#include "i18n.h"
|
||||
#include "main.h"
|
||||
#include "cipher.h"
|
||||
|
||||
|
||||
void
|
||||
@ -43,14 +43,66 @@ release_sk_list( SK_LIST sk_list )
|
||||
for( ; sk_list; sk_list = sk_rover ) {
|
||||
sk_rover = sk_list->next;
|
||||
free_secret_key( sk_list->sk );
|
||||
gcry_free( sk_list );
|
||||
m_free( sk_list );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Check that we are only using keys which don't have
|
||||
* the string "(insecure!)" or "not secure" or "do not use"
|
||||
* in one of the user ids
|
||||
*/
|
||||
static int
|
||||
is_insecure( PKT_secret_key *sk )
|
||||
{
|
||||
u32 keyid[2];
|
||||
KBNODE node = NULL, u;
|
||||
int insecure = 0;
|
||||
|
||||
keyid_from_sk( sk, keyid );
|
||||
node = get_pubkeyblock( keyid );
|
||||
for ( u = node; u; u = u->next ) {
|
||||
if ( u->pkt->pkttype == PKT_USER_ID ) {
|
||||
PKT_user_id *id = u->pkt->pkt.user_id;
|
||||
if ( id->attrib_data )
|
||||
continue; /* skip attribute packets */
|
||||
if ( strstr( id->name, "(insecure!)" )
|
||||
|| strstr( id->name, "not secure" )
|
||||
|| strstr( id->name, "do not use" ) ) {
|
||||
insecure = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
release_kbnode( node );
|
||||
|
||||
return insecure;
|
||||
}
|
||||
|
||||
static int
|
||||
key_present_in_sk_list(SK_LIST sk_list, PKT_secret_key *sk)
|
||||
{
|
||||
for (; sk_list; sk_list = sk_list->next) {
|
||||
if ( !cmp_secret_keys(sk_list->sk, sk) )
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
is_duplicated_entry (STRLIST list, STRLIST item)
|
||||
{
|
||||
for(; list && list != item; list = list->next) {
|
||||
if ( !strcmp (list->d, item->d) )
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
build_sk_list( STRLIST locusr, SK_LIST *ret_sk_list, int unlock,
|
||||
unsigned int use )
|
||||
build_sk_list( STRLIST locusr, SK_LIST *ret_sk_list,
|
||||
int unlock, unsigned int use )
|
||||
{
|
||||
SK_LIST sk_list = NULL;
|
||||
int rc;
|
||||
@ -58,24 +110,28 @@ build_sk_list( STRLIST locusr, SK_LIST *ret_sk_list, int unlock,
|
||||
if( !locusr ) { /* use the default one */
|
||||
PKT_secret_key *sk;
|
||||
|
||||
sk = gcry_xcalloc( 1, sizeof *sk );
|
||||
sk = m_alloc_clear( sizeof *sk );
|
||||
sk->req_usage = use;
|
||||
if( (rc = get_seckey_byname( NULL, sk, NULL, unlock, NULL )) ) {
|
||||
if( (rc = get_seckey_byname( sk, NULL, unlock )) ) {
|
||||
free_secret_key( sk ); sk = NULL;
|
||||
log_error("no default secret key: %s\n", gpg_errstr(rc) );
|
||||
log_error("no default secret key: %s\n", g10_errstr(rc) );
|
||||
}
|
||||
else if( !(rc=openpgp_pk_test_algo(sk->pubkey_algo,
|
||||
sk->pubkey_usage)) ) {
|
||||
else if( !(rc=check_pubkey_algo2(sk->pubkey_algo, use)) ) {
|
||||
SK_LIST r;
|
||||
|
||||
if( sk->version == 4 && (sk->pubkey_usage & GCRY_PK_USAGE_SIGN )
|
||||
&& sk->pubkey_algo == GCRY_PK_ELG_E ) {
|
||||
|
||||
if( sk->version == 4 && (use & PUBKEY_USAGE_SIG)
|
||||
&& sk->pubkey_algo == PUBKEY_ALGO_ELGAMAL_E ) {
|
||||
log_info("this is a PGP generated "
|
||||
"ElGamal key which is NOT secure for signatures!\n");
|
||||
free_secret_key( sk ); sk = NULL;
|
||||
}
|
||||
else if( random_is_faked() && !is_insecure( sk ) ) {
|
||||
log_info(_("key is not flagged as insecure - "
|
||||
"can't use it with the faked RNG!\n"));
|
||||
free_secret_key( sk ); sk = NULL;
|
||||
}
|
||||
else {
|
||||
r = gcry_xmalloc( sizeof *r );
|
||||
r = m_alloc( sizeof *r );
|
||||
r->sk = sk; sk = NULL;
|
||||
r->next = sk_list;
|
||||
r->mark = 0;
|
||||
@ -84,31 +140,54 @@ build_sk_list( STRLIST locusr, SK_LIST *ret_sk_list, int unlock,
|
||||
}
|
||||
else {
|
||||
free_secret_key( sk ); sk = NULL;
|
||||
log_error("invalid default secret key: %s\n", gpg_errstr(rc) );
|
||||
log_error("invalid default secret key: %s\n", g10_errstr(rc) );
|
||||
}
|
||||
}
|
||||
else {
|
||||
STRLIST locusr_orig = locusr;
|
||||
for(; locusr; locusr = locusr->next ) {
|
||||
PKT_secret_key *sk;
|
||||
|
||||
sk = gcry_xcalloc( 1, sizeof *sk );
|
||||
|
||||
rc = 0;
|
||||
/* Do an early check agains duplicated entries. However this
|
||||
* won't catch all duplicates because the user IDs may be
|
||||
* specified in different ways.
|
||||
*/
|
||||
if ( is_duplicated_entry ( locusr_orig, locusr ) ) {
|
||||
log_error(_("skipped `%s': duplicated\n"), locusr->d );
|
||||
continue;
|
||||
}
|
||||
sk = m_alloc_clear( sizeof *sk );
|
||||
sk->req_usage = use;
|
||||
if( (rc = get_seckey_byname( NULL, sk, locusr->d, unlock, NULL))) {
|
||||
if( (rc = get_seckey_byname( sk, locusr->d, 0 )) ) {
|
||||
free_secret_key( sk ); sk = NULL;
|
||||
log_error(_("skipped `%s': %s\n"), locusr->d, gpg_errstr(rc) );
|
||||
log_error(_("skipped `%s': %s\n"), locusr->d, g10_errstr(rc) );
|
||||
}
|
||||
else if( !(rc=openpgp_pk_test_algo(sk->pubkey_algo,
|
||||
sk->pubkey_usage)) ) {
|
||||
else if ( key_present_in_sk_list(sk_list, sk) == 0) {
|
||||
free_secret_key(sk); sk = NULL;
|
||||
log_info(_("skipped: secret key already present\n"));
|
||||
}
|
||||
else if ( unlock && (rc = check_secret_key( sk, 0 )) ) {
|
||||
free_secret_key( sk ); sk = NULL;
|
||||
log_error(_("skipped `%s': %s\n"), locusr->d, g10_errstr(rc) );
|
||||
}
|
||||
else if( !(rc=check_pubkey_algo2(sk->pubkey_algo, use)) ) {
|
||||
SK_LIST r;
|
||||
if( sk->version == 4 && (sk->pubkey_usage & GCRY_PK_USAGE_SIGN)
|
||||
&& sk->pubkey_algo == GCRY_PK_ELG_E ) {
|
||||
|
||||
if( sk->version == 4 && (use & PUBKEY_USAGE_SIG)
|
||||
&& sk->pubkey_algo == PUBKEY_ALGO_ELGAMAL_E ) {
|
||||
log_info(_("skipped `%s': this is a PGP generated "
|
||||
"ElGamal key which is not secure for signatures!\n"),
|
||||
locusr->d );
|
||||
free_secret_key( sk ); sk = NULL;
|
||||
}
|
||||
else if( random_is_faked() && !is_insecure( sk ) ) {
|
||||
log_info(_("key is not flagged as insecure - "
|
||||
"can't use it with the faked RNG!\n"));
|
||||
free_secret_key( sk ); sk = NULL;
|
||||
}
|
||||
else {
|
||||
r = gcry_xmalloc( sizeof *r );
|
||||
r = m_alloc( sizeof *r );
|
||||
r->sk = sk; sk = NULL;
|
||||
r->next = sk_list;
|
||||
r->mark = 0;
|
||||
@ -117,7 +196,7 @@ build_sk_list( STRLIST locusr, SK_LIST *ret_sk_list, int unlock,
|
||||
}
|
||||
else {
|
||||
free_secret_key( sk ); sk = NULL;
|
||||
log_error("skipped `%s': %s\n", locusr->d, gpg_errstr(rc) );
|
||||
log_error("skipped `%s': %s\n", locusr->d, g10_errstr(rc) );
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -125,7 +204,7 @@ build_sk_list( STRLIST locusr, SK_LIST *ret_sk_list, int unlock,
|
||||
|
||||
if( !rc && !sk_list ) {
|
||||
log_error("no valid signators\n");
|
||||
rc = GPGERR_NO_USER_ID;
|
||||
rc = G10ERR_NO_USER_ID;
|
||||
}
|
||||
|
||||
if( rc )
|
||||
|
350
g10/status.c
350
g10/status.c
@ -1,5 +1,5 @@
|
||||
/* status.c
|
||||
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
|
||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
@ -24,11 +24,13 @@
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#ifdef USE_SHM_COPROCESSING
|
||||
#ifdef USE_CAPABILITIES
|
||||
#include <sys/capability.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_IPC_H
|
||||
#include <sys/types.h>
|
||||
#include <sys/ipc.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_SHM_H
|
||||
@ -38,16 +40,20 @@
|
||||
#include <sys/mman.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <gcrypt.h>
|
||||
#include "util.h"
|
||||
#include "status.h"
|
||||
#include "ttyio.h"
|
||||
#include "options.h"
|
||||
#include "main.h"
|
||||
#include "i18n.h"
|
||||
#include "cipher.h" /* for progress functions */
|
||||
|
||||
#define CONTROL_D ('D' - 'A' + 1)
|
||||
|
||||
|
||||
|
||||
static FILE *statusfp;
|
||||
|
||||
static int fd = -1;
|
||||
#ifdef USE_SHM_COPROCESSING
|
||||
static int shm_id = -1;
|
||||
static volatile char *shm_area;
|
||||
@ -68,26 +74,118 @@ progress_cb ( void *ctx, int c )
|
||||
write_status_text ( STATUS_PROGRESS, buf );
|
||||
}
|
||||
|
||||
static const char *
|
||||
get_status_string ( int no )
|
||||
{
|
||||
const char *s;
|
||||
|
||||
switch( no ) {
|
||||
case STATUS_ENTER : s = "ENTER"; break;
|
||||
case STATUS_LEAVE : s = "LEAVE"; break;
|
||||
case STATUS_ABORT : s = "ABORT"; break;
|
||||
case STATUS_GOODSIG: s = "GOODSIG"; break;
|
||||
case STATUS_KEYEXPIRED: s = "KEYEXPIRED"; break;
|
||||
case STATUS_KEYREVOKED: s = "KEYREVOKED"; break;
|
||||
case STATUS_BADSIG : s = "BADSIG"; break;
|
||||
case STATUS_ERRSIG : s = "ERRSIG"; break;
|
||||
case STATUS_BADARMOR : s = "BADARMOR"; break;
|
||||
case STATUS_RSA_OR_IDEA : s= "RSA_OR_IDEA"; break;
|
||||
case STATUS_TRUST_UNDEFINED: s = "TRUST_UNDEFINED"; break;
|
||||
case STATUS_TRUST_NEVER : s = "TRUST_NEVER"; break;
|
||||
case STATUS_TRUST_MARGINAL : s = "TRUST_MARGINAL"; break;
|
||||
case STATUS_TRUST_FULLY : s = "TRUST_FULLY"; break;
|
||||
case STATUS_TRUST_ULTIMATE : s = "TRUST_ULTIMATE"; break;
|
||||
case STATUS_GET_BOOL : s = "GET_BOOL"; break;
|
||||
case STATUS_GET_LINE : s = "GET_LINE"; break;
|
||||
case STATUS_GET_HIDDEN : s = "GET_HIDDEN"; break;
|
||||
case STATUS_GOT_IT : s = "GOT_IT"; break;
|
||||
case STATUS_SHM_INFO : s = "SHM_INFO"; break;
|
||||
case STATUS_SHM_GET : s = "SHM_GET"; break;
|
||||
case STATUS_SHM_GET_BOOL : s = "SHM_GET_BOOL"; break;
|
||||
case STATUS_SHM_GET_HIDDEN : s = "SHM_GET_HIDDEN"; break;
|
||||
case STATUS_NEED_PASSPHRASE: s = "NEED_PASSPHRASE"; break;
|
||||
case STATUS_VALIDSIG : s = "VALIDSIG"; break;
|
||||
case STATUS_SIG_ID : s = "SIG_ID"; break;
|
||||
case STATUS_ENC_TO : s = "ENC_TO"; break;
|
||||
case STATUS_NODATA : s = "NODATA"; break;
|
||||
case STATUS_BAD_PASSPHRASE : s = "BAD_PASSPHRASE"; break;
|
||||
case STATUS_NO_PUBKEY : s = "NO_PUBKEY"; break;
|
||||
case STATUS_NO_SECKEY : s = "NO_SECKEY"; break;
|
||||
case STATUS_NEED_PASSPHRASE_SYM: s = "NEED_PASSPHRASE_SYM"; break;
|
||||
case STATUS_DECRYPTION_FAILED: s = "DECRYPTION_FAILED"; break;
|
||||
case STATUS_DECRYPTION_OKAY: s = "DECRYPTION_OKAY"; break;
|
||||
case STATUS_MISSING_PASSPHRASE: s = "MISSING_PASSPHRASE"; break;
|
||||
case STATUS_GOOD_PASSPHRASE : s = "GOOD_PASSPHRASE"; break;
|
||||
case STATUS_GOODMDC : s = "GOODMDC"; break;
|
||||
case STATUS_BADMDC : s = "BADMDC"; break;
|
||||
case STATUS_ERRMDC : s = "ERRMDC"; break;
|
||||
case STATUS_IMPORTED : s = "IMPORTED"; break;
|
||||
case STATUS_IMPORT_RES : s = "IMPORT_RES"; break;
|
||||
case STATUS_FILE_START : s = "FILE_START"; break;
|
||||
case STATUS_FILE_DONE : s = "FILE_DONE"; break;
|
||||
case STATUS_FILE_ERROR : s = "FILE_ERROR"; break;
|
||||
case STATUS_BEGIN_DECRYPTION:s = "BEGIN_DECRYPTION"; break;
|
||||
case STATUS_END_DECRYPTION : s = "END_DECRYPTION"; break;
|
||||
case STATUS_BEGIN_ENCRYPTION:s = "BEGIN_ENCRYPTION"; break;
|
||||
case STATUS_END_ENCRYPTION : s = "END_ENCRYPTION"; break;
|
||||
case STATUS_DELETE_PROBLEM : s = "DELETE_PROBLEM"; break;
|
||||
case STATUS_PROGRESS : s = "PROGRESS"; break;
|
||||
case STATUS_SIG_CREATED : s = "SIG_CREATED"; break;
|
||||
case STATUS_SESSION_KEY : s = "SESSION_KEY"; break;
|
||||
case STATUS_NOTATION_NAME : s = "NOTATION_NAME" ; break;
|
||||
case STATUS_NOTATION_DATA : s = "NOTATION_DATA" ; break;
|
||||
case STATUS_POLICY_URL : s = "POLICY_URL" ; break;
|
||||
case STATUS_BEGIN_STREAM : s = "BEGIN_STREAM"; break;
|
||||
case STATUS_END_STREAM : s = "END_STREAM"; break;
|
||||
case STATUS_KEY_CREATED : s = "KEY_CREATED"; break;
|
||||
case STATUS_USERID_HINT : s = "USERID_HINT"; break;
|
||||
case STATUS_UNEXPECTED : s = "UNEXPECTED"; break;
|
||||
case STATUS_INV_RECP : s = "INV_RECP"; break;
|
||||
case STATUS_NO_RECP : s = "NO_RECP"; break;
|
||||
case STATUS_ALREADY_SIGNED : s = "ALREADY_SIGNED"; break;
|
||||
case STATUS_SIGEXPIRED : s = "SIGEXPIRED deprecated-use-keyexpired-instead"; break;
|
||||
case STATUS_EXPSIG : s = "EXPSIG"; break;
|
||||
case STATUS_EXPKEYSIG : s = "EXPKEYSIG"; break;
|
||||
case STATUS_ATTRIBUTE : s = "ATTRIBUTE"; break;
|
||||
default: s = "?"; break;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
void
|
||||
set_status_fd ( int newfd )
|
||||
set_status_fd ( int fd )
|
||||
{
|
||||
fd = newfd;
|
||||
if ( fd != -1 ) {
|
||||
#warning fixme - progress functions
|
||||
/* Has to be fixed in libgcrypt */
|
||||
#if 0
|
||||
register_primegen_progress ( progress_cb, "primegen" );
|
||||
register_pk_dsa_progress ( progress_cb, "pk_dsa" );
|
||||
register_pk_elg_progress ( progress_cb, "pk_elg" );
|
||||
#endif
|
||||
static int last_fd = -1;
|
||||
|
||||
if ( fd != -1 && last_fd == fd )
|
||||
return;
|
||||
|
||||
if ( statusfp && statusfp != stdout && statusfp != stderr )
|
||||
fclose (statusfp);
|
||||
statusfp = NULL;
|
||||
if ( fd == -1 )
|
||||
return;
|
||||
|
||||
if( fd == 1 )
|
||||
statusfp = stdout;
|
||||
else if( fd == 2 )
|
||||
statusfp = stderr;
|
||||
else
|
||||
statusfp = fdopen( fd, "w" );
|
||||
if( !statusfp ) {
|
||||
log_fatal("can't open fd %d for status output: %s\n",
|
||||
fd, strerror(errno));
|
||||
}
|
||||
last_fd = fd;
|
||||
register_primegen_progress ( progress_cb, "primegen" );
|
||||
register_pk_dsa_progress ( progress_cb, "pk_dsa" );
|
||||
register_pk_elg_progress ( progress_cb, "pk_elg" );
|
||||
}
|
||||
|
||||
int
|
||||
is_status_enabled()
|
||||
{
|
||||
return fd != -1;
|
||||
return !!statusfp;
|
||||
}
|
||||
|
||||
void
|
||||
@ -99,77 +197,97 @@ write_status ( int no )
|
||||
void
|
||||
write_status_text ( int no, const char *text)
|
||||
{
|
||||
const char *s;
|
||||
|
||||
if( fd == -1 )
|
||||
if( !statusfp )
|
||||
return; /* not enabled */
|
||||
|
||||
switch( no ) {
|
||||
case STATUS_ENTER : s = "ENTER\n"; break;
|
||||
case STATUS_LEAVE : s = "LEAVE\n"; break;
|
||||
case STATUS_ABORT : s = "ABORT\n"; break;
|
||||
case STATUS_GOODSIG: s = "GOODSIG\n"; break;
|
||||
case STATUS_SIGEXPIRED: s = "SIGEXPIRED\n"; break;
|
||||
case STATUS_KEYREVOKED: s = "KEYREVOKED\n"; break;
|
||||
case STATUS_BADSIG : s = "BADSIG\n"; break;
|
||||
case STATUS_ERRSIG : s = "ERRSIG\n"; break;
|
||||
case STATUS_BADARMOR : s = "BADARMOR\n"; break;
|
||||
case STATUS_RSA_OR_IDEA : s= "RSA_OR_IDEA\n"; break;
|
||||
case STATUS_TRUST_UNDEFINED: s = "TRUST_UNDEFINED\n"; break;
|
||||
case STATUS_TRUST_NEVER : s = "TRUST_NEVER\n"; break;
|
||||
case STATUS_TRUST_MARGINAL : s = "TRUST_MARGINAL\n"; break;
|
||||
case STATUS_TRUST_FULLY : s = "TRUST_FULLY\n"; break;
|
||||
case STATUS_TRUST_ULTIMATE : s = "TRUST_ULTIMATE\n"; break;
|
||||
case STATUS_GET_BOOL : s = "GET_BOOL\n"; break;
|
||||
case STATUS_GET_LINE : s = "GET_LINE\n"; break;
|
||||
case STATUS_GET_HIDDEN : s = "GET_HIDDEN\n"; break;
|
||||
case STATUS_GOT_IT : s = "GOT_IT\n"; break;
|
||||
case STATUS_SHM_INFO : s = "SHM_INFO\n"; break;
|
||||
case STATUS_SHM_GET : s = "SHM_GET\n"; break;
|
||||
case STATUS_SHM_GET_BOOL : s = "SHM_GET_BOOL\n"; break;
|
||||
case STATUS_SHM_GET_HIDDEN : s = "SHM_GET_HIDDEN\n"; break;
|
||||
case STATUS_NEED_PASSPHRASE: s = "NEED_PASSPHRASE\n"; break;
|
||||
case STATUS_VALIDSIG : s = "VALIDSIG\n"; break;
|
||||
case STATUS_SIG_ID : s = "SIG_ID\n"; break;
|
||||
case STATUS_ENC_TO : s = "ENC_TO\n"; break;
|
||||
case STATUS_NODATA : s = "NODATA\n"; break;
|
||||
case STATUS_BAD_PASSPHRASE : s = "BAD_PASSPHRASE\n"; break;
|
||||
case STATUS_NO_PUBKEY : s = "NO_PUBKEY\n"; break;
|
||||
case STATUS_NO_SECKEY : s = "NO_SECKEY\n"; break;
|
||||
case STATUS_NEED_PASSPHRASE_SYM: s = "NEED_PASSPHRASE_SYM\n"; break;
|
||||
case STATUS_DECRYPTION_FAILED: s = "DECRYPTION_FAILED\n"; break;
|
||||
case STATUS_DECRYPTION_OKAY: s = "DECRYPTION_OKAY\n"; break;
|
||||
case STATUS_MISSING_PASSPHRASE: s = "MISSING_PASSPHRASE\n"; break;
|
||||
case STATUS_GOOD_PASSPHRASE : s = "GOOD_PASSPHRASE\n"; break;
|
||||
case STATUS_GOODMDC : s = "GOODMDC\n"; break;
|
||||
case STATUS_BADMDC : s = "BADMDC\n"; break;
|
||||
case STATUS_ERRMDC : s = "ERRMDC\n"; break;
|
||||
case STATUS_IMPORTED : s = "IMPORTED\n"; break;
|
||||
case STATUS_IMPORT_RES : s = "IMPORT_RES\n"; break;
|
||||
case STATUS_FILE_START : s = "FILE_START\n"; break;
|
||||
case STATUS_FILE_DONE : s = "FILE_DONE\n"; break;
|
||||
case STATUS_FILE_ERROR : s = "FILE_ERROR\n"; break;
|
||||
case STATUS_BEGIN_DECRYPTION:s = "BEGIN_DECRYPTION\n"; break;
|
||||
case STATUS_END_DECRYPTION : s = "END_DECRYPTION\n"; break;
|
||||
case STATUS_BEGIN_ENCRYPTION:s = "BEGIN_ENCRYPTION\n"; break;
|
||||
case STATUS_END_ENCRYPTION : s = "END_ENCRYPTION\n"; break;
|
||||
case STATUS_DELETE_PROBLEM : s = "DELETE_PROBLEM\n"; break;
|
||||
case STATUS_PROGRESS : s = "PROGRESS\n"; break;
|
||||
case STATUS_SIG_CREATED : s = "SIG_CREATED\n"; break;
|
||||
default: s = "?\n"; break;
|
||||
fputs ( "[GNUPG:] ", statusfp );
|
||||
fputs ( get_status_string (no), statusfp );
|
||||
if( text ) {
|
||||
putc ( ' ', statusfp );
|
||||
for (; *text; text++) {
|
||||
if (*text == '\n')
|
||||
fputs ( "\\n", statusfp );
|
||||
else if (*text == '\r')
|
||||
fputs ( "\\r", statusfp );
|
||||
else
|
||||
putc ( *(const byte *)text, statusfp );
|
||||
}
|
||||
}
|
||||
putc ('\n',statusfp);
|
||||
fflush (statusfp);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Write a status line with a buffer using %XX escapes. If WRAP is >
|
||||
* 0 wrap the line after this length. If STRING is not NULL it will
|
||||
* be prepended to the buffer, no escaping is done for string.
|
||||
* A wrap of -1 forces spaces not to be encoded as %20.
|
||||
*/
|
||||
void
|
||||
write_status_text_and_buffer ( int no, const char *string,
|
||||
const char *buffer, size_t len, int wrap )
|
||||
{
|
||||
const char *s, *text;
|
||||
int esc, first;
|
||||
int lower_limit = ' ';
|
||||
size_t n, count, dowrap;
|
||||
|
||||
if( !statusfp )
|
||||
return; /* not enabled */
|
||||
|
||||
if (wrap == -1) {
|
||||
lower_limit--;
|
||||
wrap = 0;
|
||||
}
|
||||
|
||||
write( fd, "[GNUPG:] ", 9 );
|
||||
if( text ) {
|
||||
write( fd, s, strlen(s)-1 );
|
||||
write( fd, " ", 1 );
|
||||
write( fd, text, strlen(text) );
|
||||
write( fd, "\n", 1 );
|
||||
}
|
||||
else
|
||||
write( fd, s, strlen(s) );
|
||||
text = get_status_string (no);
|
||||
count = dowrap = first = 1;
|
||||
do {
|
||||
if (dowrap) {
|
||||
fprintf (statusfp, "[GNUPG:] %s ", text );
|
||||
count = dowrap = 0;
|
||||
if (first && string) {
|
||||
fputs (string, statusfp);
|
||||
count += strlen (string);
|
||||
}
|
||||
first = 0;
|
||||
}
|
||||
for (esc=0, s=buffer, n=len; n && !esc; s++, n-- ) {
|
||||
if ( *s == '%' || *(const byte*)s <= lower_limit
|
||||
|| *(const byte*)s == 127 )
|
||||
esc = 1;
|
||||
if ( wrap && ++count > wrap ) {
|
||||
dowrap=1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (esc) {
|
||||
s--; n++;
|
||||
}
|
||||
if (s != buffer)
|
||||
fwrite (buffer, s-buffer, 1, statusfp );
|
||||
if ( esc ) {
|
||||
fprintf (statusfp, "%%%02X", *(const byte*)s );
|
||||
s++; n--;
|
||||
}
|
||||
buffer = s;
|
||||
len = n;
|
||||
if ( dowrap && len )
|
||||
putc ( '\n', statusfp );
|
||||
} while ( len );
|
||||
|
||||
putc ('\n',statusfp);
|
||||
fflush (statusfp);
|
||||
}
|
||||
|
||||
void
|
||||
write_status_buffer ( int no, const char *buffer, size_t len, int wrap )
|
||||
{
|
||||
write_status_text_and_buffer (no, NULL, buffer, len, wrap);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef USE_SHM_COPROCESSING
|
||||
|
||||
@ -333,7 +451,7 @@ do_shm_get( const char *keyword, int hidden, int bool )
|
||||
if( bool )
|
||||
return p[0]? "" : NULL;
|
||||
|
||||
string = hidden? gcry_xmalloc_secure( n+1 ) : gcry_xmalloc( n+1 );
|
||||
string = hidden? m_alloc_secure( n+1 ) : m_alloc( n+1 );
|
||||
memcpy(string, p, n );
|
||||
string[n] = 0; /* make sure it is a string */
|
||||
if( hidden ) /* invalidate the memory */
|
||||
@ -344,6 +462,32 @@ do_shm_get( const char *keyword, int hidden, int bool )
|
||||
|
||||
#endif /* USE_SHM_COPROCESSING */
|
||||
|
||||
static int
|
||||
myread(int fd, void *buf, size_t count)
|
||||
{
|
||||
int rc;
|
||||
do {
|
||||
rc = read( fd, buf, count );
|
||||
} while ( rc == -1 && errno == EINTR );
|
||||
if ( !rc && count ) {
|
||||
static int eof_emmited=0;
|
||||
if ( eof_emmited < 3 ) {
|
||||
*(char*)buf = CONTROL_D;
|
||||
rc = 1;
|
||||
eof_emmited++;
|
||||
}
|
||||
else { /* Ctrl-D not caught - do something reasonable */
|
||||
#ifdef HAVE_DOSISH_SYSTEM
|
||||
raise (SIGINT); /* nothing to hangup under DOS */
|
||||
#else
|
||||
raise (SIGHUP); /* no more input data */
|
||||
#endif
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/****************
|
||||
* Request a string from the client over the command-fd
|
||||
@ -362,15 +506,21 @@ do_get_from_fd( const char *keyword, int hidden, int bool )
|
||||
if( i >= len-1 ) {
|
||||
char *save = string;
|
||||
len += 100;
|
||||
string = hidden? gcry_xmalloc_secure ( len ) : gcry_malloc ( len );
|
||||
string = hidden? m_alloc_secure ( len ) : m_alloc ( len );
|
||||
if( save )
|
||||
memcpy(string, save, i );
|
||||
else
|
||||
i=0;
|
||||
}
|
||||
/* Hmmm: why not use our read_line function here */
|
||||
if( read( opt.command_fd, string+i, 1) != 1 || string[i] == '\n' )
|
||||
break;
|
||||
if( myread( opt.command_fd, string+i, 1) != 1 || string[i] == '\n' )
|
||||
break;
|
||||
else if ( string[i] == CONTROL_D ) {
|
||||
/* found ETX - cancel the line and return a sole ETX */
|
||||
string[0] = CONTROL_D;
|
||||
i=1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
string[i] = 0;
|
||||
|
||||
@ -396,6 +546,23 @@ cpr_enabled()
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *
|
||||
cpr_get_no_help( const char *keyword, const char *prompt )
|
||||
{
|
||||
char *p;
|
||||
|
||||
if( opt.command_fd != -1 )
|
||||
return do_get_from_fd ( keyword, 0, 0 );
|
||||
#ifdef USE_SHM_COPROCESSING
|
||||
if( opt.shm_coprocess )
|
||||
return do_shm_get( keyword, 0, 0 );
|
||||
#endif
|
||||
for(;;) {
|
||||
p = tty_get( prompt );
|
||||
return p;
|
||||
}
|
||||
}
|
||||
|
||||
char *
|
||||
cpr_get( const char *keyword, const char *prompt )
|
||||
{
|
||||
@ -410,7 +577,7 @@ cpr_get( const char *keyword, const char *prompt )
|
||||
for(;;) {
|
||||
p = tty_get( prompt );
|
||||
if( *p=='?' && !p[1] && !(keyword && !*keyword)) {
|
||||
gcry_free(p);
|
||||
m_free(p);
|
||||
display_online_help( keyword );
|
||||
}
|
||||
else
|
||||
@ -418,6 +585,7 @@ cpr_get( const char *keyword, const char *prompt )
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
char *
|
||||
cpr_get_utf8( const char *keyword, const char *prompt )
|
||||
{
|
||||
@ -425,7 +593,7 @@ cpr_get_utf8( const char *keyword, const char *prompt )
|
||||
p = cpr_get( keyword, prompt );
|
||||
if( p ) {
|
||||
char *utf8 = native_to_utf8( p );
|
||||
gcry_free( p );
|
||||
m_free( p );
|
||||
p = utf8;
|
||||
}
|
||||
return p;
|
||||
@ -445,7 +613,7 @@ cpr_get_hidden( const char *keyword, const char *prompt )
|
||||
for(;;) {
|
||||
p = tty_get_hidden( prompt );
|
||||
if( *p == '?' && !p[1] ) {
|
||||
gcry_free(p);
|
||||
m_free(p);
|
||||
display_online_help( keyword );
|
||||
}
|
||||
else
|
||||
@ -482,13 +650,13 @@ cpr_get_answer_is_yes( const char *keyword, const char *prompt )
|
||||
p = tty_get( prompt );
|
||||
trim_spaces(p); /* it is okay to do this here */
|
||||
if( *p == '?' && !p[1] ) {
|
||||
gcry_free(p);
|
||||
m_free(p);
|
||||
display_online_help( keyword );
|
||||
}
|
||||
else {
|
||||
tty_kill_prompt();
|
||||
yes = answer_is_yes(p);
|
||||
gcry_free(p);
|
||||
m_free(p);
|
||||
return yes;
|
||||
}
|
||||
}
|
||||
@ -510,13 +678,13 @@ cpr_get_answer_yes_no_quit( const char *keyword, const char *prompt )
|
||||
p = tty_get( prompt );
|
||||
trim_spaces(p); /* it is okay to do this here */
|
||||
if( *p == '?' && !p[1] ) {
|
||||
gcry_free(p);
|
||||
m_free(p);
|
||||
display_online_help( keyword );
|
||||
}
|
||||
else {
|
||||
tty_kill_prompt();
|
||||
yes = answer_is_yes_no_quit(p);
|
||||
gcry_free(p);
|
||||
m_free(p);
|
||||
return yes;
|
||||
}
|
||||
}
|
||||
|
31
g10/status.h
31
g10/status.h
@ -1,5 +1,5 @@
|
||||
/* status.h
|
||||
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
|
||||
* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
@ -17,8 +17,8 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifndef GPG_STATUS_H
|
||||
#define GPG_STATUS_H
|
||||
#ifndef G10_STATUS_H
|
||||
#define G10_STATUS_H
|
||||
|
||||
|
||||
#define STATUS_ENTER 1
|
||||
@ -33,7 +33,7 @@
|
||||
#define STATUS_BADARMOR 7
|
||||
|
||||
#define STATUS_RSA_OR_IDEA 8
|
||||
#define STATUS_SIGEXPIRED 9
|
||||
#define STATUS_KEYEXPIRED 9
|
||||
#define STATUS_KEYREVOKED 10
|
||||
|
||||
#define STATUS_TRUST_UNDEFINED 11
|
||||
@ -81,12 +81,32 @@
|
||||
#define STATUS_GOT_IT 49
|
||||
#define STATUS_PROGRESS 50
|
||||
#define STATUS_SIG_CREATED 51
|
||||
#define STATUS_SESSION_KEY 52
|
||||
#define STATUS_NOTATION_NAME 53
|
||||
#define STATUS_NOTATION_DATA 54
|
||||
#define STATUS_POLICY_URL 55
|
||||
#define STATUS_BEGIN_STREAM 56
|
||||
#define STATUS_END_STREAM 57
|
||||
#define STATUS_KEY_CREATED 58
|
||||
#define STATUS_USERID_HINT 59
|
||||
#define STATUS_UNEXPECTED 60
|
||||
#define STATUS_INV_RECP 61
|
||||
#define STATUS_NO_RECP 62
|
||||
#define STATUS_ALREADY_SIGNED 63
|
||||
#define STATUS_SIGEXPIRED 64
|
||||
#define STATUS_EXPSIG 65
|
||||
#define STATUS_EXPKEYSIG 66
|
||||
#define STATUS_ATTRIBUTE 67
|
||||
|
||||
/*-- status.c --*/
|
||||
void set_status_fd ( int fd );
|
||||
int is_status_enabled ( void );
|
||||
void write_status ( int no );
|
||||
void write_status_text ( int no, const char *text );
|
||||
void write_status_buffer ( int no,
|
||||
const char *buffer, size_t len, int wrap );
|
||||
void write_status_text_and_buffer ( int no, const char *text,
|
||||
const char *buffer, size_t len, int wrap );
|
||||
|
||||
#ifdef USE_SHM_COPROCESSING
|
||||
void init_shm_coprocessing ( ulong requested_shm_size, int lock_mem );
|
||||
@ -94,6 +114,7 @@ void write_status_text ( int no, const char *text );
|
||||
|
||||
int cpr_enabled(void);
|
||||
char *cpr_get( const char *keyword, const char *prompt );
|
||||
char *cpr_get_no_help( const char *keyword, const char *prompt );
|
||||
char *cpr_get_utf8( const char *keyword, const char *prompt );
|
||||
char *cpr_get_hidden( const char *keyword, const char *prompt );
|
||||
void cpr_kill_prompt(void);
|
||||
@ -101,4 +122,4 @@ int cpr_get_answer_is_yes( const char *keyword, const char *prompt );
|
||||
int cpr_get_answer_yes_no_quit( const char *keyword, const char *prompt );
|
||||
|
||||
|
||||
#endif /*GPG_STATUS_H*/
|
||||
#endif /*G10_STATUS_H*/
|
||||
|
411
g10/tdbdump.c
411
g10/tdbdump.c
@ -1,5 +1,5 @@
|
||||
/* tdbdump.c
|
||||
* Copyright (C) 1999, 2000 Free Software Foundation, Inc.
|
||||
* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
@ -33,7 +33,7 @@
|
||||
#include "errors.h"
|
||||
#include "iobuf.h"
|
||||
#include "keydb.h"
|
||||
#include <gcrypt.h>
|
||||
#include "memory.h"
|
||||
#include "util.h"
|
||||
#include "trustdb.h"
|
||||
#include "options.h"
|
||||
@ -46,22 +46,7 @@
|
||||
#define HEXTOBIN(x) ( (x) >= '0' && (x) <= '9' ? ((x)-'0') : \
|
||||
(x) >= 'A' && (x) <= 'F' ? ((x)-'A'+10) : ((x)-'a'+10))
|
||||
|
||||
/****************
|
||||
* Read a record but die if it does not exist
|
||||
* fixme: duplicate: remove it
|
||||
*/
|
||||
#if 0
|
||||
static void
|
||||
read_record( ulong recno, TRUSTREC *rec, int rectype )
|
||||
{
|
||||
int rc = tdbio_read_record( recno, rec, rectype );
|
||||
if( !rc )
|
||||
return;
|
||||
log_error(_("trust record %lu, req type %d: read failed: %s\n"),
|
||||
recno, rectype, gpg_errstr(rc) );
|
||||
tdbio_invalid();
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************
|
||||
* Wirte a record but die on error
|
||||
*/
|
||||
@ -72,263 +57,13 @@ write_record( TRUSTREC *rec )
|
||||
if( !rc )
|
||||
return;
|
||||
log_error(_("trust record %lu, type %d: write failed: %s\n"),
|
||||
rec->recnum, rec->rectype, gpg_errstr(rc) );
|
||||
rec->recnum, rec->rectype, g10_errstr(rc) );
|
||||
tdbio_invalid();
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
* sync the db
|
||||
*/
|
||||
static void
|
||||
do_sync(void)
|
||||
{
|
||||
int rc = tdbio_sync();
|
||||
if( !rc )
|
||||
return;
|
||||
log_error(_("trustdb: sync failed: %s\n"), gpg_errstr(rc) );
|
||||
gpg_exit(2);
|
||||
}
|
||||
|
||||
#if 0
|
||||
static int
|
||||
print_sigflags( FILE *fp, unsigned flags )
|
||||
{
|
||||
if( flags & SIGF_CHECKED ) {
|
||||
fprintf(fp,"%c%c%c",
|
||||
(flags & SIGF_VALID) ? 'V':'-',
|
||||
(flags & SIGF_EXPIRED) ? 'E':'-',
|
||||
(flags & SIGF_REVOKED) ? 'R':'-');
|
||||
}
|
||||
else if( flags & SIGF_NOPUBKEY)
|
||||
fputs("?--", fp);
|
||||
else
|
||||
fputs("---", fp);
|
||||
return 3;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/****************
|
||||
* Walk through the signatures of a public key.
|
||||
* The caller must provide a context structure, with all fields set
|
||||
* to zero, but the local_id field set to the requested key;
|
||||
* This function does not change this field. On return the context
|
||||
* is filled with the local-id of the signature and the signature flag.
|
||||
* No fields should be changed (clearing all fields and setting
|
||||
* pubkeyid is okay to continue with an other pubkey)
|
||||
* Returns: 0 - okay, -1 for eof (no more sigs) or any other errorcode
|
||||
* FIXME: Do we really need this large and complicated function?
|
||||
*/
|
||||
#if 0
|
||||
static int
|
||||
walk_sigrecs( SIGREC_CONTEXT *c )
|
||||
{
|
||||
TRUSTREC *r;
|
||||
ulong rnum;
|
||||
|
||||
if( c->ctl.eof )
|
||||
return -1;
|
||||
r = &c->ctl.rec;
|
||||
if( !c->ctl.init_done ) {
|
||||
c->ctl.init_done = 1;
|
||||
read_record( c->lid, r, 0 );
|
||||
if( r->rectype != RECTYPE_DIR ) {
|
||||
c->ctl.eof = 1;
|
||||
return -1; /* return eof */
|
||||
}
|
||||
c->ctl.nextuid = r->r.dir.uidlist;
|
||||
/* force a read */
|
||||
c->ctl.index = SIGS_PER_RECORD;
|
||||
r->r.sig.next = 0;
|
||||
}
|
||||
|
||||
/* need a loop to skip over deleted sigs */
|
||||
do {
|
||||
if( c->ctl.index >= SIGS_PER_RECORD ) { /* read the record */
|
||||
rnum = r->r.sig.next;
|
||||
if( !rnum && c->ctl.nextuid ) { /* read next uid record */
|
||||
read_record( c->ctl.nextuid, r, RECTYPE_UID );
|
||||
c->ctl.nextuid = r->r.uid.next;
|
||||
rnum = r->r.uid.siglist;
|
||||
}
|
||||
if( !rnum ) {
|
||||
c->ctl.eof = 1;
|
||||
return -1; /* return eof */
|
||||
}
|
||||
read_record( rnum, r, RECTYPE_SIG );
|
||||
if( r->r.sig.lid != c->lid ) {
|
||||
log_error(_("chained sigrec %lu has a wrong owner\n"), rnum );
|
||||
c->ctl.eof = 1;
|
||||
tdbio_invalid();
|
||||
}
|
||||
c->ctl.index = 0;
|
||||
}
|
||||
} while( !r->r.sig.sig[c->ctl.index++].lid );
|
||||
|
||||
c->sig_lid = r->r.sig.sig[c->ctl.index-1].lid;
|
||||
c->sig_flag = r->r.sig.sig[c->ctl.index-1].flag;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
static int
|
||||
do_list_sigs( ulong root, ulong pk_lid, int depth,
|
||||
LOCAL_ID_TABLE lids, unsigned *lineno )
|
||||
{
|
||||
SIGREC_CONTEXT sx;
|
||||
int rc;
|
||||
u32 keyid[2];
|
||||
|
||||
memset( &sx, 0, sizeof sx );
|
||||
sx.lid = pk_lid;
|
||||
for(;;) {
|
||||
rc = walk_sigrecs( &sx ); /* should we replace it and use */
|
||||
if( rc )
|
||||
break;
|
||||
rc = keyid_from_lid( sx.sig_lid, keyid );
|
||||
if( rc ) {
|
||||
printf("%6u: %*s????????.%lu:", *lineno, depth*4, "", sx.sig_lid );
|
||||
print_sigflags( stdout, sx.sig_flag );
|
||||
putchar('\n');
|
||||
++*lineno;
|
||||
}
|
||||
else {
|
||||
printf("%6u: %*s%08lX.%lu:", *lineno, depth*4, "",
|
||||
(ulong)keyid[1], sx.sig_lid );
|
||||
print_sigflags( stdout, sx.sig_flag );
|
||||
putchar(' ');
|
||||
/* check whether we already checked this pk_lid */
|
||||
if( !qry_lid_table_flag( ultikey_table, sx.sig_lid, NULL ) ) {
|
||||
print_user_id("[ultimately trusted]", keyid);
|
||||
++*lineno;
|
||||
}
|
||||
else if( sx.sig_lid == pk_lid ) {
|
||||
printf("[self-signature]\n");
|
||||
++*lineno;
|
||||
}
|
||||
else if( sx.sig_lid == root ) {
|
||||
printf("[closed]\n");
|
||||
++*lineno;
|
||||
}
|
||||
else if( ins_lid_table_item( lids, sx.sig_lid, *lineno ) ) {
|
||||
unsigned refline;
|
||||
qry_lid_table_flag( lids, sx.sig_lid, &refline );
|
||||
printf("[see line %u]\n", refline);
|
||||
++*lineno;
|
||||
}
|
||||
else if( depth+1 >= MAX_LIST_SIGS_DEPTH ) {
|
||||
print_user_id( "[too deeply nested]", keyid );
|
||||
++*lineno;
|
||||
}
|
||||
else {
|
||||
print_user_id( "", keyid );
|
||||
++*lineno;
|
||||
rc = do_list_sigs( root, sx.sig_lid, depth+1, lids, lineno );
|
||||
if( rc )
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return rc==-1? 0 : rc;
|
||||
}
|
||||
#endif
|
||||
/****************
|
||||
* List all signatures of a public key
|
||||
*/
|
||||
static int
|
||||
list_sigs( ulong pubkey_id )
|
||||
{
|
||||
int rc=0;
|
||||
#if 0
|
||||
u32 keyid[2];
|
||||
LOCAL_ID_TABLE lids;
|
||||
unsigned lineno = 1;
|
||||
|
||||
rc = keyid_from_lid( pubkey_id, keyid );
|
||||
if( rc )
|
||||
return rc;
|
||||
printf("Signatures of %08lX.%lu ", (ulong)keyid[1], pubkey_id );
|
||||
print_user_id("", keyid);
|
||||
printf("----------------------\n");
|
||||
|
||||
lids = new_lid_table();
|
||||
rc = do_list_sigs( pubkey_id, pubkey_id, 0, lids, &lineno );
|
||||
putchar('\n');
|
||||
release_lid_table(lids);
|
||||
#endif
|
||||
return rc;
|
||||
}
|
||||
|
||||
/****************
|
||||
* List all records of a public key
|
||||
*/
|
||||
static int
|
||||
list_records( ulong lid )
|
||||
{
|
||||
int rc;
|
||||
TRUSTREC dr, ur, rec;
|
||||
ulong recno;
|
||||
|
||||
rc = tdbio_read_record( lid, &dr, RECTYPE_DIR );
|
||||
if( rc ) {
|
||||
log_error(_("lid %lu: read dir record failed: %s\n"),
|
||||
lid, gpg_errstr(rc));
|
||||
return rc;
|
||||
}
|
||||
tdbio_dump_record( &dr, stdout );
|
||||
|
||||
for( recno=dr.r.dir.keylist; recno; recno = rec.r.key.next ) {
|
||||
rc = tdbio_read_record( recno, &rec, 0 );
|
||||
if( rc ) {
|
||||
log_error(_("lid %lu: read key record failed: %s\n"),
|
||||
lid, gpg_errstr(rc));
|
||||
return rc;
|
||||
}
|
||||
tdbio_dump_record( &rec, stdout );
|
||||
}
|
||||
|
||||
for( recno=dr.r.dir.uidlist; recno; recno = ur.r.uid.next ) {
|
||||
rc = tdbio_read_record( recno, &ur, RECTYPE_UID );
|
||||
if( rc ) {
|
||||
log_error(_("lid %lu: read uid record failed: %s\n"),
|
||||
lid, gpg_errstr(rc));
|
||||
return rc;
|
||||
}
|
||||
tdbio_dump_record( &ur, stdout );
|
||||
/* preference records */
|
||||
for(recno=ur.r.uid.prefrec; recno; recno = rec.r.pref.next ) {
|
||||
rc = tdbio_read_record( recno, &rec, RECTYPE_PREF );
|
||||
if( rc ) {
|
||||
log_error(_("lid %lu: read pref record failed: %s\n"),
|
||||
lid, gpg_errstr(rc));
|
||||
return rc;
|
||||
}
|
||||
tdbio_dump_record( &rec, stdout );
|
||||
}
|
||||
/* sig records */
|
||||
for(recno=ur.r.uid.siglist; recno; recno = rec.r.sig.next ) {
|
||||
rc = tdbio_read_record( recno, &rec, RECTYPE_SIG );
|
||||
if( rc ) {
|
||||
log_error(_("lid %lu: read sig record failed: %s\n"),
|
||||
lid, gpg_errstr(rc));
|
||||
return rc;
|
||||
}
|
||||
tdbio_dump_record( &rec, stdout );
|
||||
}
|
||||
}
|
||||
|
||||
/* add cache record dump here */
|
||||
|
||||
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
* Dump the complte trustdb or only the entries of one key.
|
||||
* Dump the entire trustdb or only the entries of one key.
|
||||
*/
|
||||
void
|
||||
list_trustdb( const char *username )
|
||||
@ -336,38 +71,8 @@ list_trustdb( const char *username )
|
||||
TRUSTREC rec;
|
||||
|
||||
init_trustdb();
|
||||
|
||||
if( username && *username == '#' ) {
|
||||
int rc;
|
||||
ulong lid = atoi(username+1);
|
||||
|
||||
if( (rc = list_records( lid)) )
|
||||
log_error(_("user '%s' read problem: %s\n"),
|
||||
username, gpg_errstr(rc));
|
||||
else if( (rc = list_sigs( lid )) )
|
||||
log_error(_("user '%s' list problem: %s\n"),
|
||||
username, gpg_errstr(rc));
|
||||
}
|
||||
else if( username ) {
|
||||
PKT_public_key *pk = gcry_xcalloc( 1, sizeof *pk );
|
||||
int rc;
|
||||
|
||||
if( (rc = get_pubkey_byname( NULL, pk, username, NULL )) )
|
||||
log_error(_("user '%s' not found: %s\n"), username, gpg_errstr(rc) );
|
||||
else if( (rc=tdbio_search_dir_bypk( pk, &rec )) && rc != -1 )
|
||||
log_error(_("problem finding '%s' in trustdb: %s\n"),
|
||||
username, gpg_errstr(rc));
|
||||
else if( rc == -1 )
|
||||
log_error(_("user '%s' not in trustdb\n"), username);
|
||||
else if( (rc = list_records( pk->local_id)) )
|
||||
log_error(_("user '%s' read problem: %s\n"),
|
||||
username, gpg_errstr(rc));
|
||||
else if( (rc = list_sigs( pk->local_id )) )
|
||||
log_error(_("user '%s' list problem: %s\n"),
|
||||
username, gpg_errstr(rc));
|
||||
free_public_key( pk );
|
||||
}
|
||||
else {
|
||||
/* for now we ignore the user ID */
|
||||
if (1) {
|
||||
ulong recnum;
|
||||
int i;
|
||||
|
||||
@ -391,33 +96,22 @@ void
|
||||
export_ownertrust()
|
||||
{
|
||||
TRUSTREC rec;
|
||||
TRUSTREC rec2;
|
||||
ulong recnum;
|
||||
int i;
|
||||
byte *p;
|
||||
int rc;
|
||||
|
||||
init_trustdb();
|
||||
printf(_("# List of assigned trustvalues, created %s\n"
|
||||
"# (Use \"gpg --import-ownertrust\" to restore them)\n"),
|
||||
asctimestamp( make_timestamp() ) );
|
||||
for(recnum=0; !tdbio_read_record( recnum, &rec, 0); recnum++ ) {
|
||||
if( rec.rectype == RECTYPE_DIR ) {
|
||||
if( !rec.r.dir.keylist ) {
|
||||
log_error(_("directory record w/o primary key\n"));
|
||||
if( rec.rectype == RECTYPE_TRUST ) {
|
||||
if( !rec.r.trust.ownertrust )
|
||||
continue;
|
||||
}
|
||||
if( !rec.r.dir.ownertrust )
|
||||
continue;
|
||||
rc = tdbio_read_record( rec.r.dir.keylist, &rec2, RECTYPE_KEY);
|
||||
if( rc ) {
|
||||
log_error(_("error reading key record: %s\n"), gpg_errstr(rc));
|
||||
continue;
|
||||
}
|
||||
p = rec2.r.key.fingerprint;
|
||||
for(i=0; i < rec2.r.key.fingerprint_len; i++, p++ )
|
||||
p = rec.r.trust.fingerprint;
|
||||
for(i=0; i < 20; i++, p++ )
|
||||
printf("%02X", *p );
|
||||
printf(":%u:\n", (unsigned)rec.r.dir.ownertrust );
|
||||
printf(":%u:\n", (unsigned int)rec.r.trust.ownertrust );
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -431,7 +125,10 @@ import_ownertrust( const char *fname )
|
||||
char line[256];
|
||||
char *p;
|
||||
size_t n, fprlen;
|
||||
unsigned otrust;
|
||||
unsigned int otrust;
|
||||
byte fpr[20];
|
||||
int any = 0;
|
||||
int rc;
|
||||
|
||||
init_trustdb();
|
||||
if( !fname || (*fname == '-' && !fname[1]) ) {
|
||||
@ -446,7 +143,6 @@ import_ownertrust( const char *fname )
|
||||
|
||||
while( fgets( line, DIM(line)-1, fp ) ) {
|
||||
TRUSTREC rec;
|
||||
int rc;
|
||||
|
||||
if( !*line || *line == '#' )
|
||||
continue;
|
||||
@ -475,51 +171,52 @@ import_ownertrust( const char *fname )
|
||||
if( !otrust )
|
||||
continue; /* no otrust defined - no need to update or insert */
|
||||
/* convert the ascii fingerprint to binary */
|
||||
for(p=line, fprlen=0; *p != ':'; p += 2 )
|
||||
line[fprlen++] = HEXTOBIN(p[0]) * 16 + HEXTOBIN(p[1]);
|
||||
line[fprlen] = 0;
|
||||
|
||||
repeat:
|
||||
rc = tdbio_search_dir_byfpr( line, fprlen, 0, &rec );
|
||||
for(p=line, fprlen=0; fprlen < 20 && *p != ':'; p += 2 )
|
||||
fpr[fprlen++] = HEXTOBIN(p[0]) * 16 + HEXTOBIN(p[1]);
|
||||
while (fprlen < 20)
|
||||
fpr[fprlen++] = 0;
|
||||
|
||||
rc = tdbio_search_trust_byfpr (fpr, &rec);
|
||||
if( !rc ) { /* found: update */
|
||||
if( rec.r.dir.ownertrust )
|
||||
log_info("LID %lu: changing trust from %u to %u\n",
|
||||
rec.r.dir.lid, rec.r.dir.ownertrust, otrust );
|
||||
else
|
||||
log_info("LID %lu: setting trust to %u\n",
|
||||
rec.r.dir.lid, otrust );
|
||||
rec.r.dir.ownertrust = otrust;
|
||||
write_record( &rec );
|
||||
if (rec.r.trust.ownertrust != otrust)
|
||||
{
|
||||
if( rec.r.trust.ownertrust )
|
||||
log_info("changing ownertrust from %u to %u\n",
|
||||
rec.r.trust.ownertrust, otrust );
|
||||
else
|
||||
log_info("setting ownertrust to %u\n", otrust );
|
||||
rec.r.trust.ownertrust = otrust;
|
||||
write_record (&rec );
|
||||
any = 1;
|
||||
}
|
||||
}
|
||||
else if( rc == -1 ) { /* not found; get the key from the ring */
|
||||
PKT_public_key *pk = gcry_xcalloc( 1, sizeof *pk );
|
||||
|
||||
log_info_f(fname, _("key not in trustdb, searching ring.\n"));
|
||||
rc = get_pubkey_byfprint( pk, line, fprlen );
|
||||
if( rc )
|
||||
log_info_f(fname, _("key not in ring: %s\n"), gpg_errstr(rc));
|
||||
else {
|
||||
rc = query_trust_record( pk ); /* only as assertion */
|
||||
if( rc != -1 )
|
||||
log_error_f(fname, _("Oops: key is now in trustdb???\n"));
|
||||
else {
|
||||
rc = insert_trust_record_by_pk( pk );
|
||||
if( !rc )
|
||||
goto repeat; /* update the ownertrust */
|
||||
log_error_f(fname, _("insert trust record failed: %s\n"),
|
||||
gpg_errstr(rc) );
|
||||
}
|
||||
}
|
||||
else if( rc == -1 ) { /* not found: insert */
|
||||
log_info("inserting ownertrust of %u\n", otrust );
|
||||
memset (&rec, 0, sizeof rec);
|
||||
rec.recnum = tdbio_new_recnum ();
|
||||
rec.rectype = RECTYPE_TRUST;
|
||||
memcpy (rec.r.trust.fingerprint, fpr, 20);
|
||||
rec.r.trust.ownertrust = otrust;
|
||||
write_record (&rec );
|
||||
any = 1;
|
||||
}
|
||||
else /* error */
|
||||
log_error_f(fname, _("error finding dir record: %s\n"),
|
||||
gpg_errstr(rc));
|
||||
log_error_f(fname, _("error finding trust record: %s\n"),
|
||||
g10_errstr(rc));
|
||||
}
|
||||
if( ferror(fp) )
|
||||
log_error_f(fname, _("read error: %s\n"), strerror(errno) );
|
||||
if( !is_stdin )
|
||||
fclose(fp);
|
||||
do_sync();
|
||||
sync_trustdb();
|
||||
|
||||
if (any)
|
||||
{
|
||||
revalidation_mark ();
|
||||
rc = tdbio_sync ();
|
||||
if (rc)
|
||||
log_error (_("trustdb: sync failed: %s\n"), g10_errstr(rc) );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
941
g10/tdbio.c
941
g10/tdbio.c
File diff suppressed because it is too large
Load Diff
141
g10/tdbio.h
141
g10/tdbio.h
@ -1,5 +1,5 @@
|
||||
/* tdbio.h - Trust database I/O functions
|
||||
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
|
||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
@ -18,8 +18,8 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
#ifndef GPG_TDBIO_H
|
||||
#define GPG_TDBIO_H
|
||||
#ifndef G10_TDBIO_H
|
||||
#define G10_TDBIO_H
|
||||
|
||||
#include "host2net.h"
|
||||
|
||||
@ -35,41 +35,13 @@
|
||||
|
||||
|
||||
#define RECTYPE_VER 1
|
||||
#define RECTYPE_DIR 2
|
||||
#define RECTYPE_KEY 3
|
||||
#define RECTYPE_UID 4
|
||||
#define RECTYPE_PREF 5
|
||||
#define RECTYPE_SIG 6
|
||||
#define RECTYPE_SDIR 8
|
||||
#define RECTYPE_CACH 9
|
||||
#define RECTYPE_HTBL 10
|
||||
#define RECTYPE_HLST 11
|
||||
#define RECTYPE_TRUST 12
|
||||
#define RECTYPE_VALID 13
|
||||
#define RECTYPE_FREE 254
|
||||
|
||||
|
||||
#define DIRF_CHECKED 1 /* has been checked - bits 1,2,3 are valid */
|
||||
#define DIRF_VALID 2 /* This key is valid: There is at least */
|
||||
/* one uid with a selfsignature or an revocation */
|
||||
#define DIRF_EXPIRED 4 /* the complete key has expired */
|
||||
#define DIRF_REVOKED 8 /* the complete key has been revoked */
|
||||
#define DIRF_NEWKEYS 128 /* new keys are available: we can check the sigs */
|
||||
|
||||
#define KEYF_CHECKED 1 /* This key has been checked */
|
||||
#define KEYF_VALID 2 /* This is a valid (sub)key */
|
||||
#define KEYF_EXPIRED 4 /* this key is expired */
|
||||
#define KEYF_REVOKED 8 /* this key has been revoked */
|
||||
|
||||
#define UIDF_CHECKED 1 /* user id has been checked - other bits are valid */
|
||||
#define UIDF_VALID 2 /* this is a valid user id */
|
||||
#define UIDF_REVOKED 8 /* this user id has been revoked */
|
||||
|
||||
#define SIGF_CHECKED 1 /* signature has been checked - bits 0..6 are valid */
|
||||
#define SIGF_VALID 2 /* the signature is valid */
|
||||
#define SIGF_EXPIRED 4 /* the key of this signature has expired */
|
||||
#define SIGF_REVOKED 8 /* this signature has been revoked */
|
||||
#define SIGF_IGNORED 64 /* this signature is ignored by the system */
|
||||
#define SIGF_NOPUBKEY 128 /* there is no pubkey for this sig */
|
||||
|
||||
struct trust_record {
|
||||
int rectype;
|
||||
int mark;
|
||||
@ -78,73 +50,21 @@ struct trust_record {
|
||||
ulong recnum;
|
||||
union {
|
||||
struct { /* version record: */
|
||||
byte version; /* should be 2 */
|
||||
byte version; /* should be 3 */
|
||||
byte marginals;
|
||||
byte completes;
|
||||
byte cert_depth;
|
||||
ulong created; /* timestamp of trustdb creation */
|
||||
ulong mod_down; /* timestamp of last modification downward */
|
||||
ulong mod_up; /* timestamp of last modification upward */
|
||||
ulong keyhashtbl;
|
||||
ulong nextcheck; /* timestamp of next scheduled check */
|
||||
ulong reserved;
|
||||
ulong reserved2;
|
||||
ulong firstfree;
|
||||
ulong sdirhashtbl;
|
||||
ulong reserved3;
|
||||
ulong trusthashtbl;
|
||||
} ver;
|
||||
struct { /* free record */
|
||||
ulong next;
|
||||
} free;
|
||||
struct { /* directory record */
|
||||
ulong lid;
|
||||
ulong keylist; /* List of keys (the first is the primary key)*/
|
||||
ulong uidlist; /* list of uid records */
|
||||
ulong cacherec; /* the cache record */
|
||||
byte ownertrust;
|
||||
byte dirflags;
|
||||
byte validity; /* calculated trustlevel over all uids */
|
||||
ulong valcheck; /* timestamp of last validation check */
|
||||
ulong checkat; /* Check key when this time has been reached*/
|
||||
} dir;
|
||||
struct { /* primary public key record */
|
||||
ulong lid;
|
||||
ulong next; /* next key */
|
||||
byte keyflags;
|
||||
byte pubkey_algo;
|
||||
byte fingerprint_len;
|
||||
byte fingerprint[20];
|
||||
} key;
|
||||
struct { /* user id reord */
|
||||
ulong lid; /* point back to the directory record */
|
||||
ulong next; /* points to next user id record */
|
||||
ulong prefrec; /* recno of preference record */
|
||||
ulong siglist; /* list of valid signatures (w/o self-sig)*/
|
||||
byte uidflags;
|
||||
byte validity; /* calculated trustlevel of this uid */
|
||||
byte namehash[20]; /* ripemd hash of the username */
|
||||
} uid;
|
||||
struct { /* preference record */
|
||||
ulong lid; /* point back to the directory record */
|
||||
/* or 0 for a global pref record */
|
||||
ulong next; /* points to next pref record */
|
||||
byte data[ITEMS_PER_PREF_RECORD];
|
||||
} pref;
|
||||
struct { /* signature record */
|
||||
ulong lid;
|
||||
ulong next; /* recnno of next record or NULL for last one */
|
||||
struct {
|
||||
ulong lid; /* of pubkey record of signator (0=unused) */
|
||||
byte flag; /* SIGF_xxxxx */
|
||||
} sig[SIGS_PER_RECORD];
|
||||
} sig;
|
||||
struct {
|
||||
ulong lid;
|
||||
u32 keyid[2];
|
||||
byte pubkey_algo;
|
||||
u32 hintlist;
|
||||
} sdir;
|
||||
struct { /* cache record */
|
||||
ulong lid;
|
||||
byte blockhash[20];
|
||||
byte trustlevel; /* calculated trustlevel */
|
||||
} cache;
|
||||
struct {
|
||||
ulong item[ITEMS_PER_HTBL_RECORD];
|
||||
} htbl;
|
||||
@ -152,25 +72,21 @@ struct trust_record {
|
||||
ulong next;
|
||||
ulong rnum[ITEMS_PER_HLST_RECORD]; /* of another record */
|
||||
} hlst;
|
||||
struct {
|
||||
byte fingerprint[20];
|
||||
byte ownertrust;
|
||||
byte depth;
|
||||
ulong validlist;
|
||||
} trust;
|
||||
struct {
|
||||
byte namehash[20];
|
||||
ulong next;
|
||||
byte validity;
|
||||
} valid;
|
||||
} r;
|
||||
};
|
||||
typedef struct trust_record TRUSTREC;
|
||||
|
||||
typedef struct {
|
||||
ulong lid; /* localid */
|
||||
ulong sigrec;
|
||||
ulong sig_lid; /* returned signatures LID */
|
||||
unsigned sig_flag; /* returned signature record flag */
|
||||
struct { /* internal data */
|
||||
int init_done;
|
||||
int eof;
|
||||
TRUSTREC rec;
|
||||
ulong nextuid;
|
||||
int index;
|
||||
} ctl;
|
||||
} SIGREC_CONTEXT;
|
||||
|
||||
|
||||
/*-- tdbio.c --*/
|
||||
int tdbio_set_dbname( const char *new_dbname, int create );
|
||||
const char *tdbio_get_dbname(void);
|
||||
@ -178,8 +94,8 @@ void tdbio_dump_record( TRUSTREC *rec, FILE *fp );
|
||||
int tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected );
|
||||
int tdbio_write_record( TRUSTREC *rec );
|
||||
int tdbio_db_matches_options(void);
|
||||
ulong tdbio_read_modify_stamp( int modify_down );
|
||||
void tdbio_write_modify_stamp( int up, int down );
|
||||
ulong tdbio_read_nextcheck (void);
|
||||
int tdbio_write_nextcheck (ulong stamp);
|
||||
int tdbio_is_dirty(void);
|
||||
int tdbio_sync(void);
|
||||
int tdbio_begin_transaction(void);
|
||||
@ -187,12 +103,9 @@ int tdbio_end_transaction(void);
|
||||
int tdbio_cancel_transaction(void);
|
||||
int tdbio_delete_record( ulong recnum );
|
||||
ulong tdbio_new_recnum(void);
|
||||
int tdbio_search_dir_bypk( PKT_public_key *pk, TRUSTREC *rec );
|
||||
int tdbio_search_dir_byfpr( const byte *fingerprint, size_t fingerlen,
|
||||
int pubkey_algo, TRUSTREC *rec );
|
||||
int tdbio_search_dir( u32 *keyid, int pubkey_algo, TRUSTREC *rec );
|
||||
int tdbio_search_sdir( u32 *keyid, int pubkey_algo, TRUSTREC *rec );
|
||||
int tdbio_search_trust_byfpr(const byte *fingerprint, TRUSTREC *rec );
|
||||
int tdbio_search_trust_bypk(PKT_public_key *pk, TRUSTREC *rec );
|
||||
|
||||
void tdbio_invalid(void);
|
||||
|
||||
#endif /*GPG_TDBIO_H*/
|
||||
#endif /*G10_TDBIO_H*/
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* textfilter.c
|
||||
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
|
||||
* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
@ -25,9 +25,9 @@
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <gcrypt.h>
|
||||
#include "errors.h"
|
||||
#include "iobuf.h"
|
||||
#include "memory.h"
|
||||
#include "util.h"
|
||||
#include "filter.h"
|
||||
#include "i18n.h"
|
||||
@ -133,7 +133,7 @@ text_filter( void *opaque, int control,
|
||||
if( tfx->truncated )
|
||||
log_error(_("can't handle text lines longer than %d characters\n"),
|
||||
MAX_LINELEN );
|
||||
gcry_free( tfx->buffer );
|
||||
m_free( tfx->buffer );
|
||||
tfx->buffer = NULL;
|
||||
}
|
||||
else if( control == IOBUFCTRL_DESC )
|
||||
@ -147,7 +147,7 @@ text_filter( void *opaque, int control,
|
||||
* md is updated as required by rfc2440
|
||||
*/
|
||||
int
|
||||
copy_clearsig_text( IOBUF out, IOBUF inp, GCRY_MD_HD md,
|
||||
copy_clearsig_text( IOBUF out, IOBUF inp, MD_HANDLE md,
|
||||
int escape_dash, int escape_from, int pgp2mode )
|
||||
{
|
||||
unsigned maxlen;
|
||||
@ -175,15 +175,15 @@ copy_clearsig_text( IOBUF out, IOBUF inp, GCRY_MD_HD md,
|
||||
/* update the message digest */
|
||||
if( escape_dash ) {
|
||||
if( pending_lf ) {
|
||||
gcry_md_putc( md, '\r' );
|
||||
gcry_md_putc( md, '\n' );
|
||||
md_putc( md, '\r' );
|
||||
md_putc( md, '\n' );
|
||||
}
|
||||
gcry_md_write( md, buffer,
|
||||
md_write( md, buffer,
|
||||
len_without_trailing_chars( buffer, n,
|
||||
pgp2mode? " \r\n":" \t\r\n"));
|
||||
}
|
||||
else
|
||||
gcry_md_write( md, buffer, n );
|
||||
md_write( md, buffer, n );
|
||||
pending_lf = buffer[n-1] == '\n';
|
||||
|
||||
/* write the output */
|
||||
@ -224,7 +224,7 @@ copy_clearsig_text( IOBUF out, IOBUF inp, GCRY_MD_HD md,
|
||||
if( !pending_lf ) { /* make sure that the file ends with a LF */
|
||||
iobuf_writestr( out, LF );
|
||||
if( !escape_dash )
|
||||
gcry_md_putc( md, '\n' );
|
||||
md_putc( md, '\n' );
|
||||
}
|
||||
|
||||
if( truncated )
|
||||
|
3972
g10/trustdb.c
3972
g10/trustdb.c
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,5 @@
|
||||
/* trustdb.h - Trust database
|
||||
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
|
||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
@ -18,13 +18,13 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
#ifndef GPG_TRUSTDB_H
|
||||
#define GPG_TRUSTDB_H
|
||||
#ifndef G10_TRUSTDB_H
|
||||
#define G10_TRUSTDB_H
|
||||
|
||||
|
||||
/* Trust values must be sorted in ascending order */
|
||||
#define TRUST_MASK 15
|
||||
#define TRUST_UNKNOWN 0 /* o: not yet calculated */
|
||||
#define TRUST_UNKNOWN 0 /* o: not yet calculated/assigned */
|
||||
#define TRUST_EXPIRED 1 /* e: calculation may be invalid */
|
||||
#define TRUST_UNDEFINED 2 /* q: not enough information for calculation */
|
||||
#define TRUST_NEVER 3 /* n: never trust this pubkey */
|
||||
@ -33,43 +33,37 @@
|
||||
#define TRUST_ULTIMATE 6 /* u: ultimately trusted */
|
||||
/* trust values not covered by the mask */
|
||||
#define TRUST_FLAG_REVOKED 32 /* r: revoked */
|
||||
#define TRUST_FLAG_SUB_REVOKED 64
|
||||
#define TRUST_FLAG_SUB_REVOKED 64 /* r: revoked but for subkeys */
|
||||
#define TRUST_FLAG_DISABLED 128 /* d: key/uid disabled */
|
||||
|
||||
|
||||
#define PREFTYPE_SYM 1
|
||||
#define PREFTYPE_HASH 2
|
||||
#define PREFTYPE_COMPR 3
|
||||
|
||||
#define TRUST_FLAG_PENDING_CHECK 256 /* a check-trustdb is pending */
|
||||
|
||||
/*-- trustdb.c --*/
|
||||
void list_trust_path( const char *username );
|
||||
void register_trusted_key( const char *string );
|
||||
void check_trustdb( const char *username );
|
||||
void update_trustdb( void );
|
||||
void check_trustdb (void);
|
||||
void update_trustdb (void);
|
||||
int setup_trustdb( int level, const char *dbname );
|
||||
void init_trustdb( void );
|
||||
void sync_trustdb( void );
|
||||
int check_trust( PKT_public_key *pk, unsigned *r_trustlevel,
|
||||
const byte* nh, int (*add_fnc)(ulong), unsigned *retflgs );
|
||||
int query_trust_info( PKT_public_key *pk, const byte *nh );
|
||||
|
||||
int trust_letter( unsigned value );
|
||||
|
||||
void revalidation_mark (void);
|
||||
|
||||
unsigned int get_validity (PKT_public_key *pk, const byte *namehash);
|
||||
int get_validity_info (PKT_public_key *pk, const byte *namehash);
|
||||
|
||||
void list_trust_path( const char *username );
|
||||
|
||||
int enum_cert_paths( void **context, ulong *lid,
|
||||
unsigned *ownertrust, unsigned *validity );
|
||||
void enum_cert_paths_print( void **context, FILE *fp,
|
||||
int refresh, ulong selected_lid );
|
||||
unsigned get_ownertrust( ulong lid );
|
||||
int get_ownertrust_info( ulong lid );
|
||||
byte *get_pref_data( ulong lid, const byte *namehash, size_t *ret_n );
|
||||
int is_algo_in_prefs( ulong lid, int preftype, int algo );
|
||||
int keyid_from_lid( ulong lid, u32 *keyid );
|
||||
ulong lid_from_keyblock( KBNODE keyblock );
|
||||
int query_trust_record( PKT_public_key *pk );
|
||||
int clear_trust_checked_flag( PKT_public_key *pk );
|
||||
int update_trust_record( KBNODE keyblock, int fast, int *modified );
|
||||
int insert_trust_record( KBNODE keyblock );
|
||||
int insert_trust_record_by_pk( PKT_public_key *pk );
|
||||
int update_ownertrust( ulong lid, unsigned new_trust );
|
||||
int trust_letter( unsigned value );
|
||||
|
||||
unsigned int get_ownertrust (PKT_public_key *pk);
|
||||
int get_ownertrust_info (PKT_public_key *pk);
|
||||
void update_ownertrust (PKT_public_key *pk, unsigned int new_trust );
|
||||
int clear_ownertrust (PKT_public_key *pk);
|
||||
|
||||
|
||||
/*-- tdbdump.c --*/
|
||||
void list_trustdb(const char *username);
|
||||
@ -77,6 +71,6 @@ void export_ownertrust(void);
|
||||
void import_ownertrust(const char *fname);
|
||||
|
||||
/*-- pkclist.c --*/
|
||||
int edit_ownertrust( ulong lid, int mode );
|
||||
int edit_ownertrust (PKT_public_key *pk, int mode );
|
||||
|
||||
#endif /*GPG_TRUSTDB_H*/
|
||||
#endif /*G10_TRUSTDB_H*/
|
||||
|
43
g10/verify.c
43
g10/verify.c
@ -1,5 +1,5 @@
|
||||
/* verify.c - verify signed data
|
||||
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
|
||||
* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
@ -24,13 +24,14 @@
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
#include <unistd.h> /* for isatty() */
|
||||
|
||||
#include <gcrypt.h>
|
||||
#include "options.h"
|
||||
#include "packet.h"
|
||||
#include "errors.h"
|
||||
#include "iobuf.h"
|
||||
#include "keydb.h"
|
||||
#include "memory.h"
|
||||
#include "util.h"
|
||||
#include "main.h"
|
||||
#include "status.h"
|
||||
@ -60,13 +61,38 @@ verify_signatures( int nfiles, char **files )
|
||||
STRLIST sl;
|
||||
|
||||
memset( &afx, 0, sizeof afx);
|
||||
/* decide whether we should handle a detached or a normal signature,
|
||||
* which is needed so that the code later can hash the correct data and
|
||||
* not have a normal signature act as detached signature and ignoring the
|
||||
* indended signed material from the 2nd file or stdin.
|
||||
* 1. gpg <file - normal
|
||||
* 2. gpg file - normal (or detached)
|
||||
* 3. gpg file <file2 - detached
|
||||
* 4. gpg file file2 - detached
|
||||
* The question is how decide between case 2 and 3? The only way
|
||||
* we can do it is by reading one byte from stdin and the unget
|
||||
* it; the problem here is that we may be reading from the
|
||||
* terminal (which could be detected using isatty() but won't work
|
||||
* when under contol of a pty using program (e.g. expect)) and
|
||||
* might get us in trouble when stdin is used for another purpose
|
||||
* (--passphrase-fd 0). So we have to break with the behaviour
|
||||
* prior to gpg 1.0.4 by assuming that case 3 is a normal
|
||||
* signature (where file2 is ignored and require for a detached
|
||||
* signature to indicate signed material comes from stdin by using
|
||||
* case 4 with a file2 of "-".
|
||||
*
|
||||
* Actually we don't have to change anything here but can handle
|
||||
* that all quite easily in mainproc.c
|
||||
*/
|
||||
|
||||
|
||||
sigfile = nfiles? *files : NULL;
|
||||
|
||||
/* open the signature file */
|
||||
fp = iobuf_open(sigfile);
|
||||
if( !fp ) {
|
||||
log_error(_("can't open `%s'\n"), print_fname_stdin(sigfile));
|
||||
return GPGERR_OPEN_FILE;
|
||||
return G10ERR_OPEN_FILE;
|
||||
}
|
||||
|
||||
if( !opt.no_armor && use_armor_filter( fp ) )
|
||||
@ -89,13 +115,13 @@ verify_signatures( int nfiles, char **files )
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
void
|
||||
print_file_status( int status, const char *name, int what )
|
||||
{
|
||||
char *p = gcry_xmalloc(strlen(name)+10);
|
||||
char *p = m_alloc(strlen(name)+10);
|
||||
sprintf(p, "%d %s", what, name );
|
||||
write_status_text( status, p );
|
||||
gcry_free(p);
|
||||
m_free(p);
|
||||
}
|
||||
|
||||
|
||||
@ -111,7 +137,7 @@ verify_one_file( const char *name )
|
||||
if( !fp ) {
|
||||
print_file_status( STATUS_FILE_ERROR, name, 1 );
|
||||
log_error(_("can't open `%s'\n"), print_fname_stdin(name));
|
||||
return GPGERR_OPEN_FILE;
|
||||
return G10ERR_OPEN_FILE;
|
||||
}
|
||||
|
||||
if( !opt.no_armor ) {
|
||||
@ -145,7 +171,7 @@ verify_files( int nfiles, char **files )
|
||||
lno++;
|
||||
if( !*line || line[strlen(line)-1] != '\n' ) {
|
||||
log_error(_("input line %u too long or missing LF\n"), lno );
|
||||
return GPGERR_GENERAL;
|
||||
return G10ERR_GENERAL;
|
||||
}
|
||||
/* This code does not work on MSDOS but how cares there are
|
||||
* also no script languages available. We don't strip any
|
||||
@ -161,4 +187,3 @@ verify_files( int nfiles, char **files )
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
304
po/ChangeLog
304
po/ChangeLog
@ -1,3 +1,295 @@
|
||||
2002-04-30 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* ja.po: Updated, also a bit too late for the release.
|
||||
|
||||
2002-04-29 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* pl.po: Update.
|
||||
* el.po: Updated, removed one entry due to non-matching printf and
|
||||
one removed one printf specifier.
|
||||
|
||||
Fixed fuzzy entries due to the change of (y/N) to (Y/n) in most files.
|
||||
|
||||
2002-04-25 gettextize <bug-gnu-utils@gnu.org>
|
||||
|
||||
* Makefile.in.in: Upgrade to gettext-0.10.40.
|
||||
|
||||
2002-04-22 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* et.po, tr.po, cs.po, it.po, id.po: Updated.
|
||||
|
||||
2002-04-19 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* de.po: Fixed fuzzies and added a few translations.
|
||||
|
||||
2002-04-18 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* eo.po: Updated.
|
||||
|
||||
2002-04-10 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* pl.po: Updated.
|
||||
|
||||
2002-04-09 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* pt_BR.po: Updated the info entry
|
||||
|
||||
* es.po: Fixed a c-format problem; for unknown reasons msgfmt -c
|
||||
can't cope with swapped arguments.
|
||||
|
||||
* de.po: Fuzzy fixes and a few new translations.
|
||||
|
||||
* id.po: Fixed a format string mismatch.
|
||||
|
||||
* eo.po, it.po, ja.po, sv.po: Updated with a somewhat newer
|
||||
version from the TP.
|
||||
|
||||
* es_ES.po: Removed
|
||||
* es.po: and replaced with this updated version from the TP.
|
||||
|
||||
* cs.po: New. Fixed for format string mismatches.
|
||||
|
||||
* el.po, gl.po: New from TP.
|
||||
|
||||
2002-04-06 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* fr.po: Updated.
|
||||
|
||||
2002-04-02 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* de.po, de.glo: Updated.
|
||||
|
||||
2002-03-08 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* et.po: Updated.
|
||||
|
||||
2002-03-06 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* pt_PT.po: Removed.
|
||||
* pt.po: and replaced by this updated one. My machine voted 30 to
|
||||
2 for just pt. So we go with the crowd. Thanks for Pedro Morais
|
||||
for suggesting this.
|
||||
|
||||
2002-03-05 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* tr.po, id.po: Updated.
|
||||
|
||||
2002-03-03 gettextize <bug-gnu-utils@gnu.org>
|
||||
|
||||
* Makefile.in.in: Upgrade to gettext-0.10.40.
|
||||
|
||||
2002-03-03 gettextize <bug-gnu-utils@gnu.org>
|
||||
|
||||
* Makefile.in.in: Upgrade to gettext-0.10.40.
|
||||
|
||||
2001-10-23 gettextize <bug-gnu-utils@gnu.org>
|
||||
|
||||
* Makefile.in.in: Upgrade to gettext-0.10.40.
|
||||
|
||||
2001-09-07 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* POTFILES.in: Added new files.
|
||||
|
||||
2001-07-26 gettextize <bug-gnu-utils@gnu.org>
|
||||
|
||||
* Makefile.in.in: Upgrade to gettext-0.10.38.
|
||||
|
||||
2001-07-05 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* id.po: Updated
|
||||
|
||||
2001-05-28 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* ru.po: Removed - too many format string bugs.
|
||||
|
||||
2001-05-27 gettextize <bug-gnu-utils@gnu.org>
|
||||
|
||||
* Makefile.in.in: Upgrade to gettext-0.10.38.
|
||||
* cat-id-tbl.c: Remove file.
|
||||
* stamp-cat-id: Remove file.
|
||||
|
||||
2001-05-27 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* tr.po: New copy from the TP Robot.
|
||||
* da.po, de.po, eo.po, es_ES.po, et.po, id.po, ja.po, nl.po,
|
||||
pt_BR.po, sv.po: Fixes to format string errors by Kurt Garloff.
|
||||
It is not cleare whether they are all correct but at least they
|
||||
won't give segv and minimize the risk of format string exploits.
|
||||
* ru.po: Fixed the header entry.
|
||||
|
||||
Fixed some fuzzy entries in all files.
|
||||
|
||||
2001-05-06 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* id.po: Updated
|
||||
|
||||
2001-04-27 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* de.po: Removed an extra "%s".
|
||||
|
||||
2001-04-25 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* fr.po: Updated.
|
||||
|
||||
2001-04-23 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* eo.po: Updated.
|
||||
|
||||
* it.po: Updated.
|
||||
|
||||
2001-04-22 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* pl.po: Updated.
|
||||
|
||||
2001-04-17 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* et.po: New.
|
||||
|
||||
* de.po: Updated.
|
||||
|
||||
2001-04-16 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* pt_PT.po: Updated.
|
||||
|
||||
2001-04-06 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* tr.po: New.
|
||||
|
||||
2001-03-18 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* de.po, de.glo: Updated.
|
||||
|
||||
2001-02-22 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* de.po, de.glo: Updated.
|
||||
|
||||
2001-01-23 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* de.po: Removed superfluous \r.
|
||||
|
||||
2001-01-14 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* de.po, de.glo: Updated.
|
||||
|
||||
2000-12-19 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* pl.po: Updated.
|
||||
|
||||
* ja.po: Justified one message.
|
||||
|
||||
2000-10-23 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* ja.po: Updated.
|
||||
|
||||
2000-10-19 Werner Koch <wk@gnupg.org>
|
||||
|
||||
Fixed a typo in all files.
|
||||
|
||||
2000-10-16 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* de.po, de.glo: Updated.
|
||||
|
||||
Thu Sep 14 17:45:11 CEST 2000 Werner Koch <wk@openit.de>
|
||||
|
||||
* eo.po: Updated.
|
||||
|
||||
Wed Jul 12 13:32:06 CEST 2000 Werner Koch <wk@>
|
||||
|
||||
* da.po: New from the TP server
|
||||
* eo.po: Updated from the TP server
|
||||
* pl.po: Ditto.
|
||||
* sv.po: Ditto.
|
||||
|
||||
Small English spelling correction in all files.
|
||||
|
||||
Wed Jul 5 13:28:45 CEST 2000 Werner Koch <wk@openit.de>
|
||||
|
||||
* fr.po: Minor changes by Gael
|
||||
|
||||
Wed Jun 14 12:27:09 CEST 2000 Werner Koch <wk@openit.de>
|
||||
|
||||
* de.po, de.glo: Updated.
|
||||
|
||||
2000-06-07 18:26:58 Werner Koch (wk@habibti.openit.de)
|
||||
|
||||
* fr.po: New version from Gaël
|
||||
|
||||
2000-05-02 10:44:42 Werner Koch (wk@habibti.openit.de)
|
||||
|
||||
* fr.po: New version from the TP Robot.
|
||||
|
||||
2000-05-01 14:19:52 Werner Koch (wk@habibti.openit.de)
|
||||
|
||||
* de.po: Updated.
|
||||
* de.glo: Ditto.
|
||||
|
||||
2000-03-15 15:37:08 Werner Koch (wk@habibti.openit.de)
|
||||
|
||||
* de.po: Updated.
|
||||
|
||||
Wed Feb 23 10:07:57 CET 2000 Werner Koch <wk@gnupg.de>
|
||||
|
||||
* nl.po: New. By Ivo Timmermans.
|
||||
|
||||
Wed Feb 16 16:25:09 CET 2000 Werner Koch <wk@gnupg.de>
|
||||
|
||||
* eo.po : New. By Edmund.
|
||||
|
||||
Wed Feb 16 14:09:00 CET 2000 Werner Koch <wk@gnupg.de>
|
||||
|
||||
* ja.po: New. By Yosiaki
|
||||
|
||||
* sv.po: New. By Daniel.
|
||||
|
||||
Fri Feb 11 17:44:40 CET 2000 Werner Koch <wk@gnupg.de>
|
||||
|
||||
* id.po: Updated.
|
||||
|
||||
Thu Jan 6 16:56:18 CET 2000 Werner Koch <wk@gnupg.de>
|
||||
|
||||
* Makefile.in.in: Is not longer maintained as a symlink because we
|
||||
have a patch to work around a bug in non-gnu Make.
|
||||
Fixed by Dave Dykstra.
|
||||
|
||||
Thu Dec 16 10:07:58 CET 1999 Werner Koch <wk@gnupg.de>
|
||||
|
||||
* pt_PT.po: Updated.
|
||||
* de.po: Updated.
|
||||
* it.po: Updated.
|
||||
|
||||
Thu Dec 9 10:31:05 CET 1999 Werner Koch <wk@gnupg.de>
|
||||
|
||||
* de.po: Updated.
|
||||
* pt_BR.po: Updated.
|
||||
|
||||
Fri Nov 12 20:33:19 CET 1999 Werner Koch <wk@gnupg.de>
|
||||
|
||||
* es_ES.po: Fixed 3 \n mismatches.
|
||||
|
||||
* de.po: Updated.
|
||||
|
||||
Thu Oct 28 16:08:20 CEST 1999 Werner Koch <wk@gnupg.de>
|
||||
|
||||
* es_ES.po: Updated.
|
||||
|
||||
* pt_BR.po: Updated.
|
||||
|
||||
Fri Oct 8 20:32:01 CEST 1999 Werner Koch <wk@gnupg.de>
|
||||
|
||||
* fr.po: Updated for 1.0.0d.
|
||||
|
||||
Mon Oct 4 21:23:04 CEST 1999 Werner Koch <wk@gnupg.de>
|
||||
|
||||
* pl.po: New version by Alex.
|
||||
|
||||
Thu Sep 23 06:26:28 1999 Werner Koch (wk@gnupg.org)
|
||||
|
||||
* fr.po: Updated by Gaël.
|
||||
|
||||
Sat Sep 18 11:49:51 1999 Werner Koch (wk@gnupg.org)
|
||||
|
||||
* id.po: New. Done by Tedi Heriyanto.
|
||||
|
||||
Wed Sep 15 16:22:17 CEST 1999 Werner Koch <wk@isil.d.shuttle.de>
|
||||
|
||||
* pt_PT.po: New. Done by Pedro Morais.
|
||||
@ -183,3 +475,15 @@ Fri Mar 13 09:43:19 1998 Werner Koch (wk@isil.d.shuttle.de)
|
||||
* it.po: New
|
||||
|
||||
|
||||
|
||||
Copyright 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
|
||||
|
||||
This file is free software; as a special exception the author gives
|
||||
unlimited permission to copy and/or distribute it, with or without
|
||||
modifications, as long as this notice is preserved.
|
||||
|
||||
This file is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
|
||||
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
|
||||
|
@ -1,14 +1,18 @@
|
||||
# Makefile for program source directory in GNU NLS utilities package.
|
||||
# Copyright (C) 1995, 1996, 1997 by Ulrich Drepper <drepper@gnu.ai.mit.edu>
|
||||
# Copyright (C) 1995-1997, 2000, 2001 by Ulrich Drepper <drepper@gnu.ai.mit.edu>
|
||||
#
|
||||
# This file file be copied and used freely without restrictions. It can
|
||||
# be used in projects which are not available under the GNU Public License
|
||||
# be used in projects which are not available under the GNU General Public License
|
||||
# but which still want to provide support for the GNU gettext functionality.
|
||||
# Please note that the actual code is *not* freely available.
|
||||
|
||||
PACKAGE = @PACKAGE@
|
||||
VERSION = @VERSION@
|
||||
|
||||
# These two variables depend on the location of this directory.
|
||||
subdir = po
|
||||
top_builddir = ..
|
||||
|
||||
SHELL = /bin/sh
|
||||
@SET_MAKE@
|
||||
|
||||
@ -18,22 +22,20 @@ VPATH = @srcdir@
|
||||
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
datadir = $(prefix)/@DATADIRNAME@
|
||||
datadir = @datadir@
|
||||
localedir = $(datadir)/locale
|
||||
gnulocaledir = $(prefix)/share/locale
|
||||
gettextsrcdir = $(prefix)/share/gettext/po
|
||||
subdir = po
|
||||
gettextsrcdir = $(datadir)/gettext/po
|
||||
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
MKINSTALLDIRS = $(top_srcdir)/@MKINSTALLDIRS@
|
||||
MKINSTALLDIRS = @MKINSTALLDIRS@
|
||||
mkinstalldirs = $(SHELL) `case "$(MKINSTALLDIRS)" in /*) echo "$(MKINSTALLDIRS)" ;; *) echo "$(top_builddir)/$(MKINSTALLDIRS)" ;; esac`
|
||||
|
||||
CC = @CC@
|
||||
GENCAT = @GENCAT@
|
||||
GMSGFMT = PATH=../src:$$PATH @GMSGFMT@
|
||||
GMSGFMT = @GMSGFMT@
|
||||
MSGFMT = @MSGFMT@
|
||||
XGETTEXT = PATH=../src:$$PATH @XGETTEXT@
|
||||
MSGMERGE = PATH=../src:$$PATH msgmerge
|
||||
XGETTEXT = @XGETTEXT@
|
||||
MSGMERGE = msgmerge
|
||||
|
||||
DEFS = @DEFS@
|
||||
CFLAGS = @CFLAGS@
|
||||
@ -43,26 +45,23 @@ INCLUDES = -I.. -I$(top_srcdir)/intl
|
||||
|
||||
COMPILE = $(CC) -c $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) $(XCFLAGS)
|
||||
|
||||
SOURCES = cat-id-tbl.c
|
||||
POFILES = @POFILES@
|
||||
GMOFILES = @GMOFILES@
|
||||
DISTFILES = ChangeLog Makefile.in.in POTFILES.in $(PACKAGE).pot \
|
||||
stamp-cat-id $(POFILES) $(GMOFILES) $(SOURCES)
|
||||
$(POFILES) $(GMOFILES)
|
||||
|
||||
POTFILES = \
|
||||
|
||||
CATALOGS = @CATALOGS@
|
||||
CATOBJEXT = @CATOBJEXT@
|
||||
INSTOBJEXT = @INSTOBJEXT@
|
||||
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .c .o .po .pox .gmo .mo .msg .cat
|
||||
.SUFFIXES: .c .o .po .pox .gmo .mo
|
||||
|
||||
.c.o:
|
||||
$(COMPILE) $<
|
||||
|
||||
.po.pox:
|
||||
$(MAKE) $(srcdir)/$(PACKAGE).pot
|
||||
$(MAKE) $(PACKAGE).pot
|
||||
$(MSGMERGE) $< $(srcdir)/$(PACKAGE).pot -o $*.pox
|
||||
|
||||
.po.mo:
|
||||
@ -70,19 +69,19 @@ INSTOBJEXT = @INSTOBJEXT@
|
||||
|
||||
.po.gmo:
|
||||
file=$(srcdir)/`echo $* | sed 's,.*/,,'`.gmo \
|
||||
&& rm -f $$file && $(GMSGFMT) -o $$file $<
|
||||
|
||||
.po.cat:
|
||||
sed -f ../intl/po2msg.sed < $< > $*.msg \
|
||||
&& rm -f $@ && $(GENCAT) $@ $*.msg
|
||||
&& rm -f $$file && $(GMSGFMT) --statistics -o $$file $<
|
||||
|
||||
|
||||
all: all-@USE_NLS@
|
||||
|
||||
all-yes: $(srcdir)/cat-id-tbl.c $(CATALOGS)
|
||||
all-yes: $(CATALOGS)
|
||||
all-no:
|
||||
|
||||
$(srcdir)/$(PACKAGE).pot: $(POTFILES)
|
||||
# Note: Target 'all' must not depend on target '$(srcdir)/$(PACKAGE).pot',
|
||||
# otherwise packages like GCC can not be built if only parts of the source
|
||||
# have been downloaded.
|
||||
|
||||
$(srcdir)/$(PACKAGE).pot: $(POTFILES) $(srcdir)/POTFILES.in
|
||||
$(XGETTEXT) --default-domain=$(PACKAGE) --directory=$(top_srcdir) \
|
||||
--add-comments --keyword=_ --keyword=N_ \
|
||||
--files-from=$(srcdir)/POTFILES.in \
|
||||
@ -90,78 +89,35 @@ $(srcdir)/$(PACKAGE).pot: $(POTFILES)
|
||||
|| ( rm -f $(srcdir)/$(PACKAGE).pot \
|
||||
&& mv $(PACKAGE).po $(srcdir)/$(PACKAGE).pot )
|
||||
|
||||
$(srcdir)/cat-id-tbl.c: $(srcdir)/stamp-cat-id; @:
|
||||
$(srcdir)/stamp-cat-id: $(srcdir)/$(PACKAGE).pot
|
||||
rm -f cat-id-tbl.tmp
|
||||
sed -f ../intl/po2tbl.sed $(srcdir)/$(PACKAGE).pot \
|
||||
| sed -e "s/@PACKAGE NAME@/$(PACKAGE)/" > cat-id-tbl.tmp
|
||||
if cmp -s cat-id-tbl.tmp $(srcdir)/cat-id-tbl.c; then \
|
||||
rm cat-id-tbl.tmp; \
|
||||
else \
|
||||
echo cat-id-tbl.c changed; \
|
||||
rm -f $(srcdir)/cat-id-tbl.c; \
|
||||
mv cat-id-tbl.tmp $(srcdir)/cat-id-tbl.c; \
|
||||
fi
|
||||
cd $(srcdir) && rm -f stamp-cat-id && echo timestamp > stamp-cat-id
|
||||
|
||||
|
||||
install: install-exec install-data
|
||||
install-exec:
|
||||
install-data: install-data-@USE_NLS@
|
||||
install-data-no: all
|
||||
install-data-yes: all
|
||||
if test -r "$(MKINSTALLDIRS)"; then \
|
||||
$(MKINSTALLDIRS) $(datadir); \
|
||||
else \
|
||||
$(SHELL) $(top_srcdir)/mkinstalldirs $(datadir); \
|
||||
fi
|
||||
@catalogs='$(CATALOGS)'; \
|
||||
for cat in $$catalogs; do \
|
||||
cat=`basename $$cat`; \
|
||||
case "$$cat" in \
|
||||
*.gmo) destdir=$(gnulocaledir);; \
|
||||
*) destdir=$(localedir);; \
|
||||
esac; \
|
||||
lang=`echo $$cat | sed 's/\$(CATOBJEXT)$$//'`; \
|
||||
dir=$$destdir/$$lang/LC_MESSAGES; \
|
||||
if test -r "$(MKINSTALLDIRS)"; then \
|
||||
$(MKINSTALLDIRS) $$dir; \
|
||||
else \
|
||||
$(SHELL) $(top_srcdir)/mkinstalldirs $$dir; \
|
||||
fi; \
|
||||
if test -r $$cat; then \
|
||||
$(INSTALL_DATA) $$cat $$dir/$(PACKAGE)$(INSTOBJEXT); \
|
||||
echo "installing $$cat as $$dir/$(PACKAGE)$(INSTOBJEXT)"; \
|
||||
else \
|
||||
$(INSTALL_DATA) $(srcdir)/$$cat $$dir/$(PACKAGE)$(INSTOBJEXT); \
|
||||
echo "installing $(srcdir)/$$cat as" \
|
||||
"$$dir/$(PACKAGE)$(INSTOBJEXT)"; \
|
||||
fi; \
|
||||
if test -r $$cat.m; then \
|
||||
$(INSTALL_DATA) $$cat.m $$dir/$(PACKAGE)$(INSTOBJEXT).m; \
|
||||
echo "installing $$cat.m as $$dir/$(PACKAGE)$(INSTOBJEXT).m"; \
|
||||
else \
|
||||
if test -r $(srcdir)/$$cat.m ; then \
|
||||
$(INSTALL_DATA) $(srcdir)/$$cat.m \
|
||||
$$dir/$(PACKAGE)$(INSTOBJEXT).m; \
|
||||
echo "installing $(srcdir)/$$cat as" \
|
||||
"$$dir/$(PACKAGE)$(INSTOBJEXT).m"; \
|
||||
else \
|
||||
true; \
|
||||
fi; \
|
||||
fi; \
|
||||
done
|
||||
if test "$(PACKAGE)" = "gettext"; then \
|
||||
if test -r "$(MKINSTALLDIRS)"; then \
|
||||
$(MKINSTALLDIRS) $(gettextsrcdir); \
|
||||
else \
|
||||
$(SHELL) $(top_srcdir)/mkinstalldirs $(gettextsrcdir); \
|
||||
fi; \
|
||||
$(mkinstalldirs) $(DESTDIR)$(gettextsrcdir); \
|
||||
$(INSTALL_DATA) $(srcdir)/Makefile.in.in \
|
||||
$(gettextsrcdir)/Makefile.in.in; \
|
||||
$(DESTDIR)$(gettextsrcdir)/Makefile.in.in; \
|
||||
else \
|
||||
: ; \
|
||||
fi
|
||||
install-data-no: all
|
||||
install-data-yes: all
|
||||
$(mkinstalldirs) $(DESTDIR)$(datadir)
|
||||
@catalogs='$(CATALOGS)'; \
|
||||
for cat in $$catalogs; do \
|
||||
cat=`basename $$cat`; \
|
||||
lang=`echo $$cat | sed 's/\.gmo$$//'`; \
|
||||
dir=$(localedir)/$$lang/LC_MESSAGES; \
|
||||
$(mkinstalldirs) $(DESTDIR)$$dir; \
|
||||
if test -r $$cat; then \
|
||||
$(INSTALL_DATA) $$cat $(DESTDIR)$$dir/$(PACKAGE).mo; \
|
||||
echo "installing $$cat as $(DESTDIR)$$dir/$(PACKAGE).mo"; \
|
||||
else \
|
||||
$(INSTALL_DATA) $(srcdir)/$$cat $(DESTDIR)$$dir/$(PACKAGE).mo; \
|
||||
echo "installing $(srcdir)/$$cat as" \
|
||||
"$(DESTDIR)$$dir/$(PACKAGE).mo"; \
|
||||
fi; \
|
||||
done
|
||||
|
||||
# Define this as empty until I found a useful application.
|
||||
installcheck:
|
||||
@ -170,77 +126,68 @@ uninstall:
|
||||
catalogs='$(CATALOGS)'; \
|
||||
for cat in $$catalogs; do \
|
||||
cat=`basename $$cat`; \
|
||||
lang=`echo $$cat | sed 's/\$(CATOBJEXT)$$//'`; \
|
||||
rm -f $(localedir)/$$lang/LC_MESSAGES/$(PACKAGE)$(INSTOBJEXT); \
|
||||
rm -f $(localedir)/$$lang/LC_MESSAGES/$(PACKAGE)$(INSTOBJEXT).m; \
|
||||
rm -f $(gnulocaledir)/$$lang/LC_MESSAGES/$(PACKAGE)$(INSTOBJEXT); \
|
||||
rm -f $(gnulocaledir)/$$lang/LC_MESSAGES/$(PACKAGE)$(INSTOBJEXT).m; \
|
||||
lang=`echo $$cat | sed 's/\.gmo$$//'`; \
|
||||
rm -f $(DESTDIR)$(localedir)/$$lang/LC_MESSAGES/$(PACKAGE).mo; \
|
||||
done
|
||||
rm -f $(gettextsrcdir)/po-Makefile.in.in
|
||||
if test "$(PACKAGE)" = "gettext"; then \
|
||||
rm -f $(DESTDIR)$(gettextsrcdir)/Makefile.in.in; \
|
||||
else \
|
||||
: ; \
|
||||
fi
|
||||
|
||||
check: all
|
||||
|
||||
cat-id-tbl.o: $(srcdir)/cat-id-tbl.c $(top_srcdir)/intl/libgettext.h
|
||||
$(COMPILE) $(srcdir)/cat-id-tbl.c
|
||||
|
||||
dvi info tags TAGS ID:
|
||||
|
||||
mostlyclean:
|
||||
rm -f core core.* *.pox $(PACKAGE).po *.old.po cat-id-tbl.tmp
|
||||
rm -f core core.* *.pox $(PACKAGE).po *.new.po
|
||||
rm -fr *.o
|
||||
|
||||
clean: mostlyclean
|
||||
|
||||
distclean: clean
|
||||
rm -f Makefile Makefile.in POTFILES *.mo *.msg *.cat *.cat.m
|
||||
rm -f Makefile Makefile.in POTFILES *.mo
|
||||
|
||||
maintainer-clean: distclean
|
||||
@echo "This command is intended for maintainers to use;"
|
||||
@echo "it deletes files that may require special tools to rebuild."
|
||||
rm -f $(GMOFILES) cat-id-tbl.c stamp-cat-id
|
||||
rm -f $(GMOFILES)
|
||||
|
||||
distdir = ../$(PACKAGE)-$(VERSION)/$(subdir)
|
||||
dist distdir: update-po $(DISTFILES)
|
||||
distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
|
||||
dist distdir:
|
||||
$(MAKE) update-po
|
||||
@$(MAKE) dist2
|
||||
# This is a separate target because 'update-po' must be executed before.
|
||||
dist2: $(DISTFILES)
|
||||
dists="$(DISTFILES)"; \
|
||||
for file in $$dists; do \
|
||||
ln $(srcdir)/$$file $(distdir) 2> /dev/null \
|
||||
|| cp -p $(srcdir)/$$file $(distdir); \
|
||||
if test -f $$file; then dir=.; else dir=$(srcdir); fi; \
|
||||
cp -p $$dir/$$file $(distdir); \
|
||||
done
|
||||
|
||||
update-po: Makefile
|
||||
$(MAKE) $(srcdir)/$(PACKAGE).pot
|
||||
PATH=`pwd`/../src:$$PATH; \
|
||||
$(MAKE) $(PACKAGE).pot
|
||||
if test "$(PACKAGE)" = "gettext"; then PATH=`pwd`/../src:$$PATH; fi; \
|
||||
cd $(srcdir); \
|
||||
catalogs='$(CATALOGS)'; \
|
||||
catalogs='$(GMOFILES)'; \
|
||||
for cat in $$catalogs; do \
|
||||
cat=`basename $$cat`; \
|
||||
lang=`echo $$cat | sed 's/\$(CATOBJEXT)$$//'`; \
|
||||
mv $$lang.po $$lang.old.po; \
|
||||
lang=`echo $$cat | sed 's/\.gmo$$//'`; \
|
||||
echo "$$lang:"; \
|
||||
if $(MSGMERGE) $$lang.old.po $(PACKAGE).pot -o $$lang.po; then \
|
||||
rm -f $$lang.old.po; \
|
||||
if $(MSGMERGE) $$lang.po $(PACKAGE).pot -o $$lang.new.po; then \
|
||||
mv -f $$lang.new.po $$lang.po; \
|
||||
else \
|
||||
echo "msgmerge for $$cat failed!"; \
|
||||
rm -f $$lang.po; \
|
||||
mv $$lang.old.po $$lang.po; \
|
||||
rm -f $$lang.new.po; \
|
||||
fi; \
|
||||
done
|
||||
$(MAKE) update-gmo
|
||||
|
||||
POTFILES: POTFILES.in
|
||||
( if test 'x$(srcdir)' != 'x.'; then \
|
||||
posrcprefix='$(top_srcdir)/'; \
|
||||
else \
|
||||
posrcprefix="../"; \
|
||||
fi; \
|
||||
rm -f $@-t $@ \
|
||||
&& (sed -e '/^#/d' -e '/^[ ]*$$/d' \
|
||||
-e "s@.*@ $$posrcprefix& \\\\@" < $(srcdir)/$@.in \
|
||||
| sed -e '$$s/\\$$//') > $@-t \
|
||||
&& chmod a-w $@-t \
|
||||
&& mv $@-t $@ )
|
||||
update-gmo: Makefile $(GMOFILES)
|
||||
@:
|
||||
|
||||
Makefile: Makefile.in.in ../config.status POTFILES
|
||||
cd .. \
|
||||
Makefile: Makefile.in.in $(top_builddir)/config.status POTFILES.in
|
||||
cd $(top_builddir) \
|
||||
&& CONFIG_FILES=$(subdir)/$@.in CONFIG_HEADERS= \
|
||||
$(SHELL) ./config.status
|
||||
|
||||
|
@ -2,23 +2,19 @@
|
||||
# Copyright (c) 1998 by Werner Koch (dd9jn)
|
||||
|
||||
# utility
|
||||
util/secmem.c
|
||||
util/argparse.c
|
||||
util/miscutil.c
|
||||
util/errors.c
|
||||
util/logger.c
|
||||
|
||||
# jnlib
|
||||
jnlib/argparse.c
|
||||
|
||||
# cipher
|
||||
#cipher/random.c
|
||||
#cipher/rndlinux.c
|
||||
|
||||
# gcrypt
|
||||
#gcrypt/secmem.c
|
||||
cipher/random.c
|
||||
cipher/rndlinux.c
|
||||
|
||||
# main program
|
||||
|
||||
g10/gpg.c
|
||||
g10/g10.c
|
||||
g10/armor.c
|
||||
g10/pkclist.c
|
||||
g10/keygen.c
|
||||
@ -43,7 +39,6 @@ g10/textfilter.c
|
||||
g10/tdbio.c
|
||||
g10/trustdb.c
|
||||
g10/verify.c
|
||||
g10/ringedit.c
|
||||
g10/skclist.c
|
||||
g10/status.c
|
||||
g10/pubkey-enc.c
|
||||
@ -52,3 +47,5 @@ g10/encr-data.c
|
||||
g10/seskey.c
|
||||
g10/delkey.c
|
||||
g10/helptext.c
|
||||
g10/keydb.c
|
||||
g10/keyring.c
|
||||
|
201
po/de.glo
201
po/de.glo
@ -1,115 +1,238 @@
|
||||
# Glossary for GnuPG german translation
|
||||
# Zusammenstellung der Liste:
|
||||
# Copyright (C) 1998 Free Software Foundation, Inc.
|
||||
# Walter Koch <walterk@dip.de>, 1998.
|
||||
# Walter Koch <koch@hsp.de>, 1998.
|
||||
#
|
||||
# This is just a textfile for your information.
|
||||
# It will _not_ be read or processed automatically by any program
|
||||
#
|
||||
# 1. Die Begriffe ohne ein "<" oder ">" vor dem deutschen Wort
|
||||
# stammen aus der Wortliste von Walter Koch (Programmübersetzung).
|
||||
# 2. Die Änderungsvorschläge dazu mit einem "*" vor dem deutschen Wort
|
||||
# stammen von Peter Gerwinski.
|
||||
# 3. Die Begriffe mit einem "<" vor dem deutschen Wort sind so in der
|
||||
# Bearbeitung von Herrn Goretzki verwendet worden
|
||||
# 4. Die Begriffe mit einem ">" vor dem deutschen Wort sind
|
||||
# alternative Übersetzungsmöglichkeiten, die von H.Martin angegeben
|
||||
# wurden.
|
||||
# 5. (*) Uneinheitlich verwendet
|
||||
# 6. - Gefällt mir (Walter Koch) nicht so toll
|
||||
# 7. Die erste genannte Übersetzung ist die in de.po verwendete
|
||||
# 8. # - Wurde in früherere de.po-Version verwendet
|
||||
|
||||
........ Authentisierung
|
||||
|
||||
agent Agent
|
||||
aka alias
|
||||
algorithm Verfahren
|
||||
anonymous ungenannter
|
||||
argument
|
||||
argument > Argument
|
||||
armor ASCII-Hülle
|
||||
available vorhanden [besser?: verfügbar]
|
||||
bad [signature] falsch[e] Unterschrift
|
||||
assigned zugewiesen
|
||||
associate with a person <einer Person zuordnen
|
||||
authentication Authentisierung
|
||||
available vorhanden [besser?: verfügbar, greifbar?]
|
||||
bad [MPI] fehlerhafte MPI
|
||||
bad [signature] falsch[e] Unterschrift
|
||||
break (the encryption) <(Die Verschlüsselung) aufbrechen
|
||||
bug "Bug (Programmfehler)"
|
||||
cache Lager [ ob das ernst gemeint ist? :-) ]
|
||||
cache Cache, -#Lager *Zwischenspeicher
|
||||
can't read nicht lesbar
|
||||
cancelled Abbruch, abgebrochen
|
||||
casual >zufällig, >gelegentlich >unregelmäßig
|
||||
certificate Zertifikat
|
||||
, (Urkunde)
|
||||
character set Zeichensatz
|
||||
check (verb) pr|fen, gepr|ft
|
||||
check (verb) prüfen, geprüft
|
||||
checking [sth.] [sth-]-Überprüfung
|
||||
checksum Prüfsumme
|
||||
cipher algorithm Verschlüsselungsverfahren
|
||||
clearsign
|
||||
clearsig header Klartextsignatur-Einleitung
|
||||
created erzeugt
|
||||
command Befehl
|
||||
compress algorithm Komprimierverfahren *
|
||||
comment Bemerkung
|
||||
compress algorithm Komprimierverfahren,*Komprimierungsverfahren ?
|
||||
compressed komprimiert
|
||||
compromised nicht mehr sicher
|
||||
core dump core-dump-Datei
|
||||
, (Speicherauszug?)
|
||||
core function <wesentliche Funktion
|
||||
correct beseitigen (please correct the error first)
|
||||
corrupted beschädigter
|
||||
critical bit ???
|
||||
dash escaped mit Bindestrich \"escapte\"
|
||||
decryption Enschlüsselung
|
||||
cover >behandeln, <erläutern
|
||||
created erstellt
|
||||
creation <Erzeugung
|
||||
critical bit ???
|
||||
dash escaped mit Bindestrich \"escapte\", *m.Bindestrichen maskiert?
|
||||
decryption Entschlüsselung
|
||||
default option <Standardoption
|
||||
default option file --voreingestellte Optionendatei
|
||||
DEK ???
|
||||
delete entfernen
|
||||
depreciated taugt nicht mehr viel
|
||||
delete entfernen, *>löschen
|
||||
depend on >sich verlassen auf,>angewiesen sein auf,>abhängen von
|
||||
deprecated mißbilligte
|
||||
detached [sign] abgetrennte [Unterschrift]
|
||||
determined attacker >zielbewusster,>entschlossener Angreifer
|
||||
digest algorithm Hashmethode
|
||||
direct [key sig] -"direct key"
|
||||
disabled abgeschaltet
|
||||
duplicated (adj.) doppelt
|
||||
encrypted verschlüsselte
|
||||
enviorement variable Umgebungsvariable
|
||||
eventually >schließlich, endlich Nicht: eventuell
|
||||
expand
|
||||
expiration date <Verfalldatum
|
||||
expire <verfallen
|
||||
expires verfällt
|
||||
expire date Verfallsdatum
|
||||
failed fehlgeschlagen
|
||||
faked [RNG]
|
||||
faked [RNG] - *manipulierter Zufallszahlengenerator
|
||||
faked [certificate] gefälscht
|
||||
fingerprint Fingerabdruck
|
||||
flag [verb] -kennzeichnen
|
||||
found [xyz found] entdeckt [xyz entdeckt]
|
||||
for-your-eyes-only Vertraulichkeit (\"for-your-eyes-only\")
|
||||
, Verschlußsache
|
||||
generated erzeugter
|
||||
good certificate Korrektes Zertifikat
|
||||
handle benutzt
|
||||
handle [verb] benutzen, behandeln, mit ... umgehen
|
||||
hint Tip
|
||||
init -
|
||||
key-ID Schlüssel-ID
|
||||
human readable -nicht als Klartext darstellbar
|
||||
ignored unbeachtet
|
||||
include <enthalten
|
||||
init *initialisieren
|
||||
invalid ... falsche ...
|
||||
is adequate >ist angemessen, manchmal: <reicht völlig aus
|
||||
issue
|
||||
key-ID Schlüssel-ID, *Schlüsselkennung ?
|
||||
|
||||
key binding Schlüsselanbindung
|
||||
keyblock Schlüsselblock
|
||||
keyserver Schlüsselserver, Schlü.server, -*Schlüssel-Server
|
||||
keysize
|
||||
keyring Schlüsselbund
|
||||
keyserver - Schl€sselserver
|
||||
lifetime >Gültigkeitsdauer, >Geltungsdauer
|
||||
listed
|
||||
locally (nur) für diesen Rechner, #(nur) auf diesem Rechner
|
||||
lookup - Suche
|
||||
machine häufig: Computer, Rechner
|
||||
main key Hauptschlüssel
|
||||
maintenance utility Wartungs-Hilfsprogramm
|
||||
malformed ungünstig aufgebaute
|
||||
maintenance utility -Wartungs-Hilfsprogramm
|
||||
making signatures >Unterschreiben <Unterzeichnen, <Leisten von
|
||||
malformed ungünstig aufgebaute, *fehlerhaft aufgebaute
|
||||
master key >Universalschlüssel
|
||||
, Generalschlüssel
|
||||
match Treffer
|
||||
MDC Manipulation detection code (Siegel ?)
|
||||
merge (to) >zusammenführen, >vermischen ??
|
||||
message Botschaft
|
||||
mode Modus, Methode *
|
||||
move schieben
|
||||
move schieben, *verschieben
|
||||
multiple signature Mehrfachunterschriften
|
||||
NAI
|
||||
network error Netzwerkfehler
|
||||
non-revocably nicht-widerrufbar, unwiderruflich??
|
||||
note Hinweis
|
||||
okay in Ordnung
|
||||
Ooops Huch
|
||||
original Ursprünglicher
|
||||
ownertrust \"Owner trust\"
|
||||
OpenPGP
|
||||
option Option
|
||||
original ursprünglicher
|
||||
overrides -ersetzt
|
||||
ownertrust \"Owner trust\" *Vertrauenswürdigkeit des Besitzers
|
||||
packet Paket
|
||||
packet type Pakettyp
|
||||
parse -zerlegen
|
||||
passphrase Mantra
|
||||
permission [file] Zugriffsrechte
|
||||
Photo-ID Foto-ID
|
||||
policy Richtlinie
|
||||
policy URL Richtlinien-URL
|
||||
preference items ????
|
||||
preferences Einstellungen
|
||||
preferences Einstellungen *(die gesamten) Einstellungen
|
||||
preferred bevorzugt
|
||||
primary keys Hauptschlüssel
|
||||
problem [to do sth.] -Schwierigkeit
|
||||
prompt (to) auch: >abfragen, >anfordern, >verlangen
|
||||
protected
|
||||
protection algorithm Schutzverfahren
|
||||
pubkey algorithm Public-Key Verfahren (*)
|
||||
pubkey algorithm Public-Key-Verfahren
|
||||
public key öffentlicher Schüssel
|
||||
public key algorithm Public-Key Verfahren
|
||||
quit
|
||||
public key algorithm Public-Key-Verfahren
|
||||
quit *(Programm) verlassen, beenden
|
||||
radix64 radix64
|
||||
random Zufall
|
||||
random bytes Zufallswerte
|
||||
reason Grund (für revocation)
|
||||
[xyz] rebuild [xyz]-Neuaufbau, neu erzeugt
|
||||
regular file normale Datei
|
||||
response Antwort (Reaktion?)
|
||||
retry ???? (Wiederholung?, Wiederaufnahme?)
|
||||
returns gibt zurück / antwortet
|
||||
reveal auch: <jemandem zeigen, >anderen zeigen
|
||||
revocation Widerruf <*>Rückruf
|
||||
revocation certificate *<Rückrufurkunde *Rückruf-Zertifikat
|
||||
revoke widerrufen
|
||||
revocation Widerruf
|
||||
revocably widerrufbar
|
||||
RNG Zufallsgenerator
|
||||
secondary key Zweitschlüssel
|
||||
secret key geheimer Schlüssel
|
||||
secret keyring geheimer Schlüsselbund, geh. Schlüsselbund
|
||||
secret parts geheime Teile
|
||||
security need(s) >Sicherheitsbedüfnis(se), >Sicherheitsbedarf
|
||||
self-signature Eigenbeglaubigung
|
||||
sender Absender
|
||||
sensitive - empfindlich
|
||||
set [sth.] einstellen, festlegen
|
||||
session Sitzung
|
||||
show [an]zeigen, zeigen
|
||||
sign user id User-ID beglaubigen *
|
||||
signed unterschriebene
|
||||
signature (files) Unterschrift *
|
||||
signature (keys) Beglaubigung *
|
||||
simple S2K mode ????
|
||||
skipped übergangen, übersprungen, ignoriert
|
||||
stdin - stdin
|
||||
so far bislang
|
||||
specify >spezifizieren, <angeben, ?festlegen
|
||||
stdin - stdin, *die Standardeingabe
|
||||
string Zeichenkette
|
||||
[PGP2-]style[ key] [PGP2-] artiger [Schlüssel]
|
||||
subkey Unterschlüssel
|
||||
terminal charset - Terminalzeichensatz
|
||||
superseeded überholt, veraltet
|
||||
terminal charset - Terminalzeichensatz *Terminal-Zeichensatz(s.o.)
|
||||
throw verwerfe
|
||||
Timestamp conflict Zeitangaben differieren
|
||||
Trust-DB 'Trust'-Datenbank
|
||||
trust Vertrauen
|
||||
Trust-DB 'Trust'-Datenbank, *Vertrauensdatenbank ?
|
||||
trusted - vertrauenswürdig
|
||||
trustvalues - trustvalues
|
||||
trustvalues - trustvalues >Vertrauensniveaus?? *Vertrauensmaß? >Vertrauenswerte?
|
||||
trying Versuch
|
||||
type [message] [Botschaft] eintippen
|
||||
ulimately [trust] uneingeschränktes [Vertrauen]
|
||||
update Ändern, Änderung
|
||||
User - User
|
||||
ulimately [trust] uneingeschränkt [vertrauen]
|
||||
ultimate trust uneingeschränktes Vertrauen
|
||||
unable
|
||||
unattended unbeaufsichtigt
|
||||
unavailble
|
||||
untrusted - nichtvertrauenswürdig, *nicht vertrauenswürdig
|
||||
unusable unbrauchbar
|
||||
update Ändern, Änderung >Aktualisieren, >Aktualisierung *auf den
|
||||
URL (die) URL
|
||||
[the] use [of]
|
||||
User - User, *<Benutzer, *Teilnehmer
|
||||
user ID User-ID
|
||||
user IDs User-IDs
|
||||
username Username
|
||||
untrusted - nichtvertruenswürdig
|
||||
user interface >Benutzer-Schnittstelle
|
||||
username Username, *<Benutzername,
|
||||
used benutzt (no loger used)
|
||||
using xyz verwende xyz
|
||||
valid gültig
|
||||
validate -- authentifizieren (>besser authentisieren ?? So im
|
||||
Wörterbuch der neuen Rechtschreibung)
|
||||
validation -- >Authentisierung
|
||||
verbose ausführlich
|
||||
verify < überprüfen
|
||||
warning Warnung
|
||||
weak key unsicherer Schlüssel
|
||||
writeable schreibbarer
|
||||
wisely >klug, vernünftig(erweise), >gescheit; möglichst sinnvoll
|
||||
|
||||
(*) Uneinheitlich verwendet
|
||||
- Gefällt mir nicht so toll
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
3368
po/pt_BR.po
3368
po/pt_BR.po
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user