1
0
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:
David Shaw 2002-06-29 13:46:34 +00:00
parent 151ee2f47b
commit 3f51f7db3d
155 changed files with 83872 additions and 37585 deletions

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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;
}

View File

@ -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;

View File

@ -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;
}

View File

@ -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 );
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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++;
}
}
}

View File

@ -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
View 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
View 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_ */

View File

@ -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"));

View File

@ -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*/

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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*/

View File

@ -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
View 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) {}

View File

@ -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
View File

@ -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 &lt;<a href="/pks/lookup?op=get&search=0x3CB3B415">dshaw@jabberwocky.com</a>&gt; */
/* 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;
}

View File

@ -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*/

File diff suppressed because it is too large Load Diff

View File

@ -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);
}
}

View File

@ -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*/

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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
View 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);
}

View File

@ -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*/

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -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;
}

File diff suppressed because it is too large Load Diff

1550
g10/keyring.c Normal file

File diff suppressed because it is too large Load Diff

45
g10/keyring.h Normal file
View 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
View 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

File diff suppressed because it is too large Load Diff

View File

@ -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.
*

View File

@ -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*/

View File

@ -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*/

File diff suppressed because it is too large Load Diff

View File

@ -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;

View File

@ -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
View 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;
}

View File

@ -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);
}
}

View File

@ -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*/

View File

@ -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.

View File

@ -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

File diff suppressed because it is too large Load Diff

320
g10/photoid.c Normal file
View 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
View 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
View 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 );
}

File diff suppressed because it is too large Load Diff

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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 );
}
}

File diff suppressed because it is too large Load Diff

View File

@ -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;

View File

@ -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;
}

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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);
}

View File

@ -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 )

View File

@ -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;
}
}

View File

@ -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*/

View File

@ -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) );
}
}

File diff suppressed because it is too large Load Diff

View File

@ -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*/

View File

@ -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 )

File diff suppressed because it is too large Load Diff

View File

@ -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*/

View File

@ -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;
}

View File

@ -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.

View File

@ -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

View File

@ -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

4382
po/cs.po Normal file

File diff suppressed because it is too large Load Diff

3009
po/da.po

File diff suppressed because it is too large Load Diff

201
po/de.glo
View File

@ -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

3541
po/de.po

File diff suppressed because it is too large Load Diff

4383
po/el.po Normal file

File diff suppressed because it is too large Load Diff

3355
po/eo.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

4317
po/et.po Normal file

File diff suppressed because it is too large Load Diff

3198
po/fr.po

File diff suppressed because it is too large Load Diff

4681
po/gl.po Normal file

File diff suppressed because it is too large Load Diff

3355
po/id.po

File diff suppressed because it is too large Load Diff

3540
po/it.po

File diff suppressed because it is too large Load Diff

4586
po/ja.po

File diff suppressed because it is too large Load Diff

3312
po/nl.po

File diff suppressed because it is too large Load Diff

3945
po/pl.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

4097
po/ru.po

File diff suppressed because it is too large Load Diff

3345
po/sv.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