Merged with gpg 1.4.3 code.

The gpg part does not yet build.
This commit is contained in:
Werner Koch 2006-04-19 11:26:11 +00:00
parent 751a3aeea7
commit 29b23dea97
90 changed files with 18002 additions and 10564 deletions

View File

@ -1,3 +1,12 @@
2006-04-18 Werner Koch <wk@g10code.com>
* configure.ac (PK_UID_CACHE_SIZE): New.
2006-04-07 Werner Koch <wk@g10code.com>
* configure.ac: Use new method to include the SVN revison. Now it
is the actual global revision number.
2005-12-20 Werner Koch <wk@g10code.com>
Released 1.9.20.

6
NEWS
View File

@ -1,12 +1,14 @@
Noteworthy changes in version 1.9.21
-------------------------------------------------
* [scdaemon] New command APDU.
* [scdaemon] Support for keypads of some readers. Tested only with
SPR532. New option --disable-keypad.
* Support for CardMan 4040 PCMCIA reader.
* [scdaemon] Support for CardMan 4040 PCMCIA reader.
* Cards are not anymore reseted at the end of a connection.
* [scdaemon] Cards are not anymore reseted at the end of a connection.
* [gpgsm] Kludge to allow use of Bundesnetzagentur issued
certificates.

View File

@ -1,3 +1,8 @@
2006-04-18 Werner Koch <wk@g10code.com>
* homedir.c (w32_shgetfolderpath): New. Taken from gpg 1.4.3.
(default_homedir): Use it.
2005-10-08 Marcus Brinkmann <marcus@g10code.de>
* signal.c (get_signal_name): Check value of HAVE_DECL_SYS_SIGLIST

View File

@ -1,5 +1,5 @@
/* homedir.c - Setup the home directory.
* Copyright (C) 2004 Free Software Foundation, Inc.
* Copyright (C) 2004, 2006 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -41,6 +41,47 @@
#include "util.h"
#include "sysutils.h"
/* This is a helper function to load a Windows function from either of
one DLLs. */
#ifdef HAVE_W32_SYSTEM
static HRESULT
w32_shgetfolderpath (HWND a, int b, HANDLE c, DWORD d, LPSTR e)
{
static int initialized;
static HRESULT (WINAPI * func)(HWND,int,HANDLE,DWORD,LPSTR);
if (!initialized)
{
static char *dllnames[] = { "shell32.dll", "shfolder.dll", NULL };
void *handle;
int i;
initialized = 1;
for (i=0, handle = NULL; !handle && dllnames[i]; i++)
{
handle = dlopen (dllnames[i], RTLD_LAZY);
if (handle)
{
func = dlsym (handle, "SHGetFolderPathA");
if (!func)
{
dlclose (handle);
handle = NULL;
}
}
}
}
if (func)
return func (a,b,c,d,e);
else
return -1;
}
#endif /*HAVE_W32_SYSTEM*/
/* Set up the default home directory. The usual --homedir option
should be parsed later. */
const char *
@ -56,15 +97,15 @@ default_homedir (void)
{
char path[MAX_PATH];
/* fixme: It might be better to use LOCAL_APPDATA because this
is defined as "non roaming" and thus more likely to be kept
/* It might be better to use LOCAL_APPDATA because this is
defined as "non roaming" and thus more likely to be kept
locally. For private keys this is desired. However, given
that many users copy private keys anyway forth and back,
using a system roaming serives might be better than to let
using a system roaming services might be better than to let
them do it manually. A security conscious user will anyway
use the registry entry to have better control. */
if (SHGetFolderPath(NULL, CSIDL_APPDATA|CSIDL_FLAG_CREATE,
NULL, 0, path) >= 0)
if (w32_shgetfolderpath (NULL, CSIDL_APPDATA|CSIDL_FLAG_CREATE,
NULL, 0, path) >= 0)
{
char *tmp = xmalloc (strlen (path) + 6 +1);
strcpy (stpcpy (tmp, path), "\\gnupg");

View File

@ -36,6 +36,7 @@
#define IOBUFCTRL_USER 16
typedef struct iobuf_struct *iobuf_t;
typedef struct iobuf_struct *IOBUF; /* Compatibility with gpg 1.4. */
/* fixme: we should hide most of this stuff */
struct iobuf_struct

View File

@ -59,6 +59,10 @@
#define xrealloc(a,b) gcry_xrealloc ((a),(b))
#define xstrdup(a) gcry_xstrdup ((a))
/* For compatibility with gpg 1.4 we also define these: */
#define xmalloc_clear(a) gcry_xcalloc (1, (a))
#define xmalloc_secure_clear(a) gcry_xcalloc_secure (1, (a))
/* A type to hold the ISO time. Note that this this is the same as
the the KSBA type ksba_isotime_t. */
@ -133,7 +137,7 @@ int cmp_simple_canon_sexp (const unsigned char *a, const unsigned char *b);
unsigned char *make_simple_sexp_from_hexstr (const char *line,
size_t *nscanned);
/*-- homedir. c --*/
/*-- homedir.c --*/
const char *default_homedir (void);

View File

@ -23,11 +23,16 @@ AC_PREREQ(2.52)
min_automake_version="1.9.3"
# Remember to change the version number immediately *after* a release.
# Uncomment the my_iscvs macro for non-released code.
m4_define(my_version, [1.9.21])
m4_define(my_iscvs, yes)
AC_INIT([gnupg], my_version[]m4_ifdef([my_iscvs], [-cvs[]m4_translit(
[$Revision$],[Ra-z $:])]), [gnupg-devel@gnupg.org])
# Set my_issvn to "yes" for non-released code. Remember to run an
# "svn up" and "autogen.sh" right before creating a distribution.
m4_define([my_version], [1.9.21])
m4_define([my_issvn], [yes])
m4_define([svn_revision], m4_esyscmd([echo -n $((svn info 2>/dev/null \
|| echo 'Revision: 0')|sed -n '/^Revision:/ {s/[^0-9]//gp;q}')]))
AC_INIT([gnupg], my_version[]m4_if(my_issvn,[yes],[-svn[]svn_revision]),
[gnupg-devel@gnupg.org])
# Set development_version to yes if the minor number is odd or you
# feel that the default check for a development version is not
# sufficient.
@ -219,6 +224,34 @@ if test "$use_exec" = yes ; then
AC_MSG_RESULT($enableval)
fi
dnl
dnl Check for the key/uid cache size. This can't be zero, but can be
dnl pretty small on embedded systems.
dnl
AC_MSG_CHECKING([for the size of the key and uid cache])
AC_ARG_ENABLE(key-cache,
AC_HELP_STRING([--enable-key-cache=SIZE],[Set key cache to SIZE (default 4096)]),,enableval=4096)
if test "$enableval" = "no"; then
enableval=5
elif test "$enableval" = "yes" || test "$enableval" = ""; then
enableval=4096
fi
changequote(,)dnl
key_cache_size=`echo "$enableval" | sed 's/[A-Za-z]//g'`
changequote([,])dnl
if test "$enableval" != "$key_cache_size" || test "$key_cache_size" -lt 5; then
AC_MSG_ERROR([invalid key-cache size])
fi
AC_MSG_RESULT($key_cache_size)
AC_DEFINE_UNQUOTED(PK_UID_CACHE_SIZE,$key_cache_size,[Size of the key and UID caches])
dnl
dnl Check whether we want to use Linux capabilities
dnl

View File

@ -1,3 +1,33 @@
2006-04-18 Werner Koch <wk@g10code.com>
* tdbio.c (open_db, migrate_from_v2): Removed feature to migration
from old trustdb version 2.
* gpg.c, mainproc.c: Removed pipemode feature.
* status.c: Removed shared memory coprocess stuff
Merged with current gpg 1.4.3 code.
* keygen.c, keyid.c, misc.c, openfile.c, verify.c, trustdb.c
* textfilter.c, tdbio.c, tdbdump.c, status.c, skclist.c, signal.c
* sign.c, sig-check.c, seskey.c, seckey-cert.c, revoke.c
* pubkey-enc.c, progress.c, plaintext.c, pkclist.c, photoid.c
* passphrase.c, parse-packet.c, mdfilter.c, mainproc.c
* keyserver.c, keyring.c, keylist.c, keyedit.c, keydb.c, kbnode.c
* import.c, getkey.c, gpgv.c, helptext.c, free-packet.c
* build-packet.c, cipher.c, compress.c, dearmor.c, decrypt.c
* delkey.c, encr-data.c, encode.c, exec.c, export.c
* gpg.c, armor.c: Updated from gnupg-1.4.3 and merged back gcry and
gnupg-1.9 related changes.
* trustdb.h, tdbio.h, status.h, photoid.h, packet.h, options.h
* main.h, keyserver-internal.h, keyring.h, keydb.h, filter.h
* exec.h: Ditto.
* global.h: Removed after merging constants with gpg.h.
* comment.c, pipemode.c: Removed.
* card-util.c: Updated from gnupg-1.4.3.
* compress-bz2.c: New.
2005-06-15 Werner Koch <wk@g10code.com>
* g10.c (print_hashline, add_group): Fixes for signed/unsigned
@ -9007,7 +9037,8 @@ Thu Feb 12 22:24:42 1998 Werner Koch (wk@frodo)
* pubkey-enc.c (get_session_key): rewritten
Copyright 1998,1999,2000,2001,2002,2003 Free Software Foundation, Inc.
Copyright 1998,1999,2000,2001,2002,2003,2004,2005,
2006 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

View File

@ -1,5 +1,5 @@
# Copyright (C) 1998, 1999, 2000, 2001, 2002,
# 2003 Free Software Foundation, Inc.
# 2003, 2006 Free Software Foundation, Inc.
#
# This file is part of GnuPG.
#
@ -26,16 +26,17 @@ AM_CPPFLAGS = -I$(top_srcdir)/gl -I$(top_srcdir)/common \
include $(top_srcdir)/am/cmacros.am
AM_CFLAGS = $(LIBGCRYPT_CFLAGS)
AM_CFLAGS = $(LIBGCRYPT_CFLAGS) -Wno-pointer-sign
needed_libs = ../gl/libgnu.a ../common/libcommon.a ../jnlib/libjnlib.a
bin_PROGRAMS = gpg2 gpgv2
common_source = \
global.h gpg.h \
gpg.h \
build-packet.c \
compress.c \
compress-bz2.c \
filter.h \
free-packet.c \
getkey.c \
@ -55,7 +56,6 @@ common_source = \
keyid.c \
packet.h \
parse-packet.c \
comment.c \
status.c \
status.h \
plaintext.c \
@ -63,7 +63,7 @@ common_source = \
keylist.c \
pkglue.c pkglue.h
gpg2_SOURCES = g10.c \
gpg2_SOURCES = gpg.c \
$(common_source) \
pkclist.c \
skclist.c \
@ -88,7 +88,6 @@ gpg2_SOURCES = g10.c \
tdbio.h \
delkey.c \
keygen.c \
pipemode.c \
helptext.c \
keyserver.c \
keyserver-internal.h \

View File

@ -1,6 +1,6 @@
/* armor.c - Armor flter
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003
* Free Software Foundation, Inc.
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004,
* 2005 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -16,7 +16,8 @@
*
* 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
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
#include <config.h>
@ -30,7 +31,6 @@
#include "gpg.h"
#include "errors.h"
#include "iobuf.h"
#include "memory.h"
#include "util.h"
#include "filter.h"
#include "packet.h"
@ -39,12 +39,6 @@
#include "status.h"
#include "i18n.h"
#ifdef HAVE_DOSISH_SYSTEM
#define LF "\r\n"
#else
#define LF "\n"
#endif
#define MAX_LINELEN 20000
#define CRCINIT 0xB704CE
@ -120,7 +114,6 @@ static char *tail_strings[] = {
};
static void
initialize(void)
{
@ -193,7 +186,7 @@ is_armored( const byte *buf )
* filter to do further processing.
*/
int
use_armor_filter( iobuf_t a )
use_armor_filter( IOBUF a )
{
byte buf[1];
int n;
@ -292,17 +285,24 @@ is_armor_header( byte *line, unsigned len )
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. */
/* Some Windows environments seem to add whitespace to the end of
the line, so we strip it here. This becomes strict if
--rfc2440 is set since 2440 reads "The header lines, therefore,
MUST start at the beginning of a line, and MUST NOT have text
following them on the same line." It is unclear whether "text"
refers to all text or just non-whitespace text. */
if(!RFC2440)
while(*p==' ')
if(RFC2440)
{
if( *p == '\r' )
p++;
if( *p == '\n' )
p++;
}
else
while(*p==' ' || *p=='\r' || *p=='\n' || *p=='\t')
p++;
if( *p == '\r' )
p++;
if( *p == '\n' )
p++;
if( *p )
return -1; /* garbage after dashes */
save_c = *save_p; *save_p = 0;
@ -334,21 +334,35 @@ parse_header_line( armor_filter_context_t *afx, byte *line, unsigned int len )
int hashes=0;
unsigned int len2;
len2 = length_sans_trailing_ws( line, len );
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;
/*
This is fussy. The spec says that a header line is delimited
with a colon-space pair. This means that a line such as
"Comment: " (with nothing else) is actually legal as an empty
string comment. However, email and cut-and-paste being what it
is, that trailing space may go away. Therefore, we accept empty
headers delimited with only a colon. --rfc2440, as always,
makes this strict and enforces the colon-space pair. -dms
*/
p = strchr( line, ':');
if( !p || !p[1] ) {
if( !p || (RFC2440 && p[1]!=' ')
|| (!RFC2440 && p[1]!=' ' && p[1]!='\n' && p[1]!='\r'))
{
log_error(_("invalid armor header: "));
print_string( stderr, line, len, 0 );
putc('\n', stderr);
return -1;
}
}
/* Chop off the whitespace we detected before */
len=len2;
line[len2]='\0';
if( opt.verbose ) {
log_info(_("armor header: "));
@ -373,7 +387,7 @@ parse_header_line( armor_filter_context_t *afx, byte *line, unsigned int len )
/* figure out whether the data is armored or not */
static int
check_input( armor_filter_context_t *afx, iobuf_t a )
check_input( armor_filter_context_t *afx, IOBUF a )
{
int rc = 0;
int i;
@ -415,7 +429,7 @@ check_input( armor_filter_context_t *afx, iobuf_t a )
if( hdr_line == BEGIN_SIGNED_MSG_IDX ) {
if( afx->in_cleartext ) {
log_error(_("nested clear text signatures\n"));
rc = GPG_ERR_INV_ARMOR;
rc = gpg_error (GPG_ERR_INV_ARMOR);
}
afx->in_cleartext = 1;
}
@ -431,9 +445,9 @@ check_input( armor_filter_context_t *afx, iobuf_t a )
} while( !maxlen );
}
/* parse the header lines */
/* Parse the header lines. */
while(len) {
/* read the next line (skip all truncated lines) */
/* Read the next line (skip all truncated lines). */
do {
maxlen = MAX_LINELEN;
afx->buffer_len = iobuf_read_line( a, &afx->buffer,
@ -444,8 +458,8 @@ check_input( armor_filter_context_t *afx, iobuf_t a )
i = parse_header_line( afx, line, len );
if( i <= 0 ) {
if( i )
rc = GPG_ERR_INV_ARMOR;
if (i && RFC2440)
rc = G10ERR_INVALID_ARMOR;
break;
}
}
@ -465,7 +479,8 @@ check_input( armor_filter_context_t *afx, iobuf_t a )
return rc;
}
#define PARTIAL_CHUNK 512
#define PARTIAL_POW 9
/****************
* Fake a literal data packet and wait for the next armor line
@ -473,7 +488,7 @@ check_input( armor_filter_context_t *afx, iobuf_t a )
* not implemented/checked.
*/
static int
fake_packet( armor_filter_context_t *afx, iobuf_t a,
fake_packet( armor_filter_context_t *afx, IOBUF a,
size_t *retn, byte *buf, size_t size )
{
int rc = 0;
@ -481,19 +496,31 @@ fake_packet( armor_filter_context_t *afx, iobuf_t a,
int lastline = 0;
unsigned maxlen, n;
byte *p;
byte tempbuf[PARTIAL_CHUNK];
size_t tempbuf_len=0;
len = 2; /* reserve 2 bytes for the length header */
size -= 2; /* and 2 for the terminating header */
while( !rc && len < size ) {
while( !rc && size-len>=(PARTIAL_CHUNK+1)) {
/* copy what we have in the line buffer */
if( afx->faked == 1 )
afx->faked++; /* skip the first (empty) line */
else {
while( len < size && afx->buffer_pos < afx->buffer_len )
buf[len++] = afx->buffer[afx->buffer_pos++];
if( len >= size )
else
{
/* It's full, so write this partial chunk */
if(tempbuf_len==PARTIAL_CHUNK)
{
buf[len++]=0xE0+PARTIAL_POW;
memcpy(&buf[len],tempbuf,PARTIAL_CHUNK);
len+=PARTIAL_CHUNK;
tempbuf_len=0;
continue;
}
}
while( tempbuf_len < PARTIAL_CHUNK
&& afx->buffer_pos < afx->buffer_len )
tempbuf[tempbuf_len++] = afx->buffer[afx->buffer_pos++];
if( tempbuf_len==PARTIAL_CHUNK )
continue;
}
/* read the next line */
maxlen = MAX_LINELEN;
@ -506,15 +533,64 @@ fake_packet( armor_filter_context_t *afx, iobuf_t a,
}
if( !maxlen )
afx->truncated++;
if( !afx->not_dash_escaped ) {
int crlf;
p = afx->buffer;
n = afx->buffer_len;
crlf = n > 1 && p[n-2] == '\r' && p[n-1]=='\n';
p = afx->buffer;
n = afx->buffer_len;
/* Armor header or dash-escaped line? */
if(p[0]=='-')
{
/* 2440bis-10: When reversing dash-escaping, an
implementation MUST strip the string "- " if it occurs
at the beginning of a line, and SHOULD warn on "-" and
any character other than a space at the beginning of a
line. */
if(p[1]==' ' && !afx->not_dash_escaped)
{
/* It's a dash-escaped line, so skip over the
escape. */
afx->buffer_pos = 2;
}
else if(p[1]=='-' && p[2]=='-' && p[3]=='-' && p[4]=='-')
{
/* Five dashes in a row mean it's probably armor
header. */
int type = is_armor_header( p, n );
if( afx->not_dash_escaped && type != BEGIN_SIGNATURE )
; /* this is okay */
else
{
if( type != BEGIN_SIGNATURE )
{
log_info(_("unexpected armor: "));
print_string( stderr, p, n, 0 );
putc('\n', stderr);
}
lastline = 1;
rc = -1;
}
}
else if(!afx->not_dash_escaped)
{
/* Bad dash-escaping. */
log_info(_("invalid dash escaped line: "));
print_string( stderr, p, n, 0 );
putc('\n', stderr);
}
}
/* Now handle the end-of-line canonicalization */
if( !afx->not_dash_escaped )
{
int crlf = n > 1 && p[n-2] == '\r' && p[n-1]=='\n';
/* PGP2 does not treat a tab as white space character */
afx->buffer_len = trim_trailing_chars( p, n,
afx->pgp2mode ? " \r\n" : " \t\r\n");
afx->buffer_len=
trim_trailing_chars( &p[afx->buffer_pos], n-afx->buffer_pos,
afx->pgp2mode ? " \r\n" : " \t\r\n");
afx->buffer_len+=afx->buffer_pos;
/* 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
@ -526,48 +602,23 @@ fake_packet( armor_filter_context_t *afx, iobuf_t a,
* faked packet could do the job).
*/
if( crlf )
afx->buffer[afx->buffer_len++] = '\r';
afx->buffer[afx->buffer_len++] = '\r';
afx->buffer[afx->buffer_len++] = '\n';
afx->buffer[afx->buffer_len] = 0;
}
p = afx->buffer;
n = afx->buffer_len;
if( n > 2 && *p == '-' ) {
/* check for dash escaped or armor header */
if( p[1] == ' ' && !afx->not_dash_escaped ) {
/* issue a warning if it is not regular encoded */
if( p[2] != '-' && !( n > 6 && !memcmp(p+2, "From ", 5))) {
log_info(_("invalid dash escaped line: "));
print_string( stderr, p, n, 0 );
putc('\n', stderr);
}
afx->buffer_pos = 2; /* skip */
}
else if( n >= 15 && p[1] == '-' && p[2] == '-' && p[3] == '-' ) {
int type = is_armor_header( p, n );
if( afx->not_dash_escaped && type != BEGIN_SIGNATURE )
; /* this is okay */
else {
if( type != BEGIN_SIGNATURE ) {
log_info(_("unexpected armor:"));
print_string( stderr, p, n, 0 );
putc('\n', stderr);
}
lastline = 1;
rc = -1;
}
}
}
afx->buffer[afx->buffer_len] = '\0';
}
}
buf[0] = (len-2) >> 8;
buf[1] = (len-2);
if( lastline ) { /* write last (ending) length header */
if( buf[0] || buf[1] ) { /* only if we have some text */
buf[len++] = 0;
buf[len++] = 0;
}
if(tempbuf_len<192)
buf[len++]=tempbuf_len;
else
{
buf[len++]=((tempbuf_len-192)/256) + 192;
buf[len++]=(tempbuf_len-192) % 256;
}
memcpy(&buf[len],tempbuf,tempbuf_len);
len+=tempbuf_len;
rc = 0;
afx->faked = 0;
afx->in_cleartext = 0;
@ -609,15 +660,15 @@ fake_packet( armor_filter_context_t *afx, iobuf_t a,
static int
invalid_crc(void)
{
if ( opt.ignore_crc_error )
return 0;
log_inc_errorcount();
return GPG_ERR_INV_ARMOR;
if ( opt.ignore_crc_error )
return 0;
log_inc_errorcount();
return gpg_error (GPG_ERR_INV_ARMOR);
}
static int
radix64_read( armor_filter_context_t *afx, iobuf_t a, size_t *retn,
radix64_read( armor_filter_context_t *afx, IOBUF a, size_t *retn,
byte *buf, size_t size )
{
byte val;
@ -676,7 +727,7 @@ radix64_read( armor_filter_context_t *afx, iobuf_t a, size_t *retn,
break;
}
else if( (c = asctobin[(c2=c)]) == 255 ) {
log_error(_("invalid radix64 character %02x skipped\n"), c2);
log_error(_("invalid radix64 character %02X skipped\n"), c2);
continue;
}
switch(idx) {
@ -755,13 +806,17 @@ radix64_read( armor_filter_context_t *afx, iobuf_t a, size_t *retn,
if( c == -1 ) {
log_info(_("premature eof (in CRC)\n"));
rc = invalid_crc();
}
}
else if( idx == 0 ) {
/* No CRC at all is legal ("MAY") */
rc=0;
}
else if( idx != 4 ) {
log_info(_("malformed CRC\n"));
rc = invalid_crc();
}
else if( mycrc != afx->crc ) {
log_info (_("CRC error; %06lx - %06lx\n"),
log_info (_("CRC error; %06lX - %06lX\n"),
(ulong)afx->crc, (ulong)mycrc);
rc = invalid_crc();
}
@ -781,12 +836,12 @@ radix64_read( armor_filter_context_t *afx, iobuf_t a, size_t *retn,
if( rc == -1 )
rc = 0;
else if( rc == 2 ) {
log_error(_("premature eof (in Trailer)\n"));
rc = GPG_ERR_INV_ARMOR;
log_error(_("premature eof (in trailer)\n"));
rc = G10ERR_INVALID_ARMOR;
}
else {
log_error(_("error in trailer line\n"));
rc = GPG_ERR_INV_ARMOR;
rc = G10ERR_INVALID_ARMOR;
}
#endif
}
@ -805,7 +860,7 @@ radix64_read( armor_filter_context_t *afx, iobuf_t a, size_t *retn,
*/
int
armor_filter( void *opaque, int control,
iobuf_t a, byte *buf, size_t *ret_len)
IOBUF a, byte *buf, size_t *ret_len)
{
size_t size = *ret_len;
armor_filter_context_t *afx = opaque;
@ -843,9 +898,10 @@ armor_filter( void *opaque, int control,
*ret_len = n;
}
else if( control == IOBUFCTRL_UNDERFLOW ) {
/* We need some space for the faked packet. The minmum required
* size is ~18 + length of the session marker */
if( size < 50 )
/* We need some space for the faked packet. The minmum
* required size is the PARTIAL_CHUNK size plus a byte for the
* length itself */
if( size < PARTIAL_CHUNK+1 )
BUG(); /* supplied buffer too short */
if( afx->faked )
@ -882,7 +938,7 @@ armor_filter( void *opaque, int control,
afx->pgp2mode = 1;
}
n=0;
/* first a gpg control packet */
/* 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;
@ -902,12 +958,16 @@ armor_filter( void *opaque, int control,
buf[n++] = DIGEST_ALGO_SHA512;
buf[1] = n - 2;
/* followed by a plaintext packet */
buf[n++] = 0xaf; /* old packet format, type 11, var length */
buf[n++] = 0; /* set the length header */
buf[n++] = 6;
/* ...followed by an invented plaintext packet.
Amusingly enough, this packet is not compliant with
2440 as the initial partial length is less than 512
bytes. Of course, we'll accept it anyway ;) */
buf[n++] = 0xCB; /* new packet format, type 11 */
buf[n++] = 0xE1; /* 2^1 == 2 bytes */
buf[n++] = 't'; /* canonical text mode */
buf[n++] = 0; /* namelength */
buf[n++] = 0xE2; /* 2^2 == 4 more bytes */
memset(buf+n, 0, 4); /* timestamp */
n += 4;
}
@ -926,35 +986,39 @@ armor_filter( void *opaque, int control,
else if( control == IOBUFCTRL_FLUSH && !afx->cancel ) {
if( !afx->status ) { /* write the header line */
const char *s;
STRLIST comment = opt.comments;
STRLIST comment=opt.comments;
if( afx->what >= DIM(head_strings) )
log_bug("afx->what=%d", afx->what);
iobuf_writestr(a, "-----");
iobuf_writestr(a, head_strings[afx->what] );
iobuf_writestr(a, "-----" LF );
iobuf_writestr(a, "-----" );
iobuf_writestr(a,afx->eol);
if( !opt.no_version )
{
iobuf_writestr(a, "Version: GnuPG v" VERSION " ("
PRINTABLE_OS_NAME ")" LF );
PRINTABLE_OS_NAME ")" );
iobuf_writestr(a,afx->eol);
}
/* Write the comment string. */
for(s=comment? comment->d:NULL; comment;
comment=comment->next,s=comment->d)
/* write the comment strings */
for(s=comment->d;comment;comment=comment->next,s=comment->d)
{
iobuf_writestr(a, "Comment: " );
for ( ; *s; s++ )
{
for( ; *s; s++ )
{
if( *s == '\n' )
iobuf_writestr(a, "\\n" );
iobuf_writestr(a, "\\n" );
else if( *s == '\r' )
iobuf_writestr(a, "\\r" );
iobuf_writestr(a, "\\r" );
else if( *s == '\v' )
iobuf_writestr(a, "\\v" );
iobuf_writestr(a, "\\v" );
else
iobuf_put(a, *s );
}
iobuf_writestr(a, LF );
}
iobuf_put(a, *s );
}
iobuf_writestr(a,afx->eol);
}
if ( afx->hdrlines ) {
for ( s = afx->hdrlines; *s; s++ ) {
@ -965,7 +1029,8 @@ armor_filter( void *opaque, int control,
iobuf_put(a, *s );
}
}
iobuf_writestr(a, LF );
iobuf_writestr(a,afx->eol);
afx->status++;
afx->idx = 0;
afx->idx2 = 0;
@ -994,10 +1059,11 @@ armor_filter( void *opaque, int control,
iobuf_put(a, c);
c = bintoasc[radbuf[2]&077];
iobuf_put(a, c);
if( ++idx2 >= (64/4) ) { /* pgp doesn't like 72 here */
iobuf_writestr(a, LF );
if( ++idx2 >= (64/4) )
{ /* pgp doesn't like 72 here */
iobuf_writestr(a,afx->eol);
idx2=0;
}
}
}
}
for(i=0; i < idx; i++ )
@ -1006,10 +1072,23 @@ armor_filter( void *opaque, int control,
afx->idx2 = idx2;
afx->crc = crc;
}
else if( control == IOBUFCTRL_INIT ) {
else if( control == IOBUFCTRL_INIT )
{
if( !is_initialized )
initialize();
}
initialize();
/* Figure out what we're using for line endings if the caller
didn't specify. */
if(afx->eol[0]==0)
{
#ifdef HAVE_DOSISH_SYSTEM
afx->eol[0]='\r';
afx->eol[1]='\n';
#else
afx->eol[0]='\n';
#endif
}
}
else if( control == IOBUFCTRL_CANCEL ) {
afx->cancel = 1;
}
@ -1038,14 +1117,15 @@ armor_filter( void *opaque, int control,
iobuf_put(a, c);
iobuf_put(a, '=');
}
if( ++idx2 >= (64/4) ) { /* pgp doesn't like 72 here */
iobuf_writestr(a, LF );
if( ++idx2 >= (64/4) )
{ /* pgp doesn't like 72 here */
iobuf_writestr(a,afx->eol);
idx2=0;
}
}
}
/* may need a linefeed */
if( idx2 )
iobuf_writestr(a, LF );
iobuf_writestr(a,afx->eol);
/* write the CRC */
iobuf_put(a, '=');
radbuf[0] = crc >>16;
@ -1059,13 +1139,14 @@ armor_filter( void *opaque, int control,
iobuf_put(a, c);
c = bintoasc[radbuf[2]&077];
iobuf_put(a, c);
iobuf_writestr(a, LF );
iobuf_writestr(a,afx->eol);
/* and the the trailer */
if( afx->what >= DIM(tail_strings) )
log_bug("afx->what=%d", afx->what);
iobuf_writestr(a, "-----");
iobuf_writestr(a, tail_strings[afx->what] );
iobuf_writestr(a, "-----" LF );
iobuf_writestr(a, "-----" );
iobuf_writestr(a,afx->eol);
}
else if( !afx->any_data && !afx->inp_bypass ) {
log_error(_("no valid OpenPGP data found.\n"));
@ -1079,7 +1160,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") );
xfree ( afx->buffer );
xfree( afx->buffer );
afx->buffer = NULL;
}
else if( control == IOBUFCTRL_DESC )
@ -1096,7 +1177,7 @@ make_radix64_string( const byte *data, size_t len )
{
char *buffer, *p;
buffer = p = xmalloc ( (len+2)/3*4 + 1 );
buffer = p = xmalloc( (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];
@ -1156,7 +1237,7 @@ unarmor_pump_new (void)
if( !is_initialized )
initialize();
x = xcalloc (1,sizeof *x);
x = xmalloc_clear (sizeof *x);
return x;
}
@ -1253,7 +1334,7 @@ unarmor_pump (UnarmorPump x, int c)
{
int c2;
if( (c = asctobin[(c2=c)]) == 255 ) {
log_error(_("invalid radix64 character %02x skipped\n"), c2);
log_error(_("invalid radix64 character %02X skipped\n"), c2);
break;
}
}
@ -1290,7 +1371,7 @@ unarmor_pump (UnarmorPump x, int c)
if( (c = asctobin[c]) == 255 ) {
rval = -1; /* ready */
if( x->crc != x->mycrc ) {
log_info (_("CRC error; %06lx - %06lx\n"),
log_info (_("CRC error; %06lX - %06lX\n"),
(ulong)x->crc, (ulong)x->mycrc);
if ( invalid_crc() )
rval = -3;

View File

@ -1,6 +1,6 @@
/* build-packet.c - assemble packets and write them
* Copyright (C) 1998, 1999, 2000, 2001, 2002,
* 2003 Free Software Foundation, Inc.
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
* 2006 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -16,7 +16,8 @@
*
* 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
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
#include <config.h>
@ -24,40 +25,38 @@
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <ctype.h>
#include "gpg.h"
#include "packet.h"
#include "errors.h"
#include "iobuf.h"
#include "mpi.h"
#include "util.h"
#include "cipher.h"
#include "memory.h"
#include "i18n.h"
#include "options.h"
static int do_comment( iobuf_t out, int ctb, PKT_comment *rem );
static int do_user_id( iobuf_t out, int ctb, PKT_user_id *uid );
static int do_public_key( iobuf_t out, int ctb, PKT_public_key *pk );
static int do_secret_key( iobuf_t out, int ctb, PKT_secret_key *pk );
static int do_symkey_enc( iobuf_t out, int ctb, PKT_symkey_enc *enc );
static int do_pubkey_enc( iobuf_t out, int ctb, PKT_pubkey_enc *enc );
static int do_user_id( IOBUF out, int ctb, PKT_user_id *uid );
static int do_public_key( IOBUF out, int ctb, PKT_public_key *pk );
static int do_secret_key( IOBUF out, int ctb, PKT_secret_key *pk );
static int do_symkey_enc( IOBUF out, int ctb, PKT_symkey_enc *enc );
static int do_pubkey_enc( IOBUF out, int ctb, PKT_pubkey_enc *enc );
static u32 calc_plaintext( PKT_plaintext *pt );
static int do_plaintext( iobuf_t out, int ctb, PKT_plaintext *pt );
static int do_encrypted( iobuf_t out, int ctb, PKT_encrypted *ed );
static int do_encrypted_mdc( iobuf_t out, int ctb, PKT_encrypted *ed );
static int do_compressed( iobuf_t out, int ctb, PKT_compressed *cd );
static int do_signature( iobuf_t out, int ctb, PKT_signature *sig );
static int do_onepass_sig( iobuf_t out, int ctb, PKT_onepass_sig *ops );
static int do_plaintext( IOBUF out, int ctb, PKT_plaintext *pt );
static int do_encrypted( IOBUF out, int ctb, PKT_encrypted *ed );
static int do_encrypted_mdc( IOBUF out, int ctb, PKT_encrypted *ed );
static int do_compressed( IOBUF out, int ctb, PKT_compressed *cd );
static int do_signature( IOBUF out, int ctb, PKT_signature *sig );
static int do_onepass_sig( IOBUF out, int ctb, PKT_onepass_sig *ops );
static int calc_header_length( u32 len, int new_ctb );
static int write_16(iobuf_t inp, u16 a);
static int write_32(iobuf_t inp, u32 a);
static int write_header( iobuf_t out, int ctb, u32 len );
static int write_sign_packet_header( iobuf_t out, int ctb, u32 len );
static int write_header2( iobuf_t out, int ctb, u32 len, int hdrlen, int blkmode );
static int write_new_header( iobuf_t out, int ctb, u32 len, int hdrlen );
static int write_version( iobuf_t out, int ctb );
static int write_16(IOBUF inp, u16 a);
static int write_32(IOBUF inp, u32 a);
static int write_header( IOBUF out, int ctb, u32 len );
static int write_sign_packet_header( IOBUF out, int ctb, u32 len );
static int write_header2( IOBUF out, int ctb, u32 len, int hdrlen );
static int write_new_header( IOBUF out, int ctb, u32 len, int hdrlen );
static int write_version( IOBUF out, int ctb );
/****************
* Build a packet and write it to INP
@ -66,7 +65,7 @@ static int write_version( iobuf_t out, int ctb );
* Note: Caller must free the packet
*/
int
build_packet( iobuf_t out, PACKET *pkt )
build_packet( IOBUF out, PACKET *pkt )
{
int new_ctb=0, rc=0, ctb;
int pkttype;
@ -75,30 +74,38 @@ build_packet( iobuf_t out, PACKET *pkt )
log_debug("build_packet() type=%d\n", pkt->pkttype );
assert( pkt->pkt.generic );
switch( (pkttype = pkt->pkttype) ) {
case PKT_OLD_COMMENT: pkttype = pkt->pkttype = PKT_COMMENT; break;
switch( (pkttype = pkt->pkttype) )
{
case PKT_PLAINTEXT: new_ctb = pkt->pkt.plaintext->new_ctb; break;
case PKT_ENCRYPTED:
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->attrib_data )
pkttype = PKT_ATTRIBUTE;
break;
if( pkt->pkt.user_id->attrib_data )
pkttype = PKT_ATTRIBUTE;
break;
default: break;
}
}
if( new_ctb || pkttype > 15 ) /* new format */
ctb = 0xc0 | (pkttype & 0x3f);
else
ctb = 0x80 | ((pkttype & 15)<<2);
switch( pkttype ) {
switch( pkttype )
{
case PKT_ATTRIBUTE:
case PKT_USER_ID:
rc = do_user_id( out, ctb, pkt->pkt.user_id );
break;
case PKT_OLD_COMMENT:
case PKT_COMMENT:
rc = do_comment( out, ctb, pkt->pkt.comment );
/*
Ignore these. Theoretically, this will never be called as
we have no way to output comment packets any longer, but
just in case there is some code path that would end up
outputting a comment that was written before comments were
dropped (in the public key?) this is a no-op.
*/
break;
case PKT_PUBLIC_SUBKEY:
case PKT_PUBLIC_KEY:
@ -138,11 +145,32 @@ build_packet( iobuf_t out, PACKET *pkt )
default:
log_bug("invalid packet type in build_packet()\n");
break;
}
}
return rc;
}
/*
* Write the mpi A to OUT.
*/
static int
mpi_write (iobuf_t out, gcry_mpi_t 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, &nbytes, a );
if( !rc )
rc = iobuf_write( out, buffer, nbytes );
return rc;
}
/****************
* calculate the length of a packet described by PKT
*/
@ -180,56 +208,42 @@ calc_packet_length( PACKET *pkt )
}
static void
write_fake_data( iobuf_t out, gcry_mpi_t a )
write_fake_data (IOBUF out, gcry_mpi_t a)
{
if( a ) {
unsigned int n;
void *p;
assert( gcry_mpi_get_flag (a, GCRYMPI_FLAG_OPAQUE));
p = gcry_mpi_get_opaque (a, &n);
iobuf_write (out, p, (n+7)/8);
if (a)
{
unsigned int n;
void *p;
p = gcry_mpi_get_opaque ( a, &n );
iobuf_write (out, p, (n+7)/8 );
}
}
static int
do_comment (iobuf_t out, int ctb, PKT_comment *rem)
do_user_id( IOBUF out, int ctb, PKT_user_id *uid )
{
int rc = 0;
int rc;
if (opt.sk_comments)
{
write_header(out, ctb, rem->len);
rc = iobuf_write( out, rem->data, rem->len );
}
return rc;
if( uid->attrib_data )
{
write_header(out, ctb, uid->attrib_len);
rc = iobuf_write( out, uid->attrib_data, uid->attrib_len );
}
else
{
write_header2( out, ctb, uid->len, 2 );
rc = iobuf_write( out, uid->name, uid->len );
}
return 0;
}
static int
do_user_id( iobuf_t out, int ctb, PKT_user_id *uid )
{
int rc;
if (uid->attrib_data)
{
write_header (out, ctb, uid->attrib_len);
rc = iobuf_write (out, uid->attrib_data, uid->attrib_len );
}
else
{
write_header (out, ctb, uid->len);
rc = iobuf_write (out, uid->name, uid->len );
}
return rc;
}
static int
do_public_key( iobuf_t out, int ctb, PKT_public_key *pk )
do_public_key( IOBUF out, int ctb, PKT_public_key *pk )
{
int rc = 0;
int n, i;
iobuf_t a = iobuf_temp();
IOBUF a = iobuf_temp();
if( !pk->version )
iobuf_put( a, 3 );
@ -251,99 +265,20 @@ do_public_key( iobuf_t out, int ctb, PKT_public_key *pk )
for(i=0; i < n; i++ )
mpi_write(a, pk->pkey[i] );
write_header2(out, ctb, iobuf_get_temp_length(a), pk->hdrbytes, 1 );
rc = iobuf_write_temp (out, a);
write_header2(out, ctb, iobuf_get_temp_length(a), pk->hdrbytes);
rc = iobuf_write_temp( out, a );
iobuf_close(a);
return rc;
}
/****************
* Make a hash value from the public key certificate
*/
void
hash_public_key( MD_HANDLE md, PKT_public_key *pk )
{
PACKET pkt;
int rc = 0;
int ctb;
ulong pktlen;
int c;
iobuf_t a = iobuf_temp();
#if 0
FILE *fp = fopen("dump.pk", "a");
int i=0;
fprintf(fp, "\nHashing PK (v%d):\n", pk->version);
#endif
/* build the packet */
init_packet(&pkt);
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_strerror (rc));
if( !(pk->version == 3 && pk->pubkey_algo == 16) ) {
/* skip the constructed header but don't do this for our very old
* v3 ElG keys */
ctb = iobuf_get_noeof(a);
pktlen = 0;
if( (ctb & 0x40) ) {
c = iobuf_get_noeof(a);
if( c < 192 )
pktlen = c;
else if( c < 224 ) {
pktlen = (c - 192) * 256;
c = iobuf_get_noeof(a);
pktlen += c + 192;
}
else if( c == 255 ) {
pktlen = iobuf_get_noeof(a) << 24;
pktlen |= iobuf_get_noeof(a) << 16;
pktlen |= iobuf_get_noeof(a) << 8;
pktlen |= iobuf_get_noeof(a);
}
}
else {
int lenbytes = ((ctb&3)==3)? 0 : (1<<(ctb & 3));
for( ; lenbytes; lenbytes-- ) {
pktlen <<= 8;
pktlen |= iobuf_get_noeof(a);
}
}
/* hash a header */
gcry_md_putc ( md, 0x99 );
pktlen &= 0xffff; /* can't handle longer packets */
gcry_md_putc ( md, pktlen >> 8 );
gcry_md_putc ( md, pktlen & 0xff );
}
/* hash the packet body */
while( (c=iobuf_get(a)) != -1 ) {
#if 0
fprintf( fp," %02x", c );
if( (++i == 24) ) {
putc('\n', fp);
i=0;
}
#endif
gcry_md_putc ( md, c );
}
#if 0
putc('\n', fp);
fclose(fp);
#endif
iobuf_cancel(a);
}
static int
do_secret_key( iobuf_t out, int ctb, PKT_secret_key *sk )
do_secret_key( IOBUF out, int ctb, PKT_secret_key *sk )
{
int rc = 0;
int i, nskey, npkey;
iobuf_t a = iobuf_temp(); /* build in a self-enlarging buffer */
IOBUF a = iobuf_temp(); /* build in a self-enlarging buffer */
/* Write the version number - if none is specified, use 3 */
if( !sk->version )
@ -371,7 +306,7 @@ do_secret_key( iobuf_t out, int ctb, PKT_secret_key *sk )
/* 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) gcry_mpi_t */
one blob in a faked (opaque) MPI */
if( !npkey ) {
write_fake_data( a, sk->skey[0] );
goto leave;
@ -415,9 +350,9 @@ do_secret_key( iobuf_t out, int ctb, PKT_secret_key *sk )
if( sk->protect.s2k.mode == 3 )
iobuf_put(a, sk->protect.s2k.count );
/* For our special modes 1001 and 1002 we do not need an IV */
if( sk->protect.s2k.mode != 1001
&& sk->protect.s2k.mode != 1002 )
/* For out special modes 1001, 1002 we do not need an IV */
if( sk->protect.s2k.mode != 1001
&& sk->protect.s2k.mode != 1002 )
iobuf_write(a, sk->protect.iv, sk->protect.ivlen );
}
}
@ -437,19 +372,21 @@ do_secret_key( iobuf_t out, int ctb, PKT_secret_key *sk )
else if( sk->is_protected && sk->version >= 4 ) {
/* The secret key is protected - write it out as it is */
byte *p;
assert( gcry_mpi_get_flag( sk->skey[npkey], GCRYMPI_FLAG_OPAQUE ) );
p = gcry_mpi_get_opaque( sk->skey[npkey], &i );
iobuf_write(a, p, (i+7)/8 );
unsigned int ndatabits;
assert (gcry_mpi_get_flag (sk->skey[npkey], GCRYMPI_FLAG_OPAQUE));
p = gcry_mpi_get_opaque (sk->skey[npkey], &ndatabits );
iobuf_write (a, p, (ndatabits+7)/8 );
}
else if( sk->is_protected ) {
/* The secret key is protected the old v4 way. */
/* The secret key is protected te old v4 way. */
for( ; i < nskey; i++ ) {
byte *p;
size_t n;
unsigned int ndatabits;
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 (gcry_mpi_get_flag (sk->skey[i], GCRYMPI_FLAG_OPAQUE));
p = gcry_mpi_get_opaque (sk->skey[i], &ndatabits);
iobuf_write (a, p, (ndatabits+7)/8);
}
write_16(a, sk->csum );
}
@ -463,19 +400,19 @@ do_secret_key( iobuf_t out, int ctb, PKT_secret_key *sk )
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 );
write_header2(out, ctb, iobuf_get_temp_length(a), sk->hdrbytes);
/* And finally write it out the real stream */
rc = iobuf_write_temp (out, a );
rc = iobuf_write_temp( out, a );
iobuf_close(a); /* close the remporary buffer */
return rc;
}
static int
do_symkey_enc( iobuf_t out, int ctb, PKT_symkey_enc *enc )
do_symkey_enc( IOBUF out, int ctb, PKT_symkey_enc *enc )
{
int rc = 0;
iobuf_t a = iobuf_temp();
IOBUF a = iobuf_temp();
assert( enc->version == 4 );
switch( enc->s2k.mode ) {
@ -495,21 +432,19 @@ do_symkey_enc( iobuf_t out, int ctb, PKT_symkey_enc *enc )
iobuf_write(a, enc->seskey, enc->seskeylen );
write_header(out, ctb, iobuf_get_temp_length(a) );
rc = iobuf_write_temp (out, a);
rc = iobuf_write_temp( out, a );
iobuf_close(a);
return rc;
}
static int
do_pubkey_enc( iobuf_t out, int ctb, PKT_pubkey_enc *enc )
do_pubkey_enc( IOBUF out, int ctb, PKT_pubkey_enc *enc )
{
int rc = 0;
int n, i;
iobuf_t a = iobuf_temp();
IOBUF a = iobuf_temp();
write_version( a, ctb );
if( enc->throw_keyid ) {
@ -528,55 +463,56 @@ do_pubkey_enc( iobuf_t out, int ctb, PKT_pubkey_enc *enc )
mpi_write(a, enc->data[i] );
write_header(out, ctb, iobuf_get_temp_length(a) );
rc = iobuf_write_temp (out, a);
rc = iobuf_write_temp( out, a );
iobuf_close(a);
return rc;
}
static u32
calc_plaintext( PKT_plaintext *pt )
{
return pt->len? (1 + 1 + pt->namelen + 4 + pt->len) : 0;
/* Truncate namelen to the maximum 255 characters. Note this means
that a function that calls build_packet with an illegal literal
packet will get it back legalized. */
if(pt->namelen>255)
pt->namelen=255;
return pt->len? (1 + 1 + pt->namelen + 4 + pt->len) : 0;
}
static int
do_plaintext( iobuf_t out, int ctb, PKT_plaintext *pt )
do_plaintext( IOBUF out, int ctb, PKT_plaintext *pt )
{
int i, rc = 0;
u32 n;
byte buf[1000]; /* this buffer has the plaintext! */
int nbytes;
/* Truncate namelen to the maximum 255 characters. This does mean
that a function that calls build_packet with an illegal literal
packet will get it back legalized. */
if(pt->namelen>255)
pt->namelen=255;
write_header(out, ctb, calc_plaintext( pt ) );
iobuf_put(out, pt->mode );
iobuf_put(out, pt->namelen );
for(i=0; i < pt->namelen; i++ )
iobuf_put(out, pt->name[i] );
rc = write_32 (out, pt->timestamp);
rc = write_32(out, pt->timestamp );
if (rc)
return rc;
n = 0;
while( (nbytes=iobuf_read(pt->buf, buf, 1000)) != -1 ) {
rc = iobuf_write(out, buf, nbytes);
if (rc)
break;
n += nbytes;
rc = iobuf_write (out, buf, nbytes);
if (rc)
break;
n += nbytes;
}
wipememory(buf,1000); /* burn the buffer */
if( !pt->len )
iobuf_set_block_mode(out, 0 ); /* write end marker */
else if( n != pt->len )
log_error("do_plaintext(): wrote %lu bytes but expected %lu bytes\n",
(ulong)n, (ulong)pt->len );
if( (ctb&0x40) && !pt->len )
iobuf_set_partial_block_mode(out, 0 ); /* turn off partial */
if( pt->len && n != pt->len )
log_error("do_plaintext(): wrote %lu bytes but expected %lu bytes\n",
(ulong)n, (ulong)pt->len );
return rc;
}
@ -584,7 +520,7 @@ do_plaintext( iobuf_t out, int ctb, PKT_plaintext *pt )
static int
do_encrypted( iobuf_t out, int ctb, PKT_encrypted *ed )
do_encrypted( IOBUF out, int ctb, PKT_encrypted *ed )
{
int rc = 0;
u32 n;
@ -598,7 +534,7 @@ do_encrypted( iobuf_t out, int ctb, PKT_encrypted *ed )
}
static int
do_encrypted_mdc( iobuf_t out, int ctb, PKT_encrypted *ed )
do_encrypted_mdc( IOBUF out, int ctb, PKT_encrypted *ed )
{
int rc = 0;
u32 n;
@ -617,7 +553,7 @@ do_encrypted_mdc( iobuf_t out, int ctb, PKT_encrypted *ed )
static int
do_compressed( iobuf_t out, int ctb, PKT_compressed *cd )
do_compressed( IOBUF out, int ctb, PKT_compressed *cd )
{
int rc = 0;
@ -626,7 +562,7 @@ do_compressed( iobuf_t out, int ctb, PKT_compressed *cd )
set, CTB is already formatted as new style and write_header2
does create a partial length encoding using new the new
style. */
write_header2(out, ctb, 0, 0, 0 );
write_header2(out, ctb, 0, 0);
iobuf_put(out, cd->algorithm );
/* This is all. The caller has to write the real data */
@ -734,6 +670,7 @@ build_sig_subpkt (PKT_signature *sig, sigsubpkttype_t type,
case SIGSUBPKT_NOTATION:
case SIGSUBPKT_POLICY:
case SIGSUBPKT_REV_KEY:
case SIGSUBPKT_SIGNATURE:
/* we do allow multiple subpackets */
break;
@ -803,18 +740,20 @@ build_sig_subpkt (PKT_signature *sig, sigsubpkttype_t type,
else
nlen = 1; /* just a 1 byte length header */
switch( type ) {
switch( type )
{
/* The issuer being unhashed is a historical oddity. It
should work equally as well hashed. Of course, if even an
unhashed issuer is tampered with, it makes it awfully hard
to verify the sig... */
case SIGSUBPKT_ISSUER:
case SIGSUBPKT_SIGNATURE:
hashed = 0;
break;
default:
hashed = 1;
break;
}
}
if( critical )
type |= SIGSUBPKT_FLAG_CRITICAL;
@ -966,12 +905,179 @@ build_attribute_subpkt(PKT_user_id *uid,byte type,
uid->attrib_len+=idx+headerlen+buflen;
}
struct notation *
string_to_notation(const char *string,int is_utf8)
{
const char *s;
int saw_at=0;
struct notation *notation;
notation=xmalloc_clear(sizeof(*notation));
if(*string=='-')
{
notation->flags.ignore=1;
string++;
}
if(*string=='!')
{
notation->flags.critical=1;
string++;
}
/* If and when the IETF assigns some official name tags, we'll have
to add them here. */
for( s=string ; *s != '='; s++ )
{
if( *s=='@')
saw_at++;
/* -notationname is legal without an = sign */
if(!*s && notation->flags.ignore)
break;
if( !*s || !isascii (*s) || (!isgraph(*s) && !isspace(*s)) )
{
log_error(_("a notation name must have only printable characters"
" or spaces, and end with an '='\n") );
goto fail;
}
}
notation->name=xmalloc((s-string)+1);
strncpy(notation->name,string,s-string);
notation->name[s-string]='\0';
if(!saw_at && !opt.expert)
{
log_error(_("a user notation name must contain the '@' character\n"));
goto fail;
}
if (saw_at > 1)
{
log_error(_("a notation name must not contain more than"
" one '@' character\n"));
goto fail;
}
if(*s)
{
const char *i=s+1;
int highbit=0;
/* we only support printable text - therefore we enforce the use
of only printable characters (an empty value is valid) */
for(s++; *s ; s++ )
{
if ( !isascii (*s) )
highbit=1;
else if (iscntrl(*s))
{
log_error(_("a notation value must not use any"
" control characters\n"));
goto fail;
}
}
if(!highbit || is_utf8)
notation->value=xstrdup(i);
else
notation->value=native_to_utf8(i);
}
return notation;
fail:
free_notation(notation);
return NULL;
}
struct notation *
sig_to_notation(PKT_signature *sig)
{
const byte *p;
size_t len;
int seq=0,crit;
struct notation *list=NULL;
while((p=enum_sig_subpkt(sig->hashed,SIGSUBPKT_NOTATION,&len,&seq,&crit)))
{
int n1,n2;
struct notation *n=NULL;
if(len<8)
{
log_info(_("WARNING: invalid notation data found\n"));
continue;
}
n1=(p[4]<<8)|p[5];
n2=(p[6]<<8)|p[7];
if(8+n1+n2!=len)
{
log_info(_("WARNING: invalid notation data found\n"));
continue;
}
n=xmalloc_clear(sizeof(*n));
n->name=xmalloc(n1+1);
memcpy(n->name,&p[8],n1);
n->name[n1]='\0';
if(p[0]&0x80)
{
n->value=xmalloc(n2+1);
memcpy(n->value,&p[8+n1],n2);
n->value[n2]='\0';
}
else
{
n->bdat=xmalloc(n2);
n->blen=n2;
memcpy(n->bdat,&p[8+n1],n2);
n->value=xmalloc(2+strlen(_("not human readable"))+2+1);
strcpy(n->value,"[ ");
strcat(n->value,_("not human readable"));
strcat(n->value," ]");
}
n->flags.critical=crit;
n->next=list;
list=n;
}
return list;
}
void
free_notation(struct notation *notation)
{
while(notation)
{
struct notation *n=notation;
xfree(n->name);
xfree(n->value);
xfree(n->altvalue);
xfree(n->bdat);
notation=n->next;
xfree(n);
}
}
static int
do_signature( iobuf_t out, int ctb, PKT_signature *sig )
do_signature( IOBUF out, int ctb, PKT_signature *sig )
{
int rc = 0;
int n, i;
iobuf_t a = iobuf_temp();
IOBUF a = iobuf_temp();
if( !sig->version )
iobuf_put( a, 3 );
@ -1013,7 +1119,7 @@ do_signature( iobuf_t out, int ctb, PKT_signature *sig )
write_sign_packet_header(out, ctb, iobuf_get_temp_length(a) );
else
write_header(out, ctb, iobuf_get_temp_length(a) );
rc = iobuf_write_temp (out, a);
rc = iobuf_write_temp( out, a );
iobuf_close(a);
return rc;
@ -1021,10 +1127,10 @@ do_signature( iobuf_t out, int ctb, PKT_signature *sig )
static int
do_onepass_sig( iobuf_t out, int ctb, PKT_onepass_sig *ops )
do_onepass_sig( IOBUF out, int ctb, PKT_onepass_sig *ops )
{
int rc = 0;
iobuf_t a = iobuf_temp();
IOBUF a = iobuf_temp();
write_version( a, ctb );
iobuf_put(a, ops->sig_class );
@ -1035,7 +1141,7 @@ do_onepass_sig( iobuf_t out, int ctb, PKT_onepass_sig *ops )
iobuf_put(a, ops->last );
write_header(out, ctb, iobuf_get_temp_length(a) );
rc = iobuf_write_temp (out, a);
rc = iobuf_write_temp( out, a );
iobuf_close(a);
return rc;
@ -1043,19 +1149,21 @@ do_onepass_sig( iobuf_t out, int ctb, PKT_onepass_sig *ops )
static int
write_16(iobuf_t out, u16 a)
write_16(IOBUF out, u16 a)
{
iobuf_put(out, a>>8);
return iobuf_put(out,a);
if( iobuf_put(out,a) )
return -1;
return 0;
}
static int
write_32(iobuf_t out, u32 a)
write_32(IOBUF out, u32 a)
{
iobuf_put(out, a>> 24);
iobuf_put(out, a>> 16);
iobuf_put(out, a>> 8);
return iobuf_put (out, a);
return iobuf_put(out, a);
}
@ -1088,14 +1196,14 @@ calc_header_length( u32 len, int new_ctb )
* Write the CTB and the packet length
*/
static int
write_header( iobuf_t out, int ctb, u32 len )
write_header( IOBUF out, int ctb, u32 len )
{
return write_header2( out, ctb, len, 0, 1 );
return write_header2( out, ctb, len, 0 );
}
static int
write_sign_packet_header( iobuf_t out, int ctb, u32 len )
write_sign_packet_header( IOBUF out, int ctb, u32 len )
{
/* work around a bug in the pgp read function for signature packets,
* which are not correctly coded and silently assume at some
@ -1106,57 +1214,66 @@ write_sign_packet_header( iobuf_t out, int ctb, u32 len )
}
/****************
* if HDRLEN is > 0, try to build a header of this length.
* we need this, so that we can hash packets without reading them again.
* If HDRLEN is > 0, try to build a header of this length. We need
* this so that we can hash packets without reading them again. If
* len is 0, write a partial or indeterminate length header, unless
* hdrlen is specified in which case write an actual zero length
* (using the specified hdrlen).
*/
static int
write_header2( iobuf_t out, int ctb, u32 len, int hdrlen, int blkmode )
write_header2( IOBUF out, int ctb, u32 len, int hdrlen )
{
if( ctb & 0x40 )
return write_new_header( out, ctb, len, hdrlen );
if( ctb & 0x40 )
return write_new_header( out, ctb, len, hdrlen );
if( hdrlen ) {
if( !len )
ctb |= 3;
else if( hdrlen == 2 && len < 256 )
;
else if( hdrlen == 3 && len < 65536 )
ctb |= 1;
else
ctb |= 2;
if( hdrlen )
{
if( hdrlen == 2 && len < 256 )
;
else if( hdrlen == 3 && len < 65536 )
ctb |= 1;
else
ctb |= 2;
}
else {
if( !len )
ctb |= 3;
else if( len < 256 )
;
else if( len < 65536 )
ctb |= 1;
else
ctb |= 2;
else
{
if( !len )
ctb |= 3;
else if( len < 256 )
;
else if( len < 65536 )
ctb |= 1;
else
ctb |= 2;
}
if( iobuf_put(out, ctb ) )
return -1;
if( !len ) {
if( blkmode )
iobuf_set_block_mode(out, 8196 );
}
else {
if( ctb & 2 ) {
iobuf_put(out, len >> 24 );
iobuf_put(out, len >> 16 );
}
if( ctb & 3 )
iobuf_put(out, len >> 8 );
if( iobuf_put(out, len ) )
if( iobuf_put(out, ctb ) )
return -1;
if( len || hdrlen )
{
if( ctb & 2 )
{
if(iobuf_put(out, len >> 24 ))
return -1;
if(iobuf_put(out, len >> 16 ))
return -1;
}
if( ctb & 3 )
if(iobuf_put(out, len >> 8 ))
return -1;
if( iobuf_put(out, len ) )
return -1;
}
return 0;
return 0;
}
static int
write_new_header( iobuf_t out, int ctb, u32 len, int hdrlen )
write_new_header( IOBUF out, int ctb, u32 len, int hdrlen )
{
if( hdrlen )
log_bug("can't cope with hdrlen yet\n");
@ -1195,7 +1312,7 @@ write_new_header( iobuf_t out, int ctb, u32 len, int hdrlen )
}
static int
write_version( iobuf_t out, int ctb )
write_version( IOBUF out, int ctb )
{
if( iobuf_put( out, 3 ) )
return -1;

View File

@ -18,8 +18,8 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if 0 /* lety Emacs display a red warning */
#error fixme: this shares a lof of code with the file in ../sm
#if 0 /* let Emacs display a red warning */
#error fixme: this shares a lot of code with the file in ../sm
#endif
#include <config.h>

View File

@ -1,5 +1,5 @@
/* card-util.c - Utility functions for the OpenPGP card.
* Copyright (C) 2003 Free Software Foundation, Inc.
* Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -15,7 +15,8 @@
*
* 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
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
#include <config.h>
@ -27,7 +28,7 @@
#if GNUPG_MAJOR_VERSION != 1
#include "gpg.h"
#endif
#endif /*GNUPG_MAJOR_VERSION != 1*/
#include "util.h"
#include "i18n.h"
#include "ttyio.h"
@ -36,10 +37,14 @@
#include "main.h"
#include "keyserver-internal.h"
#if GNUPG_MAJOR_VERSION == 1
#ifdef HAVE_LIBREADLINE
#include <stdio.h>
#include <readline/readline.h>
#endif /*HAVE_LIBREADLINE*/
#include "cardglue.h"
#else
#else /*GNUPG_MAJOR_VERSION!=1*/
#include "call-agent.h"
#endif
#endif /*GNUPG_MAJOR_VERSION!=1*/
#define CONTROL_D ('D' - 'A' + 1)
@ -63,21 +68,25 @@ change_pin (int chvno, int allow_admin)
log_info (_("OpenPGP card no. %s detected\n"),
info.serialno? info.serialno : "[none]");
agent_release_card_info (&info);
agent_clear_pin_cache (info.serialno);
if (opt.batch)
{
log_error (_("sorry, can't do this in batch mode\n"));
agent_release_card_info (&info);
log_error (_("can't do this in batch mode\n"));
return;
}
if(!allow_admin)
{
rc = agent_scd_change_pin (1);
rc = agent_scd_change_pin (1, info.serialno);
if (rc)
tty_printf ("Error changing the PIN: %s\n", gpg_strerror (rc));
else
tty_printf ("PIN changed.\n");
{
write_status (STATUS_SC_OP_SUCCESS);
tty_printf ("PIN changed.\n");
}
}
else
for (;;)
@ -99,33 +108,44 @@ change_pin (int chvno, int allow_admin)
rc = 0;
if (*answer == '1')
{
rc = agent_scd_change_pin (1);
rc = agent_scd_change_pin (1, info.serialno);
if (rc)
tty_printf ("Error changing the PIN: %s\n", gpg_strerror (rc));
else
tty_printf ("PIN changed.\n");
{
write_status (STATUS_SC_OP_SUCCESS);
tty_printf ("PIN changed.\n");
}
}
else if (*answer == '2')
{
rc = agent_scd_change_pin (101);
rc = agent_scd_change_pin (101, info.serialno);
if (rc)
tty_printf ("Error unblocking the PIN: %s\n", gpg_strerror (rc));
else
tty_printf ("PIN unblocked and new PIN set.\n");
}
{
write_status (STATUS_SC_OP_SUCCESS);
tty_printf ("PIN unblocked and new PIN set.\n");
}
}
else if (*answer == '3')
{
rc = agent_scd_change_pin (3);
rc = agent_scd_change_pin (3, info.serialno);
if (rc)
tty_printf ("Error changing the PIN: %s\n", gpg_strerror (rc));
else
tty_printf ("PIN changed.\n");
{
write_status (STATUS_SC_OP_SUCCESS);
tty_printf ("PIN changed.\n");
}
}
else if (*answer == 'q' || *answer == 'Q')
{
break;
}
}
agent_release_card_info (&info);
}
static const char *
@ -137,6 +157,8 @@ get_manufacturer (unsigned int no)
case 0:
case 0xffff: return "test card";
case 0x0001: return "PPC Card Systems";
case 0x0002: return "Prism";
case 0x0003: return "OpenFortress";
default: return "unknown";
}
}
@ -270,6 +292,8 @@ card_status (FILE *fp, char *serialno, size_t serialnobuflen)
PKT_public_key *pk = xcalloc (1, sizeof *pk);
int rc;
unsigned int uval;
const unsigned char *thefpr;
int i;
if (serialno && serialnobuflen)
*serialno = 0;
@ -346,6 +370,17 @@ card_status (FILE *fp, char *serialno, size_t serialnobuflen)
info.chvretry[0], info.chvretry[1], info.chvretry[2]);
fprintf (fp, "sigcount:%lu:::\n", info.sig_counter);
for (i=0; i < 4; i++)
{
if (info.private_do[i])
{
fprintf (fp, "private_do:%d:", i+1);
print_string (fp, info.private_do[i],
strlen (info.private_do[i]), ':');
fputs (":\n", fp);
}
}
fputs ("cafpr:", fp);
print_sha1_fpr_colon (fp, info.cafpr1valid? info.cafpr1:NULL);
print_sha1_fpr_colon (fp, info.cafpr2valid? info.cafpr2:NULL);
@ -356,7 +391,9 @@ card_status (FILE *fp, char *serialno, size_t serialnobuflen)
print_sha1_fpr_colon (fp, info.fpr2valid? info.fpr2:NULL);
print_sha1_fpr_colon (fp, info.fpr3valid? info.fpr3:NULL);
putc ('\n', fp);
fprintf (fp, "fprtime:%lu:%lu:%lu:\n",
(unsigned long)info.fpr1time, (unsigned long)info.fpr2time,
(unsigned long)info.fpr3time);
}
else
{
@ -377,6 +414,14 @@ card_status (FILE *fp, char *serialno, size_t serialnobuflen)
info.disp_sex == 2? _("female") : _("unspecified"));
print_name (fp, "URL of public key : ", info.pubkey_url);
print_name (fp, "Login data .......: ", info.login_data);
if (info.private_do[0])
print_name (fp, "Private DO 1 .....: ", info.private_do[0]);
if (info.private_do[1])
print_name (fp, "Private DO 2 .....: ", info.private_do[1]);
if (info.private_do[2])
print_name (fp, "Private DO 3 .....: ", info.private_do[2]);
if (info.private_do[3])
print_name (fp, "Private DO 4 .....: ", info.private_do[3]);
if (info.cafpr1valid)
{
tty_fprintf (fp, "CA fingerprint %d .:", 1);
@ -401,13 +446,48 @@ card_status (FILE *fp, char *serialno, size_t serialnobuflen)
tty_fprintf (fp, "Signature counter : %lu\n", info.sig_counter);
tty_fprintf (fp, "Signature key ....:");
print_sha1_fpr (fp, info.fpr1valid? info.fpr1:NULL);
if (info.fpr1valid && info.fpr1time)
tty_fprintf (fp, " created ....: %s\n",
isotimestamp (info.fpr1time));
tty_fprintf (fp, "Encryption key....:");
print_sha1_fpr (fp, info.fpr2valid? info.fpr2:NULL);
if (info.fpr2valid && info.fpr2time)
tty_fprintf (fp, " created ....: %s\n",
isotimestamp (info.fpr2time));
tty_fprintf (fp, "Authentication key:");
print_sha1_fpr (fp, info.fpr3valid? info.fpr3:NULL);
if (info.fpr3valid && info.fpr3time)
tty_fprintf (fp, " created ....: %s\n",
isotimestamp (info.fpr3time));
tty_fprintf (fp, "General key info..: ");
if (info.fpr1valid && !get_pubkey_byfprint (pk, info.fpr1, 20))
print_pubkey_info (fp, pk);
thefpr = (info.fpr1valid? info.fpr1 : info.fpr2valid? info.fpr2 :
info.fpr3valid? info.fpr3 : NULL);
if ( thefpr && !get_pubkey_byfprint (pk, thefpr, 20))
{
KBNODE keyblock = NULL;
print_pubkey_info (fp, pk);
if ( !get_seckeyblock_byfprint (&keyblock, thefpr, 20) )
print_card_key_info (fp, keyblock);
else if ( !get_keyblock_byfprint (&keyblock, thefpr, 20) )
{
release_kbnode (keyblock);
keyblock = NULL;
if (!auto_create_card_key_stub (info.serialno,
info.fpr1valid? info.fpr1:NULL,
info.fpr2valid? info.fpr2:NULL,
info.fpr3valid? info.fpr3:NULL))
{
if ( !get_seckeyblock_byfprint (&keyblock, thefpr, 20) )
print_card_key_info (fp, keyblock);
}
}
release_kbnode (keyblock);
}
else
tty_fprintf (fp, "[none]\n");
}
@ -483,8 +563,7 @@ change_name (void)
return -1;
}
log_debug ("setting Name to `%s'\n", isoname);
rc = agent_scd_setattr ("DISP-NAME", isoname, strlen (isoname) );
rc = agent_scd_setattr ("DISP-NAME", isoname, strlen (isoname), NULL );
if (rc)
log_error ("error setting Name: %s\n", gpg_strerror (rc));
@ -513,13 +592,16 @@ change_url (void)
return -1;
}
rc = agent_scd_setattr ("PUBKEY-URL", url, strlen (url) );
rc = agent_scd_setattr ("PUBKEY-URL", url, strlen (url), NULL );
if (rc)
log_error ("error setting URL: %s\n", gpg_strerror (rc));
xfree (url);
return rc;
}
/* Fetch the key from the URL given on the card or try to get it from
the default keyserver. */
static int
fetch_url(void)
{
@ -532,7 +614,7 @@ fetch_url(void)
rc=agent_scd_getattr("PUBKEY-URL",&info);
if(rc)
log_error("error retrieving URL from card: %s\n",gpg_strerror(rc));
else if(info.pubkey_url)
else
{
struct keyserver_spec *spec=NULL;
@ -540,9 +622,9 @@ fetch_url(void)
if(rc)
log_error("error retrieving key fingerprint from card: %s\n",
gpg_strerror(rc));
else
else if (info.pubkey_url && *info.pubkey_url)
{
spec=parse_keyserver_uri(info.pubkey_url,0,NULL,0);
spec=parse_keyserver_uri(info.pubkey_url,1,NULL,0);
if(spec && info.fpr1valid)
{
/* This is not perfectly right. Currently, all card
@ -556,9 +638,11 @@ fetch_url(void)
free_keyserver_spec(spec);
}
}
else if (info.fpr1valid)
{
rc = keyserver_import_fprint (info.fpr1, 20, opt.keyserver);
}
}
else
log_error("no URL set on card\n");
return rc;
#else
@ -624,13 +708,82 @@ change_login (const char *args)
return -1;
}
rc = agent_scd_setattr ("LOGIN-DATA", data, n );
rc = agent_scd_setattr ("LOGIN-DATA", data, n, NULL );
if (rc)
log_error ("error setting login data: %s\n", gpg_strerror (rc));
xfree (data);
return rc;
}
static int
change_private_do (const char *args, int nr)
{
char do_name[] = "PRIVATE-DO-X";
char *data;
int n;
int rc;
assert (nr >= 1 && nr <= 4);
do_name[11] = '0' + nr;
if (args && (args = strchr (args, '<'))) /* Read it from a file */
{
FILE *fp;
/* Fixme: Factor this duplicated code out. */
for (args++; spacep (args); args++)
;
fp = fopen (args, "rb");
#if GNUPG_MAJOR_VERSION == 1
if (fp && is_secured_file (fileno (fp)))
{
fclose (fp);
fp = NULL;
errno = EPERM;
}
#endif
if (!fp)
{
tty_printf (_("can't open `%s': %s\n"), args, strerror (errno));
return -1;
}
data = xmalloc (254);
n = fread (data, 1, 254, fp);
fclose (fp);
if (n < 0)
{
tty_printf (_("error reading `%s': %s\n"), args, strerror (errno));
xfree (data);
return -1;
}
}
else
{
data = cpr_get ("cardedit.change_private_do",
_("Private DO data: "));
if (!data)
return -1;
trim_spaces (data);
cpr_kill_prompt ();
n = strlen (data);
}
if (n > 254 )
{
tty_printf (_("Error: Private DO too long "
"(limit is %d characters).\n"), 254);
xfree (data);
return -1;
}
rc = agent_scd_setattr (do_name, data, n, NULL );
if (rc)
log_error ("error setting private DO: %s\n", gpg_strerror (rc));
xfree (data);
return rc;
}
static int
change_lang (void)
{
@ -660,7 +813,7 @@ change_lang (void)
return -1;
}
rc = agent_scd_setattr ("DISP-LANG", data, strlen (data) );
rc = agent_scd_setattr ("DISP-LANG", data, strlen (data), NULL );
if (rc)
log_error ("error setting lang: %s\n", gpg_strerror (rc));
xfree (data);
@ -695,7 +848,7 @@ change_sex (void)
return -1;
}
rc = agent_scd_setattr ("DISP-SEX", str, 1 );
rc = agent_scd_setattr ("DISP-SEX", str, 1, NULL );
if (rc)
log_error ("error setting sex: %s\n", gpg_strerror (rc));
xfree (data);
@ -740,7 +893,7 @@ change_cafpr (int fprno)
rc = agent_scd_setattr (fprno==1?"CA-FPR-1":
fprno==2?"CA-FPR-2":
fprno==3?"CA-FPR-3":"x", fpr, 20 );
fprno==3?"CA-FPR-3":"x", fpr, 20, NULL );
if (rc)
log_error ("error setting cafpr: %s\n", gpg_strerror (rc));
return rc;
@ -765,7 +918,7 @@ toggle_forcesig (void)
newstate = !info.chv1_cached;
agent_release_card_info (&info);
rc = agent_scd_setattr ("CHV-STATUS-1", newstate? "\x01":"", 1);
rc = agent_scd_setattr ("CHV-STATUS-1", newstate? "\x01":"", 1, NULL);
if (rc)
log_error ("error toggling signature PIN flag: %s\n", gpg_strerror (rc));
}
@ -803,12 +956,14 @@ check_pin_for_key_operation (struct agent_card_info_s *info, int *forced_chv1)
{
int rc = 0;
agent_clear_pin_cache (info->serialno);
*forced_chv1 = !info->chv1_cached;
if (*forced_chv1)
{ /* Switch of the forced mode so that during key generation we
don't get bothered with PIN queries for each
self-signature. */
rc = agent_scd_setattr ("CHV-STATUS-1", "\x01", 1);
rc = agent_scd_setattr ("CHV-STATUS-1", "\x01", 1, info->serialno);
if (rc)
{
log_error ("error clearing forced signature PIN flag: %s\n",
@ -836,7 +991,7 @@ restore_forced_chv1 (int *forced_chv1)
if (*forced_chv1)
{ /* Switch back to forced state. */
rc = agent_scd_setattr ("CHV-STATUS-1", "", 1);
rc = agent_scd_setattr ("CHV-STATUS-1", "", 1, NULL);
if (rc)
{
log_error ("error setting forced signature PIN flag: %s\n",
@ -900,7 +1055,7 @@ generate_card_keys (const char *serialno)
want_backup=answer_is_yes_no_default(answer,1);
cpr_kill_prompt();
m_free(answer);
xfree(answer);
}
#else
want_backup = cpr_get_answer_is_yes
@ -949,7 +1104,7 @@ generate_card_keys (const char *serialno)
}
/* This fucntion is used by the key edit menu to generate an arbitrary
/* This function is used by the key edit menu to generate an arbitrary
subkey. */
int
card_generate_subkey (KBNODE pub_keyblock, KBNODE sec_keyblock)
@ -1007,9 +1162,10 @@ card_generate_subkey (KBNODE pub_keyblock, KBNODE sec_keyblock)
}
/* Store the subkey at NODE into the smartcard and modify NODE to
carry the serrialno stuff instead of the actual secret key
parameters. */
/* Store the key at NODE into the smartcard and modify NODE to
carry the serialno stuff instead of the actual secret key
parameters. USE is the usage for that key; 0 means any
usage. */
int
card_store_subkey (KBNODE node, int use)
{
@ -1140,49 +1296,101 @@ card_store_subkey (KBNODE node, int use)
}
/* Data used by the command parser. This needs to be outside of the
function scope to allow readline based command completion. */
enum cmdids
{
cmdNOP = 0,
cmdQUIT, cmdADMIN, cmdHELP, cmdLIST, cmdDEBUG, cmdVERIFY,
cmdNAME, cmdURL, cmdFETCH, cmdLOGIN, cmdLANG, cmdSEX, cmdCAFPR,
cmdFORCESIG, cmdGENERATE, cmdPASSWD, cmdPRIVATEDO,
cmdINVCMD
};
static struct
{
const char *name;
enum cmdids id;
int admin_only;
const char *desc;
} cmds[] =
{
{ "quit" , cmdQUIT , 0, N_("quit this menu")},
{ "q" , cmdQUIT , 0, NULL },
{ "admin" , cmdADMIN , 0, N_("show admin commands")},
{ "help" , cmdHELP , 0, N_("show this help")},
{ "?" , cmdHELP , 0, NULL },
{ "list" , cmdLIST , 0, N_("list all available data")},
{ "l" , cmdLIST , 0, NULL },
{ "debug" , cmdDEBUG , 0, NULL },
{ "name" , cmdNAME , 1, N_("change card holder's name")},
{ "url" , cmdURL , 1, N_("change URL to retrieve key")},
{ "fetch" , cmdFETCH , 0, N_("fetch the key specified in the card URL")},
{ "login" , cmdLOGIN , 1, N_("change the login name")},
{ "lang" , cmdLANG , 1, N_("change the language preferences")},
{ "sex" , cmdSEX , 1, N_("change card holder's sex")},
{ "cafpr" , cmdCAFPR , 1, N_("change a CA fingerprint")},
{ "forcesig", cmdFORCESIG, 1, N_("toggle the signature force PIN flag")},
{ "generate", cmdGENERATE, 1, N_("generate new keys")},
{ "passwd" , cmdPASSWD, 0, N_("menu to change or unblock the PIN")},
{ "verify" , cmdVERIFY, 0, N_("verify the PIN and list all data")},
/* Note, that we do not announce this command yet. */
{ "privatedo", cmdPRIVATEDO, 0, NULL },
{ NULL, cmdINVCMD, 0, NULL }
};
#if GNUPG_MAJOR_VERSION == 1 && defined (HAVE_LIBREADLINE)
/* These two functions are used by readline for command completion. */
static char *
command_generator(const char *text,int state)
{
static int list_index,len;
const char *name;
/* If this is a new word to complete, initialize now. This includes
saving the length of TEXT for efficiency, and initializing the
index variable to 0. */
if(!state)
{
list_index=0;
len=strlen(text);
}
/* Return the next partial match */
while((name=cmds[list_index].name))
{
/* Only complete commands that have help text */
if(cmds[list_index++].desc && strncmp(name,text,len)==0)
return strdup(name);
}
return NULL;
}
static char **
card_edit_completion(const char *text, int start, int end)
{
/* If we are at the start of a line, we try and command-complete.
If not, just do nothing for now. */
if(start==0)
return rl_completion_matches(text,command_generator);
rl_attempted_completion_over=1;
return NULL;
}
#endif /* GNUPG_MAJOR_VERSION == 1 && HAVE_LIBREADLINE */
/* Menu to edit all user changeable values on an OpenPGP card. Only
Key creation is not handled here. */
void
card_edit (STRLIST commands)
{
enum cmdids {
cmdNOP = 0,
cmdQUIT, cmdADMIN, cmdHELP, cmdLIST, cmdDEBUG,
cmdNAME, cmdURL, cmdFETCH, cmdLOGIN, cmdLANG, cmdSEX, cmdCAFPR,
cmdFORCESIG, cmdGENERATE, cmdPASSWD,
cmdINVCMD
};
static struct {
const char *name;
enum cmdids id;
int admin_only;
const char *desc;
} cmds[] = {
{ N_("quit") , cmdQUIT , 0, N_("quit this menu") },
{ N_("q") , cmdQUIT , 0, NULL },
{ N_("admin") , cmdADMIN , 0, N_("show admin commands") },
{ N_("help") , cmdHELP , 0, N_("show this help") },
{ "?" , cmdHELP , 0, NULL },
{ N_("list") , cmdLIST , 0, N_("list all available data") },
{ N_("l") , cmdLIST , 0, NULL },
{ N_("debug") , cmdDEBUG , 0, NULL },
{ N_("name") , cmdNAME , 1, N_("change card holder's name") },
{ N_("url") , cmdURL , 1, N_("change URL to retrieve key") },
{ N_("fetch") , cmdFETCH , 0,
N_("fetch the key specified in the card URL") },
{ N_("login") , cmdLOGIN , 1, N_("change the login name") },
{ N_("lang") , cmdLANG , 1, N_("change the language preferences") },
{ N_("sex") , cmdSEX , 1, N_("change card holder's sex") },
{ N_("cafpr"), cmdCAFPR, 1, N_("change a CA fingerprint") },
{ N_("forcesig"),
cmdFORCESIG, 1, N_("toggle the signature force PIN flag") },
{ N_("generate"),
cmdGENERATE, 1, N_("generate new keys") },
{ N_("passwd"), cmdPASSWD, 0, N_("menu to change or unblock the PIN") },
{ NULL, cmdINVCMD, 0, NULL }
};
enum cmdids cmd = cmdNOP;
int have_commands = !!commands;
int redisplay = 1;
@ -1195,7 +1403,7 @@ card_edit (STRLIST commands)
;
else if (opt.batch && !have_commands)
{
log_error(_("can't do that in batchmode\n"));
log_error(_("can't do this in batch mode\n"));
goto leave;
}
@ -1243,8 +1451,14 @@ card_edit (STRLIST commands)
if (!have_commands)
{
#if GNUPG_MAJOR_VERSION == 1
tty_enable_completion (card_edit_completion);
#endif
answer = cpr_get_no_help("cardedit.prompt", _("Command> "));
cpr_kill_prompt();
#if GNUPG_MAJOR_VERSION == 1
tty_disable_completion ();
#endif
}
trim_spaces(answer);
}
@ -1292,9 +1506,33 @@ card_edit (STRLIST commands)
break;
case cmdADMIN:
allow_admin=!allow_admin;
if ( !strcmp (arg_string, "on") )
allow_admin = 1;
else if ( !strcmp (arg_string, "off") )
allow_admin = 0;
else if ( !strcmp (arg_string, "verify") )
{
/* Force verification of the Admin Command. However,
this is only done if the retry counter is at initial
state. */
char *tmp = xmalloc (strlen (serialnobuf) + 6 + 1);
strcpy (stpcpy (tmp, serialnobuf), "[CHV3]");
allow_admin = !agent_scd_checkpin (tmp);
xfree (tmp);
}
else /* Toggle. */
allow_admin=!allow_admin;
if(allow_admin)
tty_printf(_("Admin commands are allowed\n"));
else
tty_printf(_("Admin commands are not allowed\n"));
break;
case cmdVERIFY:
agent_scd_checkpin (serialnobuf);
redisplay = 1;
break;
case cmdLIST:
redisplay = 1;
break;
@ -1331,6 +1569,14 @@ card_edit (STRLIST commands)
change_cafpr (arg_number);
break;
case cmdPRIVATEDO:
if ( arg_number < 1 || arg_number > 4 )
tty_printf ("usage: privatedo N\n"
" 1 <= N <= 4\n");
else
change_private_do (arg_string, arg_number);
break;
case cmdFORCESIG:
toggle_forcesig ();
break;

View File

@ -1,5 +1,6 @@
/* cipher.c - En-/De-ciphering filter
* Copyright (C) 1998, 1999, 2000, 2001, 2003 Free Software Foundation, Inc.
* Copyright (C) 1998, 1999, 2000, 2001, 2003,
* 2006 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -15,7 +16,8 @@
*
* 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
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
#include <config.h>
@ -28,7 +30,6 @@
#include "gpg.h"
#include "errors.h"
#include "iobuf.h"
#include "memory.h"
#include "util.h"
#include "filter.h"
#include "packet.h"
@ -41,17 +42,17 @@
static void
write_header( cipher_filter_context_t *cfx, iobuf_t a )
write_header( cipher_filter_context_t *cfx, IOBUF a )
{
gcry_error_t err;
PACKET pkt;
PKT_encrypted ed;
byte temp[18];
unsigned int blocksize;
unsigned int nprefix;
gpg_error_t rc;
blocksize = gcry_cipher_get_algo_blklen ( cfx->dek->algo );
if( blocksize < 8 || blocksize > 16 )
blocksize = gcry_cipher_algo_blklen (cfx->dek->algo);
if ( blocksize < 8 || blocksize > 16 )
log_fatal("unsupported blocksize %u\n", blocksize );
memset( &ed, 0, sizeof ed );
@ -60,9 +61,9 @@ write_header( cipher_filter_context_t *cfx, iobuf_t a )
ed.new_ctb = !ed.len && !RFC1991;
if( cfx->dek->use_mdc ) {
ed.mdc_method = DIGEST_ALGO_SHA1;
gcry_md_open (&cfx->mdc_hash, GCRY_MD_SHA1, 0 );
gcry_md_open (&cfx->mdc_hash, DIGEST_ALGO_SHA1, 0);
if ( DBG_HASHING )
gcry_md_start_debug ( cfx->mdc_hash, "creatmdc" );
gcry_md_start_debug (cfx->mdc_hash, "creatmdc");
}
{
@ -78,28 +79,31 @@ write_header( cipher_filter_context_t *cfx, iobuf_t a )
if( build_packet( a, &pkt ))
log_bug("build_packet(ENCR_DATA) failed\n");
nprefix = blocksize;
gcry_randomize ( temp, nprefix, GCRY_STRONG_RANDOM);
gcry_randomize (temp, nprefix, GCRY_STRONG_RANDOM );
temp[nprefix] = temp[nprefix-2];
temp[nprefix+1] = temp[nprefix-1];
print_cipher_algo_note( cfx->dek->algo );
rc = gcry_cipher_open (&cfx->cipher_hd, cfx->dek->algo,
GCRY_CIPHER_MODE_CFB,
GCRY_CIPHER_SECURE
| ((cfx->dek->use_mdc || cfx->dek->algo >= 100) ?
0 : GCRY_CIPHER_ENABLE_SYNC));
err = gcry_cipher_open (&cfx->cipher_hd,
cfx->dek->algo,
GCRY_CIPHER_MODE_CFB,
(GCRY_CIPHER_SECURE
| ((cfx->dek->use_mdc || cfx->dek->algo >= 100)?
0 : GCRY_CIPHER_ENABLE_SYNC));
if (rc) {
/* we should never get an error here cause we already checked, that
* the algorithm is available. */
/* We should never get an error here cause we already checked,
* that the algorithm is available. */
BUG();
}
/* log_hexdump( "thekey", cfx->dek->key, cfx->dek->keylen );*/
gcry_cipher_setkey( cfx->cipher_hd, cfx->dek->key, cfx->dek->keylen );
gcry_cipher_setiv( cfx->cipher_hd, NULL, 0 );
/* log_hexdump( "prefix", temp, nprefix+2 ); */
if( cfx->mdc_hash ) /* hash the "IV" */
gcry_md_write( cfx->mdc_hash, temp, nprefix+2 );
gcry_cipher_encrypt( cfx->cipher_hd, temp, nprefix+2, NULL, 0);
gcry_cipher_sync( cfx->cipher_hd );
if (cfx->mdc_hash) /* Hash the "IV". */
gcry_md_write (cfx->mdc_hash, temp, nprefix+2 );
gcry_cipher_encrypt (cfx->cipher_hd, temp, nprefix+2, NULL, 0);
gcry_cipher_sync (cfx->cipher_hd);
iobuf_write(a, temp, nprefix+2);
cfx->header=1;
}
@ -111,7 +115,7 @@ write_header( cipher_filter_context_t *cfx, iobuf_t a )
*/
int
cipher_filter( void *opaque, int control,
iobuf_t a, byte *buf, size_t *ret_len)
IOBUF a, byte *buf, size_t *ret_len)
{
size_t size = *ret_len;
cipher_filter_context_t *cfx = opaque;
@ -125,32 +129,31 @@ cipher_filter( void *opaque, int control,
if( !cfx->header ) {
write_header( cfx, a );
}
if( cfx->mdc_hash )
gcry_md_write( cfx->mdc_hash, buf, size );
gcry_cipher_encrypt( cfx->cipher_hd, buf, size, NULL, 0);
if (cfx->mdc_hash)
gcry_md_write (cfx->mdc_hash, buf, size);
gcry_cipher_encrypt (cfx->cipher_hd, buf, size, NULL, 0);
rc = iobuf_write( a, buf, size );
}
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 = gcry_md_get_algo_dlen (gcry_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] );
gcry_md_putc (cfx->mdc_hash, temp[0]);
gcry_md_putc (cfx->mdc_hash, temp[1]);
gcry_md_final ( cfx->mdc_hash );
hash = gcry_md_read ( cfx->mdc_hash, 0 );
gcry_md_final (cfx->mdc_hash);
hash = gcry_md_read (cfx->mdc_hash, 0);
memcpy(temp+2, hash, 20);
gcry_cipher_encrypt( cfx->cipher_hd, temp, 22, NULL, 0 );
gcry_md_close ( cfx->mdc_hash ); cfx->mdc_hash = NULL;
rc = iobuf_write( a, temp, 22 );
if (rc)
gcry_cipher_encrypt (cfx->cipher_hd, temp, 22, NULL, 0);
gcry_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);
@ -160,6 +163,3 @@ cipher_filter( void *opaque, int control,
}
return rc;
}

View File

@ -1,6 +1,6 @@
/* compress.c - compress filter
* Copyright (C) 1998, 1999, 2000, 2001, 2002,
* 2003 Free Software Foundation, Inc.
* 2003, 2006 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -16,9 +16,16 @@
*
* 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
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
/* Note that the code in compress-bz2.c is nearly identical to the
code here, so if you fix a bug here, look there to see if a
matching bug needs to be fixed. I tried to have one set of
functions that could do ZIP, ZLIB, and BZIP2, but it became
dangerously unreadable with #ifdefs and if(algo) -dshaw */
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
@ -27,43 +34,42 @@
#include <assert.h>
#include <errno.h>
#include <zlib.h>
#ifdef __riscos__
#if defined(__riscos__) && defined(USE_ZLIBRISCOS)
# include "zlib-riscos.h"
#endif
#endif
#include "gpg.h"
#include "util.h"
#include "memory.h"
#include "packet.h"
#include "filter.h"
#include "main.h"
#include "options.h"
int compress_filter_bz2( void *opaque, int control,
IOBUF a, byte *buf, size_t *ret_len);
static void
init_compress( compress_filter_context_t *zfx, z_stream *zs )
{
int rc;
int level;
#ifdef __riscos__
#if defined(__riscos__) && defined(USE_ZLIBRISCOS)
static int zlib_initialized = 0;
if (!zlib_initialized)
zlib_initialized = riscos_load_module("ZLib", zlib_path, 1);
#endif
if( opt.compress >= 0 && opt.compress <= 9 )
level = opt.compress;
else if( opt.compress == -1 )
if( opt.compress_level >= 1 && opt.compress_level <= 9 )
level = opt.compress_level;
else if( opt.compress_level == -1 )
level = Z_DEFAULT_COMPRESSION;
else if( opt.compress == 10 ) /* remove this ! */
level = 0;
else {
log_error("invalid compression level; using default level\n");
level = Z_DEFAULT_COMPRESSION;
}
if( (rc = zfx->algo == 1? deflateInit2( zs, level, Z_DEFLATED,
-13, 8, Z_DEFAULT_STRATEGY)
: deflateInit( zs, level )
@ -75,13 +81,13 @@ init_compress( compress_filter_context_t *zfx, z_stream *zs )
}
zfx->outbufsize = 8192;
zfx->outbuf = xmalloc ( zfx->outbufsize );
zfx->outbuf = xmalloc( zfx->outbufsize );
}
static int
do_compress( compress_filter_context_t *zfx, z_stream *zs, int flush, iobuf_t a )
do_compress( compress_filter_context_t *zfx, z_stream *zs, int flush, IOBUF a )
{
gpg_error_t rc;
int rc;
int zrc;
unsigned n;
@ -111,12 +117,10 @@ do_compress( compress_filter_context_t *zfx, z_stream *zs, int flush, iobuf_t a
(unsigned)zs->avail_in, (unsigned)zs->avail_out,
(unsigned)n, zrc );
rc = iobuf_write (a, zfx->outbuf, n);
if (rc)
{
if( (rc=iobuf_write( a, zfx->outbuf, n )) ) {
log_debug("deflate: iobuf_write failed\n");
return rc;
}
}
} while( zs->avail_in || (flush == Z_FINISH && zrc != Z_STREAM_END) );
return 0;
}
@ -145,13 +149,13 @@ init_uncompress( compress_filter_context_t *zfx, z_stream *zs )
}
zfx->inbufsize = 2048;
zfx->inbuf = xmalloc ( zfx->inbufsize );
zfx->inbuf = xmalloc( zfx->inbufsize );
zs->avail_in = 0;
}
static int
do_uncompress( compress_filter_context_t *zfx, z_stream *zs,
iobuf_t a, size_t *ret_len )
IOBUF a, size_t *ret_len )
{
int zrc;
int rc=0;
@ -213,9 +217,9 @@ do_uncompress( compress_filter_context_t *zfx, z_stream *zs,
return rc;
}
int
static int
compress_filter( void *opaque, int control,
iobuf_t a, byte *buf, size_t *ret_len)
IOBUF a, byte *buf, size_t *ret_len)
{
size_t size = *ret_len;
compress_filter_context_t *zfx = opaque;
@ -224,7 +228,7 @@ compress_filter( void *opaque, int control,
if( control == IOBUFCTRL_UNDERFLOW ) {
if( !zfx->status ) {
zs = zfx->opaque = xcalloc (1, sizeof *zs );
zs = zfx->opaque = xmalloc_clear( sizeof *zs );
init_uncompress( zfx, zs );
zfx->status = 1;
}
@ -242,10 +246,8 @@ compress_filter( void *opaque, int control,
if( !zfx->status ) {
PACKET pkt;
PKT_compressed cd;
if( !zfx->algo )
zfx->algo = DEFAULT_COMPRESS_ALGO;
if( zfx->algo != 1 && zfx->algo != 2 )
if(zfx->algo != COMPRESS_ALGO_ZIP
&& zfx->algo != COMPRESS_ALGO_ZLIB)
BUG();
memset( &cd, 0, sizeof cd );
cd.len = 0;
@ -255,7 +257,7 @@ 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 = xcalloc (1, sizeof *zs );
zs = zfx->opaque = xmalloc_clear( sizeof *zs );
init_compress( zfx, zs );
zfx->status = 2;
}
@ -271,9 +273,9 @@ compress_filter( void *opaque, int control,
else if( control == IOBUFCTRL_FREE ) {
if( zfx->status == 1 ) {
inflateEnd(zs);
xfree (zs);
xfree(zs);
zfx->opaque = NULL;
xfree (zfx->outbuf); zfx->outbuf = NULL;
xfree(zfx->outbuf); zfx->outbuf = NULL;
}
else if( zfx->status == 2 ) {
#ifndef __riscos__
@ -284,9 +286,9 @@ compress_filter( void *opaque, int control,
zs->avail_in = 0;
do_compress( zfx, zs, Z_FINISH, a );
deflateEnd(zs);
xfree (zs);
xfree(zs);
zfx->opaque = NULL;
xfree (zfx->outbuf); zfx->outbuf = NULL;
xfree(zfx->outbuf); zfx->outbuf = NULL;
}
if (zfx->release)
zfx->release (zfx);
@ -308,17 +310,17 @@ release_context (compress_filter_context_t *ctx)
*/
int
handle_compressed( void *procctx, PKT_compressed *cd,
int (*callback)(iobuf_t, void *), void *passthru )
int (*callback)(IOBUF, void *), void *passthru )
{
compress_filter_context_t *cfx;
int rc;
if( cd->algorithm < 1 || cd->algorithm > 2 )
return GPG_ERR_COMPR_ALGO;
cfx = xcalloc (1,sizeof *cfx);
cfx->algo = cd->algorithm;
if(check_compress_algo(cd->algorithm))
return G10ERR_COMPR_ALGO;
cfx = xmalloc_clear (sizeof *cfx);
cfx->release = release_context;
iobuf_push_filter( cd->buf, compress_filter, cfx );
cfx->algo = cd->algorithm;
push_compress_filter(cd->buf,cfx,cd->algorithm);
if( callback )
rc = callback(cd->buf, passthru );
else
@ -327,3 +329,38 @@ handle_compressed( void *procctx, PKT_compressed *cd,
return rc;
}
void
push_compress_filter(IOBUF out,compress_filter_context_t *zfx,int algo)
{
push_compress_filter2(out,zfx,algo,0);
}
void
push_compress_filter2(IOBUF out,compress_filter_context_t *zfx,
int algo,int rel)
{
if(algo>=0)
zfx->algo=algo;
else
zfx->algo=DEFAULT_COMPRESS_ALGO;
switch(zfx->algo)
{
case COMPRESS_ALGO_NONE:
break;
case COMPRESS_ALGO_ZIP:
case COMPRESS_ALGO_ZLIB:
iobuf_push_filter2(out,compress_filter,zfx,rel);
break;
#ifdef HAVE_BZIP2
case COMPRESS_ALGO_BZIP2:
iobuf_push_filter2(out,compress_filter_bz2,zfx,rel);
break;
#endif
default:
BUG();
}
}

View File

@ -1,5 +1,5 @@
/* dearmor.c - Armor utility
* Copyright (C) 1998, 1999, 2000, 2001, 2003 Free Software Foundation, Inc.
* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -15,7 +15,8 @@
*
* 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
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
#include <config.h>
@ -28,13 +29,12 @@
#include "gpg.h"
#include "errors.h"
#include "iobuf.h"
#include "memory.h"
#include "util.h"
#include "filter.h"
#include "packet.h"
#include "options.h"
#include "main.h"
#include "i18n.h"
/****************
* Take an armor file and write it out without armor
@ -43,17 +43,24 @@ int
dearmor_file( const char *fname )
{
armor_filter_context_t afx;
iobuf_t inp = NULL, out = NULL;
IOBUF inp = NULL, out = NULL;
int rc = 0;
int c;
memset( &afx, 0, sizeof afx);
/* prepare iobufs */
if( !(inp = iobuf_open(fname)) ) {
rc = gpg_error_from_errno (errno);
log_error("can't open %s: %s\n", fname? fname: "[stdin]",
inp = iobuf_open(fname);
if (inp && is_secured_file (iobuf_get_fd (inp)))
{
iobuf_close (inp);
inp = NULL;
errno = EPERM;
}
if (!inp) {
log_error(_("can't open `%s': %s\n"), fname? fname: "[stdin]",
strerror(errno) );
rc = G10ERR_OPEN_FILE;
goto leave;
}
@ -85,17 +92,24 @@ int
enarmor_file( const char *fname )
{
armor_filter_context_t afx;
iobuf_t inp = NULL, out = NULL;
IOBUF inp = NULL, out = NULL;
int rc = 0;
int c;
memset( &afx, 0, sizeof afx);
/* prepare iobufs */
if( !(inp = iobuf_open(fname)) ) {
rc = gpg_error_from_errno (errno);
log_error("can't open %s: %s\n", fname? fname: "[stdin]",
strerror(errno) );
inp = iobuf_open(fname);
if (inp && is_secured_file (iobuf_get_fd (inp)))
{
iobuf_close (inp);
inp = NULL;
errno = EPERM;
}
if (!inp) {
log_error(_("can't open `%s': %s\n"), fname? fname: "[stdin]",
strerror(errno) );
rc = G10ERR_OPEN_FILE;
goto leave;
}

View File

@ -1,5 +1,6 @@
/* decrypt.c - verify signed data
* Copyright (C) 1998,1999,2000,2001,2002,2003 Free Software Foundation, Inc.
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003
* 2004 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -15,7 +16,8 @@
*
* 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
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
#include <config.h>
@ -25,12 +27,12 @@
#include <errno.h>
#include <assert.h>
#include "gpg.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"
@ -49,17 +51,24 @@
int
decrypt_message( const char *filename )
{
iobuf_t fp;
IOBUF fp;
armor_filter_context_t afx;
progress_filter_context_t pfx;
int rc;
int no_out=0;
/* open the message file */
/* Open the message file. */
fp = iobuf_open(filename);
if (fp && is_secured_file (iobuf_get_fd (fp)))
{
iobuf_close (fp);
fp = NULL;
errno = EPERM;
}
if( !fp ) {
rc = gpg_error_from_errno (errno);
log_error(_("can't open `%s'\n"), print_fname_stdin(filename));
log_error (_("can't open `%s': %s\n"), print_fname_stdin(filename),
gpg_strerror (rc));
return rc;
}
@ -84,13 +93,14 @@ decrypt_message( const char *filename )
}
void
decrypt_messages(int nfiles, char **files)
decrypt_messages(int nfiles, char *files[])
{
iobuf_t fp;
IOBUF fp;
armor_filter_context_t afx;
progress_filter_context_t pfx;
char *p, *output = NULL;
int rc = 0;
int rc=0,use_stdin=0;
unsigned int lno=0;
if (opt.outfile)
{
@ -99,20 +109,61 @@ decrypt_messages(int nfiles, char **files)
}
while (nfiles--)
if(!nfiles)
use_stdin=1;
for(;;)
{
print_file_status(STATUS_FILE_START, *files, 3);
output = make_outfile_name(*files);
char line[2048];
char *filename=NULL;
if(use_stdin)
{
if(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);
else
{
line[strlen(line)-1] = '\0';
filename=line;
}
}
}
else
{
if(nfiles)
{
filename=*files;
nfiles--;
files++;
}
}
if(filename==NULL)
break;
print_file_status(STATUS_FILE_START, filename, 3);
output = make_outfile_name(filename);
if (!output)
goto next_file;
fp = iobuf_open(*files);
fp = iobuf_open(filename);
if (fp)
iobuf_ioctl (fp,3,1,NULL); /* disable fd caching */
if (fp && is_secured_file (iobuf_get_fd (fp)))
{
iobuf_close (fp);
fp = NULL;
errno = EPERM;
}
if (!fp)
{
log_error(_("can't open `%s'\n"), print_fname_stdin(*files));
log_error(_("can't open `%s'\n"), print_fname_stdin(filename));
goto next_file;
}
handle_progress (&pfx, fp, *files);
handle_progress (&pfx, fp, filename);
if (!opt.no_armor)
{
@ -125,8 +176,8 @@ decrypt_messages(int nfiles, char **files)
rc = proc_packets(NULL, fp);
iobuf_close(fp);
if (rc)
log_error("%s: decryption failed: %s\n", print_fname_stdin(*files),
gpg_strerror (rc));
log_error("%s: decryption failed: %s\n", print_fname_stdin(filename),
g10_errstr(rc));
p = get_last_passphrase();
set_next_passphrase(p);
xfree (p);
@ -134,9 +185,8 @@ decrypt_messages(int nfiles, char **files)
next_file:
/* Note that we emit file_done even after an error. */
write_status( STATUS_FILE_DONE );
xfree (output);
files++;
xfree(output);
}
set_next_passphrase(NULL);
}

View File

@ -1,5 +1,6 @@
/* delkey.c - delete keys
* Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004,
* 2005, 2006 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -15,7 +16,8 @@
*
* 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
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
#include <config.h>
@ -26,12 +28,12 @@
#include <assert.h>
#include <ctype.h>
#include "gpg.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 "trustdb.h"
@ -47,7 +49,7 @@
* key can't be deleted for that reason.
*/
static int
do_delete_key( const char *username, int secret, int *r_sec_avail )
do_delete_key( const char *username, int secret, int force, int *r_sec_avail )
{
int rc = 0;
KBNODE keyblock = NULL;
@ -68,9 +70,9 @@ do_delete_key( const char *username, int secret, int *r_sec_avail )
exactmatch = (desc.mode == KEYDB_SEARCH_MODE_FPR
|| desc.mode == KEYDB_SEARCH_MODE_FPR16
|| desc.mode == KEYDB_SEARCH_MODE_FPR20);
rc = desc.mode? keydb_search (hd, &desc, 1):GPG_ERR_INV_USER_ID;
rc = desc.mode? keydb_search (hd, &desc, 1):G10ERR_INV_USER_ID;
if (rc) {
log_error (_("key `%s' not found: %s\n"), username, gpg_strerror (rc));
log_error (_("key \"%s\" not found: %s\n"), username, g10_errstr (rc));
write_status_text( STATUS_DELETE_PROBLEM, "1" );
goto leave;
}
@ -78,7 +80,7 @@ do_delete_key( const char *username, int secret, int *r_sec_avail )
/* read the keyblock */
rc = keydb_get_keyblock (hd, &keyblock );
if (rc) {
log_error (_("error reading keyblock: %s\n"), gpg_strerror (rc) );
log_error (_("error reading keyblock: %s\n"), g10_errstr(rc) );
goto leave;
}
@ -86,29 +88,36 @@ do_delete_key( const char *username, int secret, int *r_sec_avail )
node = find_kbnode( keyblock, secret? PKT_SECRET_KEY:PKT_PUBLIC_KEY );
if( !node ) {
log_error("Oops; key not found anymore!\n");
rc = GPG_ERR_GENERAL;
rc = G10ERR_GENERAL;
goto leave;
}
if( secret ) {
if( secret )
{
sk = node->pkt->pkt.secret_key;
keyid_from_sk( sk, keyid );
}
else {
}
else
{
/* public */
pk = node->pkt->pkt.public_key;
keyid_from_pk( pk, keyid );
rc = seckey_available( keyid );
if( !rc ) {
*r_sec_avail = 1;
rc = -1;
goto leave;
}
else if( rc != GPG_ERR_NO_SECKEY ) {
log_error("%s: get secret key: %s\n", username, gpg_strerror (rc) );
}
else
rc = 0;
}
if(!force)
{
rc = seckey_available( keyid );
if( !rc )
{
*r_sec_avail = 1;
rc = -1;
goto leave;
}
else if( rc != G10ERR_NO_SECKEY )
log_error("%s: get secret key: %s\n", username, g10_errstr(rc) );
else
rc = 0;
}
}
if( rc )
rc = 0;
@ -116,26 +125,26 @@ do_delete_key( const char *username, int secret, int *r_sec_avail )
okay++;
else if( opt.batch && secret )
{
log_error(_("can't do that in batchmode\n"));
log_error(_("can't do this in batch mode\n"));
log_info (_("(unless you specify the key by fingerprint)\n"));
}
else if( opt.batch && opt.answer_yes )
okay++;
else if( opt.batch )
{
log_error(_("can't do that in batchmode without \"--yes\"\n"));
log_error(_("can't do this in batch mode without \"--yes\"\n"));
log_info (_("(unless you specify the key by fingerprint)\n"));
}
else {
if( secret )
print_seckey_info( sk );
else
print_pubkey_info (NULL, pk );
print_pubkey_info(NULL, pk );
tty_printf( "\n" );
yes = cpr_get_answer_is_yes( secret? "delete_key.secret.okay"
: "delete_key.okay",
_("Delete this key from the keyring? "));
_("Delete this key from the keyring? (y/N) "));
if( !cpr_enabled() && secret && yes ) {
/* I think it is not required to check a passphrase; if
* the user is so stupid as to let others access his secret keyring
@ -143,7 +152,7 @@ do_delete_key( const char *username, int secret, int *r_sec_avail )
* basic texts about security.
*/
yes = cpr_get_answer_is_yes("delete_key.secret.okay",
_("This is a secret key! - really delete? "));
_("This is a secret key! - really delete? (y/N) "));
}
if( yes )
okay++;
@ -153,7 +162,7 @@ do_delete_key( const char *username, int secret, int *r_sec_avail )
if( okay ) {
rc = keydb_delete_keyblock (hd);
if (rc) {
log_error (_("deleting keyblock failed: %s\n"), gpg_strerror (rc) );
log_error (_("deleting keyblock failed: %s\n"), g10_errstr(rc) );
goto leave;
}
@ -179,15 +188,18 @@ do_delete_key( const char *username, int secret, int *r_sec_avail )
int
delete_keys( STRLIST names, int secret, int allow_both )
{
int rc, avail;
int rc, avail, force=(!allow_both && !secret && opt.expert);
/* Force allows us to delete a public key even if a secret key
exists. */
for(;names;names=names->next) {
rc = do_delete_key (names->d, secret, &avail );
rc = do_delete_key (names->d, secret, force, &avail );
if ( rc && avail ) {
if ( allow_both ) {
rc = do_delete_key (names->d, 1, &avail );
rc = do_delete_key (names->d, 1, 0, &avail );
if ( !rc )
rc = do_delete_key (names->d, 0, &avail );
rc = do_delete_key (names->d, 0, 0, &avail );
}
else {
log_error(_(
@ -200,7 +212,7 @@ delete_keys( STRLIST names, int secret, int allow_both )
}
if(rc) {
log_error("%s: delete key failed: %s\n", names->d, gpg_strerror (rc) );
log_error("%s: delete key failed: %s\n", names->d, g10_errstr(rc) );
return rc;
}
}

View File

@ -1,6 +1,6 @@
/* encode.c - encode data
* Copyright (C) 1998, 1999, 2000, 2001, 2002,
* 2003 Free Software Foundation, Inc.
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004,
* 2005 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -16,7 +16,8 @@
*
* 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
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
#include <config.h>
@ -32,7 +33,6 @@
#include "errors.h"
#include "iobuf.h"
#include "keydb.h"
#include "memory.h"
#include "util.h"
#include "main.h"
#include "filter.h"
@ -42,10 +42,8 @@
#include "pkglue.h"
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_t out );
static int encode_simple( const char *filename, int mode, int use_seskey );
static int write_pubkey_enc_from_list( PK_LIST pk_list, DEK *dek, IOBUF out );
/****************
* Encode FILENAME with only the symmetric cipher. Take input from
@ -54,17 +52,7 @@ static int write_pubkey_enc_from_list( PK_LIST pk_list, DEK *dek, iobuf_t out );
int
encode_symmetric( const char *filename )
{
int compat = 1;
#if 0
/* We don't want to use it because older gnupg version can't
handle it and we can presume that a lot of scripts are running
with the expert mode set. Some time in the future we might
want to allow for it. */
if ( opt.expert )
compat = 0; /* PGP knows how to handle this mode. */
#endif
return encode_simple( filename, 1, compat );
return encode_simple( filename, 1, 0 );
}
/****************
@ -74,69 +62,62 @@ encode_symmetric( const char *filename )
int
encode_store( const char *filename )
{
return encode_simple( filename, 0, 1 );
return encode_simple( filename, 0, 0 );
}
static void
encode_sesskey (DEK * dek, DEK ** ret_dek, byte * enckey)
encode_seskey( DEK *dek, DEK **seskey, byte *enckey )
{
CIPHER_HANDLE hd;
DEK * c;
byte buf[33];
gcry_cipher_hd_t hd;
byte buf[33];
assert (dek->keylen < 32);
assert ( dek->keylen <= 32 );
if(!*seskey)
{
*seskey=xmalloc_clear(sizeof(DEK));
(*seskey)->keylen=dek->keylen;
(*seskey)->algo=dek->algo;
make_session_key(*seskey);
/*log_hexdump( "thekey", c->key, c->keylen );*/
}
/* The encrypted session key is prefixed with a one-octet algorithm id. */
buf[0] = (*seskey)->algo;
memcpy( buf + 1, (*seskey)->key, (*seskey)->keylen );
c = xcalloc (1, sizeof *c);
c->keylen = dek->keylen;
c->algo = dek->algo;
make_session_key (c);
/*log_hexdump ("thekey", c->key, c->keylen);*/
/* We only pass already checked values to the following fucntion,
thus we consider any failure as fatal. */
if (gcry_cipher_open (&hd, dek->algo, GCRY_CIPHER_MODE_CFB, 1))
BUG ();
if (gcry_cipher_setkey (hd, dek->key, dek->keylen))
BUG ();
gry_cipher_setiv (hd, NULL, 0);
gcry_cipher_encrypt (hd, buf, (*seskey)->keylen + 1, NULL, 0);
gcry_cipher_close (hd);
/* the encrypted session key is prefixed with a one-octet algorithm id */
buf[0] = c->algo;
memcpy (buf + 1, c->key, c->keylen);
/* due to the fact that we use only checked values, consider each
failure as fatal. */
if (gcry_cipher_open (&hd, dek->algo, GCRY_CIPHER_MODE_CFB, 1))
BUG();
if (gcry_cipher_setkey (hd, dek->key, dek->keylen))
BUG();
gcry_cipher_setiv (hd, NULL, 0);
gcry_cipher_encrypt (hd, buf, c->keylen + 1, NULL, 0);
gcry_cipher_close (hd);
memcpy (enckey, buf, c->keylen + 1);
wipememory (buf, sizeof buf); /* burn key */
*ret_dek = c;
memcpy( enckey, buf, (*seskey)->keylen + 1 );
wipememory( buf, sizeof buf ); /* burn key */
}
/* We try very hard to use a MDC */
static int
use_mdc (PK_LIST pk_list,int algo)
use_mdc(PK_LIST pk_list,int algo)
{
byte cipher_algid[4] = {
CIPHER_ALGO_AES,
CIPHER_ALGO_AES192,
CIPHER_ALGO_AES256,
CIPHER_ALGO_TWOFISH
};
int i;
/* RFC-1991 and 2440 don't have MDC */
if(RFC1991 || RFC2440)
return 0;
/* --force-mdc overrides --disable-mdc */
if (opt.force_mdc)
if(opt.force_mdc)
return 1;
if (opt.disable_mdc)
if(opt.disable_mdc)
return 0;
/* Do the keys really support MDC? */
if (select_mdc_from_pklist (pk_list))
if(select_mdc_from_pklist(pk_list))
return 1;
/* The keys don't support MDC, so now we do a bit of a hack - if any
@ -144,26 +125,40 @@ use_mdc (PK_LIST pk_list,int algo)
can handle a MDC. This is valid for PGP 7, which can handle MDCs
though it will not generate them. 2440bis allows this, by the
way. */
for (i=0; i < DIM (cipher_algid); i++)
{
if (select_algo_from_prefs (pk_list, PREFTYPE_SYM, cipher_algid[i],
NULL) == cipher_algid[i])
return 1;
}
if(select_algo_from_prefs(pk_list,PREFTYPE_SYM,
CIPHER_ALGO_AES,NULL)==CIPHER_ALGO_AES)
return 1;
if(select_algo_from_prefs(pk_list,PREFTYPE_SYM,
CIPHER_ALGO_AES192,NULL)==CIPHER_ALGO_AES192)
return 1;
if(select_algo_from_prefs(pk_list,PREFTYPE_SYM,
CIPHER_ALGO_AES256,NULL)==CIPHER_ALGO_AES256)
return 1;
if(select_algo_from_prefs(pk_list,PREFTYPE_SYM,
CIPHER_ALGO_TWOFISH,NULL)==CIPHER_ALGO_TWOFISH)
return 1;
/* Last try. Use MDC for the modern ciphers. */
if (gcry_cipher_get_algo_blklen (algo) != 8)
return 1;
return 0; /* No MDC */
}
/* We don't want to use use_seskey yet because older gnupg versions
can't handle it, and there isn't really any point unless we're
making a message that can be decrypted by a public key or
passphrase. */
static int
encode_simple( const char *filename, int mode, int compat )
encode_simple( const char *filename, int mode, int use_seskey )
{
iobuf_t inp, out;
IOBUF inp, out;
PACKET pkt;
DEK *dek = NULL;
PKT_plaintext *pt = NULL;
STRING2KEY *s2k = NULL;
byte enckey[33];
@ -175,7 +170,7 @@ encode_simple( const char *filename, int mode, int compat )
compress_filter_context_t zfx;
text_filter_context_t tfx;
progress_filter_context_t pfx;
int do_compress = opt.compress && !RFC1991;
int do_compress = !RFC1991 && default_compress_algo();
memset( &cfx, 0, sizeof cfx);
memset( &afx, 0, sizeof afx);
@ -184,10 +179,19 @@ encode_simple( const char *filename, int mode, int compat )
init_packet(&pkt);
/* prepare iobufs */
if( !(inp = iobuf_open(filename)) ) {
inp = iobuf_open(filename);
if (inp)
iobuf_ioctl (inp,3,1,NULL); /* disable fd caching */
if (inp && is_secured_file (iobuf_get_fd (inp)))
{
iobuf_close (inp);
inp = NULL;
errno = EPERM;
}
if( !inp ) {
rc = gpg_error_from_errno (errno);
log_error(_("%s: can't open: %s\n"), filename? filename: "[stdin]",
strerror(errno) );
log_error(_("can't open `%s': %s\n"), filename? filename: "[stdin]"
strerror(errno) );
return rc;
}
@ -199,42 +203,49 @@ encode_simple( const char *filename, int mode, int compat )
/* 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 ( RFC1991 && !compat )
compat = 1;
if ( RFC1991 && use_seskey )
use_seskey = 0;
cfx.dek = NULL;
if( mode ) {
s2k = xcalloc (1, sizeof *s2k );
s2k = xmalloc_clear( sizeof *s2k );
s2k->mode = RFC1991? 0:opt.s2k_mode;
s2k->hash_algo = opt.s2k_digest_algo;
s2k->hash_algo=S2K_DIGEST_ALGO;
cfx.dek = passphrase_to_dek( NULL, 0,
default_cipher_algo(), s2k, 2,
NULL, NULL);
if( !cfx.dek || !cfx.dek->keylen ) {
rc = gpg_error (GPG_ERR_INV_PASSPHRASE);
xfree (cfx.dek);
xfree (s2k);
rc = gpg_error (GPG_ERR_INV_PASSPHRASE);
xfree(cfx.dek);
xfree(s2k);
iobuf_close(inp);
log_error(_("error creating passphrase: %s\n"), gpg_strerror (rc) );
log_error(_("error creating passphrase: %s\n"), gpg_strerror (rc));
return rc;
}
if (!compat && s2k->mode != 1 && s2k->mode != 3) {
compat = 1;
if (use_seskey && s2k->mode != 1 && s2k->mode != 3) {
use_seskey = 0;
log_info (_("can't use a symmetric ESK packet "
"due to the S2K mode\n"));
}
if ( !compat ) {
seskeylen = gcry_cipher_get_algo_keylen (default_cipher_algo());
encode_sesskey( cfx.dek, &dek, enckey );
xfree (cfx.dek); cfx.dek = dek;
}
if ( use_seskey )
{
DEK *dek = NULL;
seskeylen = gcry_cipher_get_algo_keylen (default_cipher_algo ());
encode_seskey( cfx.dek, &dek, enckey );
xfree( cfx.dek ); cfx.dek = dek;
}
if(opt.verbose)
log_info(_("using cipher %s\n"),
gcry_cipher_algo_name (cfx.dek->algo));
cfx.dek->use_mdc=use_mdc(NULL,cfx.dek->algo);
}
if (opt.compress == -1 && cfx.dek && cfx.dek->use_mdc &&
is_file_compressed(filename, &rc))
if (do_compress && cfx.dek && cfx.dek->use_mdc
&& is_file_compressed(filename, &rc))
{
if (opt.verbose)
log_info(_("`%s' already compressed\n"), filename);
@ -243,52 +254,43 @@ encode_simple( const char *filename, int mode, int compat )
if( rc || (rc = open_outfile( filename, opt.armor? 1:0, &out )) ) {
iobuf_cancel(inp);
xfree (cfx.dek);
xfree (s2k);
xfree(cfx.dek);
xfree(s2k);
return rc;
}
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
if( s2k && !RFC1991 ) {
PKT_symkey_enc *enc = xcalloc (1, sizeof *enc + seskeylen + 1 );
PKT_symkey_enc *enc = xmalloc_clear( sizeof *enc + seskeylen + 1 );
enc->version = 4;
enc->cipher_algo = cfx.dek->algo;
enc->s2k = *s2k;
if ( !compat && seskeylen ) {
if ( use_seskey && 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_strerror (rc) );
xfree (enc);
log_error("build symkey packet failed: %s\n", g10_errstr(rc) );
xfree(enc);
}
if (!opt.no_literal) {
/* setup the inner packet */
if( filename || opt.set_filename ) {
char *s = make_basename ( opt.set_filename ? opt.set_filename
: filename
/* for riscos?
.iobuf_get_real_fname( inp ) */
);
pt = xmalloc ( sizeof *pt + strlen(s) - 1 );
char *s = make_basename( opt.set_filename ? opt.set_filename
: filename,
iobuf_get_real_fname( inp ) );
pt = xmalloc( sizeof *pt + strlen(s) - 1 );
pt->namelen = strlen(s);
memcpy(pt->name, s, pt->namelen );
xfree (s);
xfree(s);
}
else { /* no filename */
pt = xmalloc ( sizeof *pt - 1 );
pt = xmalloc( sizeof *pt - 1 );
pt->namelen = 0;
}
}
@ -304,12 +306,14 @@ encode_simple( const char *filename, int mode, int compat )
either partial length or fixed length with the new style
messages. */
if (filename && *filename && !(*filename == '-' && !filename[1])
&& !opt.textmode ) {
if ( !iobuf_is_pipe_filename (filename) && *filename && !opt.textmode )
{
off_t tmpsize;
int overflow;
if ( !(tmpsize = iobuf_get_filelength(inp)) )
log_info(_("%s: WARNING: empty file\n"), filename );
if ( !(tmpsize = iobuf_get_filelength(inp, &overflow))
&& !overflow )
log_info(_("WARNING: `%s' is an empty file\n"), filename );
/* We can't encode the length of very large files because
OpenPGP uses only 32 bit for file sizes. So if the the
size of a file is larger than 2^32 minus some bytes for
@ -318,9 +322,9 @@ encode_simple( const char *filename, int mode, int compat )
filesize = tmpsize;
else
filesize = 0;
}
}
else
filesize = opt.set_filesize ? opt.set_filesize : 0; /* stdin */
filesize = opt.set_filesize ? opt.set_filesize : 0; /* stdin */
if (!opt.no_literal) {
pt->timestamp = make_timestamp();
@ -347,14 +351,13 @@ encode_simple( const char *filename, int mode, int compat )
{
if (cfx.dek && cfx.dek->use_mdc)
zfx.new_ctb = 1;
zfx.algo=default_compress_algo();
iobuf_push_filter( out, compress_filter, &zfx );
push_compress_filter(out,&zfx,default_compress_algo());
}
/* do the work */
if (!opt.no_literal) {
if( (rc = build_packet( out, &pkt )) )
log_error("build_packet failed: %s\n", gpg_strerror (rc) );
log_error("build_packet failed: %s\n", g10_errstr(rc) );
}
else {
/* user requested not to create a literal packet,
@ -362,8 +365,9 @@ encode_simple( const char *filename, int mode, int compat )
byte copy_buffer[4096];
int bytes_copied;
while ((bytes_copied = iobuf_read(inp, copy_buffer, 4096)) != -1)
if ( (rc=iobuf_write(out, copy_buffer, bytes_copied))) {
log_error("copying input to output failed: %s\n", gpg_strerror (rc) );
if (iobuf_write(out, copy_buffer, bytes_copied) == -1) {
rc = G10ERR_WRITE_FILE;
log_error("copying input to output failed: %s\n", g10_errstr(rc) );
break;
}
wipememory(copy_buffer, 4096); /* burn buffer */
@ -381,21 +385,70 @@ encode_simple( const char *filename, int mode, int compat )
if (pt)
pt->buf = NULL;
free_packet(&pkt);
xfree (cfx.dek);
xfree (s2k);
xfree(cfx.dek);
xfree(s2k);
return rc;
}
int
setup_symkey(STRING2KEY **symkey_s2k,DEK **symkey_dek)
{
*symkey_s2k=xmalloc_clear(sizeof(STRING2KEY));
(*symkey_s2k)->mode = opt.s2k_mode;
(*symkey_s2k)->hash_algo = S2K_DIGEST_ALGO;
*symkey_dek=passphrase_to_dek(NULL,0,opt.s2k_cipher_algo,
*symkey_s2k,2,NULL,NULL);
if(!*symkey_dek || !(*symkey_dek)->keylen)
{
xfree(*symkey_dek);
xfree(*symkey_s2k);
return G10ERR_PASSPHRASE;
}
return 0;
}
static int
write_symkey_enc(STRING2KEY *symkey_s2k,DEK *symkey_dek,DEK *dek,IOBUF out)
{
int rc,seskeylen=cipher_get_keylen(dek->algo)/8;
PKT_symkey_enc *enc;
byte enckey[33];
PACKET pkt;
enc=xmalloc_clear(sizeof(PKT_symkey_enc)+seskeylen+1);
encode_seskey(symkey_dek,&dek,enckey);
enc->version = 4;
enc->cipher_algo = opt.s2k_cipher_algo;
enc->s2k = *symkey_s2k;
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_enc packet failed: %s\n",g10_errstr(rc));
xfree(enc);
return rc;
}
/****************
* Encrypt the file with the given userids (or ask if none
* is supplied).
*/
int
encode_crypt( const char *filename, STRLIST remusr )
encode_crypt( const char *filename, STRLIST remusr, int use_symkey )
{
iobuf_t inp = NULL, out = NULL;
IOBUF inp = NULL, out = NULL;
PACKET pkt;
PKT_plaintext *pt = NULL;
DEK *symkey_dek = NULL;
STRING2KEY *symkey_s2k = NULL;
int rc = 0, rc2 = 0;
u32 filesize;
cipher_filter_context_t cfx;
@ -404,8 +457,7 @@ encode_crypt( const char *filename, STRLIST remusr )
text_filter_context_t tfx;
progress_filter_context_t pfx;
PK_LIST pk_list,work_list;
int do_compress = opt.compress && !RFC1991;
int do_compress = opt.compress_algo && !RFC1991;
memset( &cfx, 0, sizeof cfx);
memset( &afx, 0, sizeof afx);
@ -413,6 +465,10 @@ encode_crypt( const char *filename, STRLIST remusr )
memset( &tfx, 0, sizeof tfx);
init_packet(&pkt);
if(use_symkey
&& (rc=setup_symkey(&symkey_s2k,&symkey_dek)))
return rc;
if( (rc=build_pk_list( remusr, &pk_list, PUBKEY_USAGE_ENC)) )
return rc;
@ -429,10 +485,20 @@ encode_crypt( const char *filename, STRLIST remusr )
}
/* prepare iobufs */
if( !(inp = iobuf_open(filename)) ) {
inp = iobuf_open(filename);
if (inp)
iobuf_ioctl (inp,3,1,NULL); /* disable fd caching */
if (inp && is_secured_file (iobuf_get_fd (inp)))
{
iobuf_close (inp);
inp = NULL;
errno = EPERM;
}
if( !inp ) {
rc = gpg_error_from_errno (errno);
log_error(_("can't open %s: %s\n"), filename? filename: "[stdin]",
strerror(errno) );
log_error(_("can't open `%s': %s\n"),
filename? filename: "[stdin]",
gpg_strerror (rc) );
goto leave;
}
else if( opt.verbose )
@ -446,19 +512,11 @@ encode_crypt( const char *filename, STRLIST remusr )
if( (rc = open_outfile( filename, opt.armor? 1:0, &out )) )
goto leave;
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 = xcalloc_secure (1, sizeof *cfx.dek);
cfx.dek = xmalloc_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
@ -482,8 +540,8 @@ encode_crypt( const char *filename, STRLIST remusr )
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"),
log_info(_("WARNING: forcing symmetric cipher %s (%d)"
" violates recipient preferences\n"),
gcry_cipher_algo_name (opt.def_cipher_algo),
opt.def_cipher_algo);
@ -497,8 +555,7 @@ encode_crypt( const char *filename, STRLIST remusr )
not have a MDC to give some protection against chosen
ciphertext attacks. */
if (opt.compress == -1 && cfx.dek->use_mdc &&
is_file_compressed(filename, &rc2) )
if (do_compress && cfx.dek->use_mdc && is_file_compressed(filename, &rc2) )
{
if (opt.verbose)
log_info(_("`%s' already compressed\n"), filename);
@ -518,40 +575,49 @@ encode_crypt( const char *filename, STRLIST remusr )
if( rc )
goto leave;
/* We put the passphrase (if any) after any public keys as this
seems to be the most useful on the recipient side - there is no
point in prompting a user for a passphrase if they have the
secret key needed to decrypt. */
if(use_symkey && (rc=write_symkey_enc(symkey_s2k,symkey_dek,cfx.dek,out)))
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
/* ,iobuf_get_real_fname( inp )*/ );
pt = xmalloc ( sizeof *pt + strlen(s) - 1 );
: filename,
iobuf_get_real_fname( inp ) );
pt = xmalloc( sizeof *pt + strlen(s) - 1 );
pt->namelen = strlen(s);
memcpy(pt->name, s, pt->namelen );
xfree (s);
xfree(s);
}
else { /* no filename */
pt = xmalloc ( sizeof *pt - 1 );
pt = xmalloc( sizeof *pt - 1 );
pt->namelen = 0;
}
}
if (filename && *filename && !(*filename == '-' && !filename[1])
&& !opt.textmode ) {
if (!iobuf_is_pipe_filename (filename) && *filename && !opt.textmode )
{
off_t tmpsize;
int overflow;
if ( !(tmpsize = iobuf_get_filelength(inp)) )
log_info(_("%s: WARNING: empty file\n"), filename );
if ( !(tmpsize = iobuf_get_filelength(inp, &overflow))
&& !overflow )
log_info(_("WARNING: `%s' is an empty file\n"), filename );
/* We can't encode the length of very large files because
OpenPGP uses only 32 bit for file sizes. So if the the
size of a file is larger than 2^32 minus some bytes for
packet headers, we switch to partial length encoding. */
if ( tmpsize < (IOBUF_FILELENGTH_LIMIT - 65536) )
if (tmpsize < (IOBUF_FILELENGTH_LIMIT - 65536) )
filesize = tmpsize;
else
filesize = 0;
}
}
else
filesize = opt.set_filesize ? opt.set_filesize : 0; /* stdin */
filesize = opt.set_filesize ? opt.set_filesize : 0; /* stdin */
if (!opt.no_literal) {
pt->timestamp = make_timestamp();
@ -571,7 +637,7 @@ encode_crypt( const char *filename, STRLIST remusr )
/* register the compress filter */
if( do_compress ) {
int compr_algo = opt.def_compress_algo;
int compr_algo = opt.compress_algo;
if(compr_algo==-1)
{
@ -584,8 +650,8 @@ encode_crypt( const char *filename, STRLIST remusr )
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"),
log_info(_("WARNING: forcing compression algorithm %s (%d)"
" violates recipient preferences\n"),
compress_algo_to_string(compr_algo),compr_algo);
/* algo 0 means no compression */
@ -593,15 +659,14 @@ encode_crypt( const char *filename, STRLIST remusr )
{
if (cfx.dek && cfx.dek->use_mdc)
zfx.new_ctb = 1;
zfx.algo = compr_algo;
iobuf_push_filter( out, compress_filter, &zfx );
push_compress_filter(out,&zfx,compr_algo);
}
}
/* do the work */
if (!opt.no_literal) {
if( (rc = build_packet( out, &pkt )) )
log_error("build_packet failed: %s\n", gpg_strerror (rc) );
log_error("build_packet failed: %s\n", g10_errstr(rc) );
}
else {
/* user requested not to create a literal packet, so we copy
@ -609,9 +674,10 @@ encode_crypt( const char *filename, STRLIST remusr )
byte copy_buffer[4096];
int bytes_copied;
while ((bytes_copied = iobuf_read(inp, copy_buffer, 4096)) != -1)
if ((rc=iobuf_write(out, copy_buffer, bytes_copied))) {
if (iobuf_write(out, copy_buffer, bytes_copied) == -1) {
rc = G10ERR_WRITE_FILE;
log_error("copying input to output failed: %s\n",
gpg_strerror (rc) );
g10_errstr(rc) );
break;
}
wipememory(copy_buffer, 4096); /* burn buffer */
@ -629,7 +695,9 @@ encode_crypt( const char *filename, STRLIST remusr )
if( pt )
pt->buf = NULL;
free_packet(&pkt);
xfree (cfx.dek);
xfree(cfx.dek);
xfree(symkey_dek);
xfree(symkey_s2k);
release_pk_list( pk_list );
return rc;
}
@ -642,7 +710,7 @@ encode_crypt( const char *filename, STRLIST remusr )
*/
int
encrypt_filter( void *opaque, int control,
iobuf_t a, byte *buf, size_t *ret_len)
IOBUF a, byte *buf, size_t *ret_len)
{
size_t size = *ret_len;
encrypt_filter_context_t *efx = opaque;
@ -653,7 +721,7 @@ encrypt_filter( void *opaque, int control,
}
else if( control == IOBUFCTRL_FLUSH ) { /* encrypt */
if( !efx->header_okay ) {
efx->cfx.dek = xcalloc_secure (1, sizeof *efx->cfx.dek );
efx->cfx.dek = xmalloc_secure_clear( sizeof *efx->cfx.dek );
if( !opt.def_cipher_algo ) { /* try to get it from the prefs */
efx->cfx.dek->algo =
@ -688,6 +756,14 @@ encrypt_filter( void *opaque, int control,
if( rc )
return rc;
if(efx->symkey_s2k && efx->symkey_dek)
{
rc=write_symkey_enc(efx->symkey_s2k,efx->symkey_dek,
efx->cfx.dek,a);
if(rc)
return rc;
}
iobuf_push_filter( a, cipher_filter, &efx->cfx );
efx->header_okay = 1;
@ -695,8 +771,11 @@ encrypt_filter( void *opaque, int control,
rc = iobuf_write( a, buf, size );
}
else if( control == IOBUFCTRL_FREE ) {
}
else if( control == IOBUFCTRL_FREE )
{
xfree(efx->symkey_dek);
xfree(efx->symkey_s2k);
}
else if( control == IOBUFCTRL_DESC ) {
*(char**)buf = "encrypt_filter";
}
@ -708,7 +787,7 @@ encrypt_filter( void *opaque, int control,
* Write pubkey-enc packets from the list of PKs to OUT.
*/
static int
write_pubkey_enc_from_list( PK_LIST pk_list, DEK *dek, iobuf_t out )
write_pubkey_enc_from_list( PK_LIST pk_list, DEK *dek, IOBUF out )
{
PACKET pkt;
PKT_public_key *pk;
@ -716,12 +795,12 @@ write_pubkey_enc_from_list( PK_LIST pk_list, DEK *dek, iobuf_t out )
int rc;
for( ; pk_list; pk_list = pk_list->next ) {
gcry_mpi_t frame;
MPI frame;
pk = pk_list->pk;
print_pubkey_algo_note( pk->pubkey_algo );
enc = xcalloc (1, sizeof *enc );
enc = xmalloc_clear( sizeof *enc );
enc->pubkey_algo = pk->pubkey_algo;
keyid_from_pk( pk, enc->keyid );
enc->throw_keyid = (opt.throw_keyid || (pk_list->flags&1));
@ -742,23 +821,24 @@ write_pubkey_enc_from_list( PK_LIST pk_list, DEK *dek, iobuf_t out )
* algorithm number PK->PUBKEY_ALGO and pass it to pubkey_encrypt
* which returns the encrypted value in the array ENC->DATA.
* This array has a size which depends on the used algorithm
* (e.g. 2 for ElGamal). We don't need frame anymore because we
* (e.g. 2 for Elgamal). We don't need frame anymore because we
* have everything now in enc->data which is the passed to
* build_packet()
*/
frame = encode_session_key( dek, pubkey_nbits( pk->pubkey_algo,
pk->pkey ) );
rc = pk_encrypt( pk->pubkey_algo, enc->data, frame, pk->pkey );
gcry_mpi_release ( frame );
frame = encode_session_key (dek, pubkey_nbits (pk->pubkey_algo,
pk->pkey) );
rc = pk_encrypt (pk->pubkey_algo, enc->data, frame, pk->pkey);
gcry_mpi_release (frame);
if( rc )
log_error("pubkey_encrypt failed: %s\n", gpg_strerror (rc) );
log_error ("pubkey_encrypt failed: %s\n", gpg_strerror (rc) );
else {
if( opt.verbose ) {
char *ustr = get_user_id_string_printable (enc->keyid);
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 );
xfree (ustr);
gcry_pk_algo_name (enc->pubkey_algo),
gcry_cipher_algo_name (dek->algo),
ustr );
xfree(ustr);
}
/* and write it */
init_packet(&pkt);
@ -766,7 +846,7 @@ write_pubkey_enc_from_list( PK_LIST pk_list, DEK *dek, iobuf_t out )
pkt.pkt.pubkey_enc = enc;
rc = build_packet( out, &pkt );
if( rc )
log_error("build_packet(pubkey_enc) failed: %s\n", gpg_strerror (rc));
log_error("build_packet(pubkey_enc) failed: %s\n", g10_errstr(rc));
}
free_pubkey_enc(enc);
if( rc )
@ -800,9 +880,9 @@ encode_crypt_files(int nfiles, char **files, STRLIST remusr)
}
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), gpg_strerror (rc) );
if ( (rc = encode_crypt(line, remusr, 0)) )
log_error("encryption of `%s' failed: %s\n",
print_fname_stdin(line), g10_errstr(rc) );
write_status( STATUS_FILE_DONE );
}
}
@ -811,9 +891,9 @@ encode_crypt_files(int nfiles, char **files, STRLIST remusr)
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), gpg_strerror (rc) );
if ( (rc = encode_crypt(*files, remusr, 0)) )
log_error("encryption of `%s' failed: %s\n",
print_fname_stdin(*files), g10_errstr(rc) );
write_status( STATUS_FILE_DONE );
files++;
}

View File

@ -1,5 +1,6 @@
/* encr-data.c - process an encrypted data packet
* Copyright (C) 1998, 1999, 2000, 2001, 2003 Free Software Foundation, Inc.
* Copyright (C) 1998, 1999, 2000, 2001, 2005,
* 2006 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -15,7 +16,8 @@
*
* 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
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
#include <config.h>
@ -26,25 +28,24 @@
#include "gpg.h"
#include "util.h"
#include "memory.h"
#include "packet.h"
#include "mpi.h"
#include "cipher.h"
#include "options.h"
#include "i18n.h"
static int mdc_decode_filter( void *opaque, int control, iobuf_t a,
static int mdc_decode_filter( void *opaque, int control, IOBUF a,
byte *buf, size_t *ret_len);
static int decode_filter( void *opaque, int control, iobuf_t a,
static int decode_filter( void *opaque, int control, IOBUF a,
byte *buf, size_t *ret_len);
typedef struct {
CIPHER_HANDLE cipher_hd;
MD_HANDLE mdc_hash;
char defer[20];
int defer_filled;
int eof_seen;
typedef struct
{
gcry_cipher_hd_t cipher_hd;
gcry_md_hd_t mdc_hash;
char defer[20];
int defer_filled;
int eof_seen;
} decode_filter_ctx_t;
@ -70,7 +71,8 @@ decrypt_data( void *procctx, PKT_encrypted *ed, DEK *dek )
log_info(_("encrypted with unknown algorithm %d\n"), dek->algo );
dek->algo_info_printed = 1;
}
if( (rc=openpgp_cipher_test_algo(dek->algo)) )
rc = openpgp_cipher_test_algo (dek->algo);
if (rc)
goto leave;
blocksize = gcry_cipher_get_algo_blklen (dek->algo);
if( !blocksize || blocksize > 16 )
@ -80,31 +82,39 @@ decrypt_data( void *procctx, PKT_encrypted *ed, DEK *dek )
BUG();
if( ed->mdc_method ) {
gcry_md_open (&dfx.mdc_hash, ed->mdc_method, 0 );
if (gcry_md_open (&dfx.mdc_hash, ed->mdc_method, 0 ))
BUG ();
if ( DBG_HASHING )
gcry_md_start_debug (dfx.mdc_hash, "checkmdc");
}
rc = gcry_cipher_open (&dfx.cipher_hd, dek->algo,
GCRY_CIPHER_MODE_CFB,
GCRY_CIPHER_SECURE
| ((ed->mdc_method || dek->algo >= 100)?
0 : GCRY_CIPHER_ENABLE_SYNC) );
if (rc)
{
/* 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();
}
(GCRY_CIPHER_SECURE
| ((ed->mdc_method || dek->algo >= 100)?
0 : GCRY_CIPHER_ENABLE_SYNC)));
if (rc)
{
/* We should never get an error here cause we already checked
* that the algorithm is available. */
BUG();
}
/* log_hexdump( "thekey", dek->key, dek->keylen );*/
rc = gcry_cipher_setkey (dfx.cipher_hd, dek->key, dek->keylen);
if( gpg_err_code (rc) == GPG_ERR_WEAK_KEY )
log_info(_("WARNING: message was encrypted with "
"a weak key in the symmetric cipher.\n"));
else if( rc ) {
log_error("key setup failed: %s\n", gpg_strerror (rc) );
if ( gpg_err_code (rc) == GPG_ERR_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", g10_errstr(rc) );
goto leave;
}
}
if (!ed->buf) {
log_error(_("problem handling encrypted packet\n"));
goto leave;
@ -112,7 +122,7 @@ decrypt_data( void *procctx, PKT_encrypted *ed, DEK *dek )
gcry_cipher_setiv (dfx.cipher_hd, NULL, 0);
if (ed->len) {
if( ed->len ) {
for(i=0; i < (nprefix+2) && ed->len; i++, ed->len-- ) {
if( (c=iobuf_get(ed->buf)) == -1 )
break;
@ -127,17 +137,20 @@ 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 );
gcry_cipher_decrypt (dfx.cipher_hd, temp, nprefix+2, NULL, 0);
gcry_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] ) {
if(dek->symmetric
&& (p[nprefix-2] != p[nprefix] || p[nprefix-1] != p[nprefix+1]) )
{
rc = GPG_ERR_BAD_KEY;
goto leave;
}
}
if( dfx.mdc_hash )
gcry_md_write( dfx.mdc_hash, temp, nprefix+2 );
gcry_md_write (dfx.mdc_hash, temp, nprefix+2);
if( ed->mdc_method )
iobuf_push_filter( ed->buf, mdc_decode_filter, &dfx );
@ -152,18 +165,18 @@ decrypt_data( void *procctx, PKT_encrypted *ed, DEK *dek )
int datalen = gcry_md_get_algo_dlen (ed->mdc_method);
gcry_cipher_decrypt (dfx.cipher_hd, dfx.defer, 20, NULL, 0);
gcry_md_final ( dfx.mdc_hash );
if( datalen != 20
|| memcmp(gcry_md_read ( dfx.mdc_hash, 0 ), dfx.defer, datalen) )
rc = gpg_error (GPG_ERR_BAD_SIGNATURE);
/*log_hexdump("MDC calculated:", gcry_md_read ( dfx.mdc_hash, 0), datalen);*/
gcry_md_final (dfx.mdc_hash);
if (datalen != 20
|| memcmp (gcry_md_read( dfx.mdc_hash, 0 ), dfx.defer, datalen) )
rc = gpg_error (GPG_ERR_BAD_SIGNATURE);
/*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 );
gcry_cipher_close (dfx.cipher_hd);
gcry_md_close (dfx.mdc_hash);
return rc;
}
@ -171,7 +184,7 @@ decrypt_data( void *procctx, PKT_encrypted *ed, DEK *dek )
/* I think we should merge this with cipher_filter */
static int
mdc_decode_filter( void *opaque, int control, iobuf_t a,
mdc_decode_filter( void *opaque, int control, IOBUF a,
byte *buf, size_t *ret_len)
{
decode_filter_ctx_t *dfx = opaque;
@ -229,8 +242,8 @@ mdc_decode_filter( void *opaque, int control, iobuf_t a,
}
if( n ) {
gcry_cipher_decrypt( dfx->cipher_hd, buf, n, NULL, 0);
gcry_md_write( dfx->mdc_hash, buf, n );
gcry_cipher_decrypt (dfx->cipher_hd, buf, n, NULL, 0);
gcry_md_write (dfx->mdc_hash, buf, n);
}
else {
assert( dfx->eof_seen );
@ -245,7 +258,7 @@ mdc_decode_filter( void *opaque, int control, iobuf_t a,
}
static int
decode_filter( void *opaque, int control, iobuf_t a, byte *buf, size_t *ret_len)
decode_filter( void *opaque, int control, IOBUF a, byte *buf, size_t *ret_len)
{
decode_filter_ctx_t *fc = opaque;
size_t n, size = *ret_len;
@ -256,7 +269,7 @@ decode_filter( void *opaque, int control, iobuf_t 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);
gcry_cipher_decrypt (fc->cipher_hd, buf, n, NULL, 0);
else
rc = -1; /* eof */
*ret_len = n;

View File

@ -1,5 +1,5 @@
/* exec.c - generic call-a-program code
* Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
* Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -15,7 +15,8 @@
*
* 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
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
#include <config.h>
@ -34,12 +35,13 @@
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include "gpg.h"
#include "options.h"
#include "memory.h"
#include "i18n.h"
#include "iobuf.h"
#include "util.h"
#include "mkdtemp.h"
#include "mkdtemp.h" /* From gnulib. */
#include "exec.h"
#ifdef NO_EXEC
@ -47,12 +49,12 @@ 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 GPG_ERR_GENERAL;
return G10ERR_GENERAL;
}
int exec_read(struct exec_info *info) { return GPG_ERR_GENERAL; }
int exec_finish(struct exec_info *info) { return GPG_ERR_GENERAL; }
int set_exec_path(const char *path,int method) { return GPG_ERR_GENERAL; }
int exec_read(struct exec_info *info) { return G10ERR_GENERAL; }
int exec_finish(struct exec_info *info) { return G10ERR_GENERAL; }
int set_exec_path(const char *path) { return G10ERR_GENERAL; }
#else /* ! NO_EXEC */
@ -60,7 +62,7 @@ int set_exec_path(const char *path,int method) { return GPG_ERR_GENERAL; }
/* 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)
static int w32_system(const char *command)
{
PROCESS_INFORMATION pi;
STARTUPINFO si;
@ -68,7 +70,7 @@ static int win_system(const char *command)
/* We must use a copy of the command as CreateProcess modifies this
argument. */
string=xstrdup (command);
string=xstrdup(command);
memset(&pi,0,sizeof(pi));
memset(&si,0,sizeof(si));
@ -82,42 +84,30 @@ static int win_system(const char *command)
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
xfree (string);
xfree(string);
return 0;
}
#endif
/* method==0 to replace current $PATH, and 1 to append to current
$PATH. */
int set_exec_path(const char *path,int method)
/* Replaces current $PATH */
int set_exec_path(const char *path)
{
char *p,*curpath=NULL;
size_t curlen=0;
char *p;
if(method==1 && (curpath=getenv("PATH")))
curlen=strlen(curpath)+1;
p=xmalloc (5+curlen+strlen(path)+1);
p=xmalloc(5+strlen(path)+1);
strcpy(p,"PATH=");
if(curpath)
{
strcat(p,curpath);
strcat(p,":");
}
strcat(p,path);
if(DBG_EXTPROG)
log_debug("set_exec_path method %d: %s\n",method,p);
log_debug("set_exec_path: %s\n",p);
/* Notice that path is never freed. That is intentional due to the
way putenv() works. This leaks a few bytes if we call
set_exec_path multiple times. */
if(putenv(p)!=0)
return GPG_ERR_GENERAL;
return G10ERR_GENERAL;
else
return 0;
}
@ -128,16 +118,16 @@ 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";
namein=info->flags.binary?"tempin" EXTSEP_S "bin":"tempin" EXTSEP_S "txt";
nameout=info->binary?"tempout" EXTSEP_S "bin":"tempout" EXTSEP_S "txt";
nameout=info->flags.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 (_WIN32)
tmp=xmalloc (256);
tmp=xmalloc(256);
if(GetTempPath(256,tmp)==0)
strcpy(tmp,"c:\\windows\\temp");
else
@ -169,12 +159,12 @@ static int make_tempdir(struct exec_info *info)
#endif
}
info->tempdir=xmalloc (strlen(tmp)+strlen(DIRSEP_S)+10+1);
info->tempdir=xmalloc(strlen(tmp)+strlen(DIRSEP_S)+10+1);
sprintf(info->tempdir,"%s" DIRSEP_S "gpg-XXXXXX",tmp);
#if defined (_WIN32)
xfree (tmp);
xfree(tmp);
#endif
if(mkdtemp(info->tempdir)==NULL)
@ -182,21 +172,21 @@ static int make_tempdir(struct exec_info *info)
info->tempdir,strerror(errno));
else
{
info->madedir=1;
info->flags.madedir=1;
info->tempfile_in=xmalloc (strlen(info->tempdir)+
info->tempfile_in=xmalloc(strlen(info->tempdir)+
strlen(DIRSEP_S)+strlen(namein)+1);
sprintf(info->tempfile_in,"%s" DIRSEP_S "%s",info->tempdir,namein);
if(!info->writeonly)
if(!info->flags.writeonly)
{
info->tempfile_out=xmalloc (strlen(info->tempdir)+
info->tempfile_out=xmalloc(strlen(info->tempdir)+
strlen(DIRSEP_S)+strlen(nameout)+1);
sprintf(info->tempfile_out,"%s" DIRSEP_S "%s",info->tempdir,nameout);
}
}
return info->madedir?0:GPG_ERR_GENERAL;
return info->flags.madedir?0:G10ERR_GENERAL;
}
/* Expands %i and %o in the args to the full temp files within the
@ -206,14 +196,14 @@ static int expand_args(struct exec_info *info,const char *args_in)
const char *ch=args_in;
unsigned int size,len;
info->use_temp_files=0;
info->keep_temp_files=0;
info->flags.use_temp_files=0;
info->flags.keep_temp_files=0;
if(DBG_EXTPROG)
log_debug("expanding string \"%s\"\n",args_in);
size=100;
info->command=xmalloc (size);
info->command=xmalloc(size);
len=0;
info->command[0]='\0';
@ -228,31 +218,31 @@ static int expand_args(struct exec_info *info,const char *args_in)
switch(*ch)
{
case 'O':
info->keep_temp_files=1;
info->flags.keep_temp_files=1;
/* fall through */
case 'o': /* out */
if(!info->madedir)
if(!info->flags.madedir)
{
if(make_tempdir(info))
goto fail;
}
append=info->tempfile_out;
info->use_temp_files=1;
info->flags.use_temp_files=1;
break;
case 'I':
info->keep_temp_files=1;
info->flags.keep_temp_files=1;
/* fall through */
case 'i': /* in */
if(!info->madedir)
if(!info->flags.madedir)
{
if(make_tempdir(info))
goto fail;
}
append=info->tempfile_in;
info->use_temp_files=1;
info->flags.use_temp_files=1;
break;
case '%':
@ -293,17 +283,17 @@ static int expand_args(struct exec_info *info,const char *args_in)
}
if(DBG_EXTPROG)
log_debug("args expanded to \"%s\", use %d, keep %d\n",
info->command,info->use_temp_files,info->keep_temp_files);
log_debug("args expanded to \"%s\", use %u, keep %u\n",info->command,
info->flags.use_temp_files,info->flags.keep_temp_files);
return 0;
fail:
xfree (info->command);
xfree(info->command);
info->command=NULL;
return GPG_ERR_GENERAL;
return G10ERR_GENERAL;
}
/* Either handles the tempfile creation, or the fork/exec. If it
@ -315,7 +305,7 @@ static int expand_args(struct exec_info *info,const char *args_in)
int exec_write(struct exec_info **info,const char *program,
const char *args_in,const char *name,int writeonly,int binary)
{
int ret=GPG_ERR_GENERAL;
int ret=G10ERR_GENERAL;
if(opt.exec_disable && !opt.no_perm_warn)
{
@ -335,22 +325,22 @@ int exec_write(struct exec_info **info,const char *program,
if(program==NULL && args_in==NULL)
BUG();
*info=xcalloc (1,sizeof(struct exec_info));
*info=xmalloc_clear(sizeof(struct exec_info));
if(name)
(*info)->name=xstrdup (name);
(*info)->binary=binary;
(*info)->writeonly=writeonly;
(*info)->name=xstrdup(name);
(*info)->flags.binary=binary;
(*info)->flags.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)
if(!(*info)->flags.use_temp_files)
{
log_error(_("this platform requires temp files when calling external "
"programs\n"));
log_error(_("this platform requires temporary files when calling"
" external programs\n"));
goto fail;
}
@ -358,7 +348,7 @@ int exec_write(struct exec_info **info,const char *program,
/* 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)
if(args_in==NULL || (*info)->flags.use_temp_files==0)
{
int to[2],from[2];
@ -392,7 +382,7 @@ int exec_write(struct exec_info **info,const char *program,
/* If the program isn't going to respond back, they get to
keep their stdout/stderr */
if(!(*info)->writeonly)
if(!(*info)->flags.writeonly)
{
/* implied close of STDERR */
if(dup2(STDOUT_FILENO,STDERR_FILENO)==-1)
@ -426,10 +416,12 @@ int exec_write(struct exec_info **info,const char *program,
/* 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));
if(args_in==NULL)
log_error(_("unable to execute program `%s': %s\n"),
program,strerror(errno));
else
log_error(_("unable to execute shell `%s': %s\n"),
shell,strerror(errno));
/* This mimics the POSIX sh behavior - 127 means "not found"
from the shell. */
@ -446,8 +438,8 @@ int exec_write(struct exec_info **info,const char *program,
(*info)->tochild=fdopen(to[1],binary?"wb":"w");
if((*info)->tochild==NULL)
{
ret = gpg_error_from_errno (errno);
close(to[1]);
ret=G10ERR_WRITE_FILE;
goto fail;
}
@ -456,8 +448,8 @@ int exec_write(struct exec_info **info,const char *program,
(*info)->fromchild=iobuf_fdopen(from[0],"r");
if((*info)->fromchild==NULL)
{
ret = gpg_error_from_errno (errno);
close(from[0]);
ret=G10ERR_READ_FILE;
goto fail;
}
@ -472,12 +464,18 @@ int exec_write(struct exec_info **info,const char *program,
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( is_secured_filename ((*info)->tempfile_in) )
{
(*info)->tochild = NULL;
errno = EPERM;
}
else
(*info)->tochild=fopen((*info)->tempfile_in,binary?"wb":"w");
if((*info)->tochild==NULL)
{
ret = gpg_error_from_errno (errno);
log_error(_("can't create `%s': %s\n"),
(*info)->tempfile_in,strerror(errno));
ret=G10ERR_WRITE_FILE;
goto fail;
}
@ -489,18 +487,18 @@ int exec_write(struct exec_info **info,const char *program,
int exec_read(struct exec_info *info)
{
int ret=GPG_ERR_GENERAL;
int ret=G10ERR_GENERAL;
fclose(info->tochild);
info->tochild=NULL;
if(info->use_temp_files)
if(info->flags.use_temp_files)
{
if(DBG_EXTPROG)
log_debug("system() command is %s\n",info->command);
#if defined (_WIN32)
info->progreturn=win_system(info->command);
info->progreturn=w32_system(info->command);
#else
info->progreturn=system(info->command);
#endif
@ -537,14 +535,21 @@ int exec_read(struct exec_info *info)
goto fail;
}
if(!info->writeonly)
if(!info->flags.writeonly)
{
info->fromchild=iobuf_open(info->tempfile_out);
if (info->fromchild
&& is_secured_file (iobuf_get_fd (info->fromchild)))
{
iobuf_close (info->fromchild);
info->fromchild = NULL;
errno = EPERM;
}
if(info->fromchild==NULL)
{
ret = gpg_error_from_errno (errno);
log_error(_("unable to read external program response: %s\n"),
strerror(errno));
ret=G10ERR_READ_FILE;
goto fail;
}
@ -583,7 +588,7 @@ int exec_finish(struct exec_info *info)
}
#endif
if(info->madedir && !info->keep_temp_files)
if(info->flags.madedir && !info->flags.keep_temp_files)
{
if(info->tempfile_in)
{
@ -604,12 +609,12 @@ int exec_finish(struct exec_info *info)
info->tempdir,strerror(errno));
}
xfree (info->command);
xfree (info->name);
xfree (info->tempdir);
xfree (info->tempfile_in);
xfree (info->tempfile_out);
xfree (info);
xfree(info->command);
xfree(info->name);
xfree(info->tempdir);
xfree(info->tempfile_in);
xfree(info->tempfile_out);
xfree(info);
return ret;
}

View File

@ -1,5 +1,5 @@
/* exec.h
* Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
* Copyright (C) 2001, 2002, 2005 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -15,7 +15,8 @@
*
* 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
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
#ifndef _EXEC_H_
@ -23,11 +24,20 @@
#include <unistd.h>
#include <stdio.h>
#include "../common/iobuf.h"
struct exec_info
{
int progreturn,binary,writeonly,madedir,use_temp_files,keep_temp_files;
int progreturn;
struct
{
unsigned int binary:1;
unsigned int writeonly:1;
unsigned int madedir:1;
unsigned int use_temp_files:1;
unsigned int keep_temp_files:1;
} flags;
pid_t child;
FILE *tochild;
iobuf_t fromchild;
@ -38,6 +48,6 @@ 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);
int set_exec_path(const char *path,int method);
int set_exec_path(const char *path);
#endif /* !_EXEC_H_ */

View File

@ -1,6 +1,6 @@
/* export.c
* Copyright (C) 1998, 1999, 2000, 2001, 2002,
* 2003 Free Software Foundation, Inc.
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004,
* 2005 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -16,7 +16,8 @@
*
* 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
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
#include <config.h>
@ -26,38 +27,68 @@
#include <errno.h>
#include <assert.h>
#include "gpg.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"
#include "trustdb.h"
/* An object to keep track of subkeys. */
struct subkey_list_s
{
struct subkey_list_s *next;
u32 kid[2];
};
typedef struct subkey_list_s *subkey_list_t;
static int do_export( STRLIST users, int secret, unsigned int options );
static int do_export_stream( iobuf_t out, STRLIST users, int secret,
static int do_export_stream( IOBUF out, STRLIST users, int secret,
KBNODE *keyblock_out, unsigned int options,
int *any );
static int build_sexp (iobuf_t out, PACKET *pkt, int *indent);
int
parse_export_options(char *str,unsigned int *options)
parse_export_options(char *str,unsigned int *options,int noisy)
{
struct parse_options export_opts[]=
{
{"include-non-rfc",EXPORT_INCLUDE_NON_RFC},
{"include-local-sigs",EXPORT_INCLUDE_LOCAL_SIGS},
{"include-attributes",EXPORT_INCLUDE_ATTRIBUTES},
{"include-sensitive-revkeys",EXPORT_INCLUDE_SENSITIVE_REVKEYS},
{"sexp-format",EXPORT_SEXP_FORMAT},
{NULL,0}
{"export-local-sigs",EXPORT_LOCAL_SIGS,NULL,
N_("export signatures that are marked as local-only")},
{"export-attributes",EXPORT_ATTRIBUTES,NULL,
N_("export attribute user IDs (generally photo IDs)")},
{"export-sensitive-revkeys",EXPORT_SENSITIVE_REVKEYS,NULL,
N_("export revocation keys marked as \"sensitive\"")},
{"export-reset-subkey-passwd",EXPORT_RESET_SUBKEY_PASSWD,NULL,
N_("remove the passphrase from exported subkeys")},
{"export-clean",EXPORT_CLEAN,NULL,
N_("remove unusable parts from key during export")},
{"export-minimal",EXPORT_MINIMAL|EXPORT_CLEAN,NULL,
N_("remove as much as possible from key during export")},
{"export-sexp-format",EXPORT_SEXP_FORMAT, NULL,
N_("export keys in an S-expression based format")},
/* Aliases for backward compatibility */
{"include-local-sigs",EXPORT_LOCAL_SIGS,NULL,NULL},
{"include-attributes",EXPORT_ATTRIBUTES,NULL,NULL},
{"include-sensitive-revkeys",EXPORT_SENSITIVE_REVKEYS,NULL,NULL},
/* dummy */
{"export-unusable-sigs",0,NULL,NULL},
{"export-clean-sigs",0,NULL,NULL},
{"export-clean-uids",0,NULL,NULL},
{NULL,0,NULL,NULL}
/* add tags for include revoked and disabled? */
};
return parse_options(str,options,export_opts);
return parse_options(str,options,export_opts,noisy);
}
/****************
* Export the public keys (to standard out or --output).
* Depending on opt.armor the output is armored.
@ -74,7 +105,7 @@ export_pubkeys( STRLIST users, unsigned int options )
* been exported
*/
int
export_pubkeys_stream( iobuf_t out, STRLIST users,
export_pubkeys_stream( IOBUF out, STRLIST users,
KBNODE *keyblock_out, unsigned int options )
{
int any, rc;
@ -90,7 +121,7 @@ export_seckeys( STRLIST users )
{
/* Use only relevant options for the secret key. */
unsigned int options = (opt.export_options & EXPORT_SEXP_FORMAT);
return do_export (users, 1, options);
return do_export( users, 1, options );
}
int
@ -98,37 +129,38 @@ export_secsubkeys( STRLIST users )
{
/* Use only relevant options for the secret key. */
unsigned int options = (opt.export_options & EXPORT_SEXP_FORMAT);
return do_export( users, 2, options);
return do_export( users, 2, options );
}
static int
do_export (STRLIST users, int secret, unsigned int options)
do_export( STRLIST users, int secret, unsigned int options )
{
iobuf_t out = NULL;
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);
memset( &afx, 0, sizeof afx);
memset( &zfx, 0, sizeof zfx);
rc = open_outfile (NULL, 0, &out);
rc = open_outfile( NULL, 0, &out );
if (rc)
return rc;
if (!(options & EXPORT_SEXP_FORMAT))
{
if (opt.armor)
if ( opt.armor )
{
afx.what = secret?5:1;
iobuf_push_filter( out, armor_filter, &afx );
iobuf_push_filter ( out, armor_filter, &afx );
}
if (opt.compress_keys && opt.compress)
iobuf_push_filter( out, compress_filter, &zfx );
if ( opt.compress_keys )
push_compress_filter (out,&zfx,default_compress_algo());
}
rc = do_export_stream (out, users, secret, NULL, options, &any );
if (rc || !any)
rc = do_export_stream ( out, users, secret, NULL, options, &any );
if ( rc || !any )
iobuf_cancel (out);
else
iobuf_close (out);
@ -136,11 +168,129 @@ do_export (STRLIST users, int secret, unsigned int options)
}
/* Release an entire subkey list. */
static void
release_subkey_list (subkey_list_t list)
{
while (list)
{
subkey_list_t tmp = list->next;;
xfree (list);
list = tmp;
}
}
/* Returns true if NODE is a subkey and contained in LIST. */
static int
subkey_in_list_p (subkey_list_t list, KBNODE node)
{
if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY
|| node->pkt->pkttype == PKT_SECRET_SUBKEY )
{
u32 kid[2];
if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
keyid_from_pk (node->pkt->pkt.public_key, kid);
else
keyid_from_sk (node->pkt->pkt.secret_key, kid);
for (; list; list = list->next)
if (list->kid[0] == kid[0] && list->kid[1] == kid[1])
return 1;
}
return 0;
}
/* Allocate a new subkey list item from NODE. */
static subkey_list_t
new_subkey_list_item (KBNODE node)
{
subkey_list_t list = xcalloc (1, sizeof *list);
if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
keyid_from_pk (node->pkt->pkt.public_key, list->kid);
else if (node->pkt->pkttype == PKT_SECRET_SUBKEY)
keyid_from_sk (node->pkt->pkt.secret_key, list->kid);
return list;
}
/* Helper function to check whether the subkey at NODE actually
matches the description at DESC. The function returns true if the
key under question has been specified by an exact specification
(keyID or fingerprint) and does match the one at NODE. It is
assumed that the packet at NODE is either a public or secret
subkey. */
static int
exact_subkey_match_p (KEYDB_SEARCH_DESC *desc, KBNODE node)
{
u32 kid[2];
byte fpr[MAX_FINGERPRINT_LEN];
size_t fprlen;
int result = 0;
switch(desc->mode)
{
case KEYDB_SEARCH_MODE_SHORT_KID:
case KEYDB_SEARCH_MODE_LONG_KID:
if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
keyid_from_pk (node->pkt->pkt.public_key, kid);
else
keyid_from_sk (node->pkt->pkt.secret_key, kid);
break;
case KEYDB_SEARCH_MODE_FPR16:
case KEYDB_SEARCH_MODE_FPR20:
case KEYDB_SEARCH_MODE_FPR:
if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
fingerprint_from_pk (node->pkt->pkt.public_key, fpr,&fprlen);
else
fingerprint_from_sk (node->pkt->pkt.secret_key, fpr,&fprlen);
break;
default:
break;
}
switch(desc->mode)
{
case KEYDB_SEARCH_MODE_SHORT_KID:
if (desc->u.kid[1] == kid[1])
result = 1;
break;
case KEYDB_SEARCH_MODE_LONG_KID:
if (desc->u.kid[0] == kid[0] && desc->u.kid[1] == kid[1])
result = 1;
break;
case KEYDB_SEARCH_MODE_FPR16:
if (!memcmp (desc->u.fpr, fpr, 16))
result = 1;
break;
case KEYDB_SEARCH_MODE_FPR20:
case KEYDB_SEARCH_MODE_FPR:
if (!memcmp (desc->u.fpr, fpr, 20))
result = 1;
break;
default:
break;
}
return result;
}
/* If keyblock_out is non-NULL, AND the exit code is zero, then it
contains a pointer to the first keyblock found and exported. No
other keyblocks are exported. The caller must free it. */
static int
do_export_stream( iobuf_t out, STRLIST users, int secret,
do_export_stream( IOBUF out, STRLIST users, int secret,
KBNODE *keyblock_out, unsigned int options, int *any )
{
int rc = 0;
@ -149,6 +299,7 @@ do_export_stream( iobuf_t out, STRLIST users, int secret,
KBNODE kbctx, node;
size_t ndesc, descindex;
KEYDB_SEARCH_DESC *desc = NULL;
subkey_list_t subkey_list = NULL; /* Track alreay processed subkeys. */
KEYDB_HANDLE kdbhd;
STRLIST sl;
int indent = 0;
@ -159,7 +310,7 @@ do_export_stream( iobuf_t out, STRLIST users, int secret,
if (!users) {
ndesc = 1;
desc = xcalloc (1, ndesc * sizeof *desc);
desc = xcalloc ( ndesc, sizeof *desc );
desc[0].mode = KEYDB_SEARCH_MODE_FIRST;
}
else {
@ -171,11 +322,11 @@ do_export_stream( iobuf_t out, STRLIST users, int secret,
if (classify_user_id (sl->d, desc+ndesc))
ndesc++;
else
log_error (_("key `%s' not found: %s\n"),
sl->d, gpg_strerror (GPG_ERR_INV_USER_ID));
log_error (_("key \"%s\" not found: %s\n"),
sl->d, g10_errstr (G10ERR_INV_USER_ID));
}
/* it would be nice to see which of the given users did
/* 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
@ -183,6 +334,14 @@ do_export_stream( iobuf_t out, STRLIST users, int secret,
do this we need an extra flag to enable this feature so */
}
#ifdef ENABLE_SELINUX_HACKS
if (secret) {
log_error (_("exporting secret keys not allowed\n"));
rc = G10ERR_GENERAL;
goto leave;
}
#endif
while (!(rc = keydb_search2 (kdbhd, desc, ndesc, &descindex))) {
int sha1_warned=0,skip_until_subkey=0;
u32 sk_keyid[2];
@ -190,49 +349,59 @@ do_export_stream( iobuf_t out, STRLIST users, int secret,
if (!users)
desc[0].mode = KEYDB_SEARCH_MODE_NEXT;
/* read the keyblock */
/* Read the keyblock. */
rc = keydb_get_keyblock (kdbhd, &keyblock );
if( rc ) {
log_error (_("error reading keyblock: %s\n"), gpg_strerror (rc) );
log_error (_("error reading keyblock: %s\n"), g10_errstr(rc) );
goto leave;
}
/* do not export keys which are incompatible with rfc2440 */
if( !(options&EXPORT_INCLUDE_NON_RFC) &&
(node = find_kbnode( keyblock, PKT_PUBLIC_KEY )) ) {
PKT_public_key *pk = node->pkt->pkt.public_key;
if( pk->version == 3 && pk->pubkey_algo > 3 ) {
log_info(_("key %08lX: not a rfc2440 key - skipped\n"),
(ulong)keyid_from_pk( pk, NULL) );
continue;
}
}
node=find_kbnode( keyblock, PKT_SECRET_KEY );
if(node)
if((node=find_kbnode(keyblock,PKT_SECRET_KEY)))
{
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 */
/* 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]);
log_info(_("key %s: not protected - skipped\n"),
keystr(sk_keyid));
continue;
}
/* no v3 keys with GNU mode 1001 */
/* 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]);
log_info(_("key %s: PGP 2.x style key - skipped\n"),
keystr(sk_keyid));
continue;
}
/* It does not make sense to export a key with a primary
key on card using a non-key stub. We simply skip those
keys when used with --export-secret-subkeys. */
if (secret == 2 && sk->is_protected
&& sk->protect.s2k.mode == 1002 )
{
log_info(_("key %s: key material on-card - skipped\n"),
keystr(sk_keyid));
continue;
}
}
else
{
/* It's a public key export, so do the cleaning if
requested. Note that both export-clean and
export-minimal only apply to UID sigs (0x10, 0x11,
0x12, and 0x13). A designated revocation is never
stripped, even with export-minimal set. */
if(options&EXPORT_CLEAN)
clean_key(keyblock,opt.verbose,options&EXPORT_MINIMAL,NULL,NULL);
}
/* and write it */
/* And write it. */
for( kbctx=NULL; (node = walk_kbnode( keyblock, &kbctx, 0 )); ) {
if( skip_until_subkey )
{
@ -243,104 +412,92 @@ do_export_stream( iobuf_t out, STRLIST users, int secret,
continue;
}
/* don't export any comment packets but those in the
* secret keyring */
if( !secret && node->pkt->pkttype == PKT_COMMENT )
continue;
/* We used to use comment packets, but not any longer. In
case we still have comments on a key, strip them here
before we call build_packet(). */
if( node->pkt->pkttype == PKT_COMMENT )
continue;
/* make sure that ring_trust packets never get exported */
/* Make sure that ring_trust packets never get exported. */
if (node->pkt->pkttype == PKT_RING_TRUST)
continue;
/* If exact is set, then we only export what was requested
(plus the primary key, if the user didn't specifically
request it) */
request it). */
if(desc[descindex].exact
&& (node->pkt->pkttype==PKT_PUBLIC_SUBKEY
|| node->pkt->pkttype==PKT_SECRET_SUBKEY))
{
u32 kid[2];
byte fpr[MAX_FINGERPRINT_LEN];
size_t fprlen;
if (!exact_subkey_match_p (desc+descindex, node))
{
/* Before skipping this subkey, check whether any
other description wants an exact match on a
subkey and include that subkey into the output
too. Need to add this subkey to a list so that
it won't get processed a second time.
So the first step here is to check that list and
skip in any case if the key is in that list.
switch(desc[descindex].mode)
{
case KEYDB_SEARCH_MODE_SHORT_KID:
case KEYDB_SEARCH_MODE_LONG_KID:
if(node->pkt->pkttype==PKT_PUBLIC_SUBKEY)
keyid_from_pk(node->pkt->pkt.public_key,kid);
else
keyid_from_sk(node->pkt->pkt.secret_key,kid);
break;
We need this whole mess because the import
function is not able to merge secret keys and
thus it is useless to output them as two
separate keys and have import merge them. */
if (subkey_in_list_p (subkey_list, node))
skip_until_subkey = 1; /* Already processed this one. */
else
{
size_t j;
case KEYDB_SEARCH_MODE_FPR16:
case KEYDB_SEARCH_MODE_FPR20:
case KEYDB_SEARCH_MODE_FPR:
if(node->pkt->pkttype==PKT_PUBLIC_SUBKEY)
fingerprint_from_pk(node->pkt->pkt.public_key,
fpr,&fprlen);
else
fingerprint_from_sk(node->pkt->pkt.secret_key,
fpr,&fprlen);
break;
default:
break;
}
switch(desc[descindex].mode)
{
case KEYDB_SEARCH_MODE_SHORT_KID:
if (desc[descindex].u.kid[1] != kid[1])
skip_until_subkey=1;
break;
case KEYDB_SEARCH_MODE_LONG_KID:
if (desc[descindex].u.kid[0] != kid[0]
|| desc[descindex].u.kid[1] != kid[1])
skip_until_subkey=1;
break;
case KEYDB_SEARCH_MODE_FPR16:
if (memcmp (desc[descindex].u.fpr, fpr, 16))
skip_until_subkey=1;
break;
case KEYDB_SEARCH_MODE_FPR20:
case KEYDB_SEARCH_MODE_FPR:
if (memcmp (desc[descindex].u.fpr, fpr, 20))
skip_until_subkey=1;
break;
default:
break;
}
for (j=0; j < ndesc; j++)
if (j != descindex && desc[j].exact
&& exact_subkey_match_p (desc+j, node))
break;
if (!(j < ndesc))
skip_until_subkey = 1; /* No other one matching. */
}
}
if(skip_until_subkey)
continue;
/* Mark this one as processed. */
{
subkey_list_t tmp = new_subkey_list_item (node);
tmp->next = subkey_list;
subkey_list = tmp;
}
}
if( node->pkt->pkttype == PKT_SIGNATURE ) {
/* do not export packets which are marked as not exportable */
if( !(options&EXPORT_INCLUDE_LOCAL_SIGS) &&
!node->pkt->pkt.signature->flags.exportable )
continue; /* not exportable */
if(node->pkt->pkttype==PKT_SIGNATURE)
{
/* do not export packets which are marked as not
exportable */
if(!(options&EXPORT_LOCAL_SIGS)
&& !node->pkt->pkt.signature->flags.exportable)
continue; /* not exportable */
/* Do not export packets with a "sensitive" revocation
key unless the user wants us to. Note that we do
export these when issuing the actual revocation (see
revoke.c). */
if( !(options&EXPORT_INCLUDE_SENSITIVE_REVKEYS) &&
node->pkt->pkt.signature->revkey ) {
int i;
/* Do not export packets with a "sensitive" revocation
key unless the user wants us to. Note that we do
export these when issuing the actual revocation
(see revoke.c). */
if(!(options&EXPORT_SENSITIVE_REVKEYS)
&& 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)
break;
for(i=0;i<node->pkt->pkt.signature->numrevkeys;i++)
if(node->pkt->pkt.signature->revkey[i]->class & 0x40)
break;
if(i<node->pkt->pkt.signature->numrevkeys)
continue;
if(i<node->pkt->pkt.signature->numrevkeys)
continue;
}
}
}
/* Don't export attribs? */
if( !(options&EXPORT_INCLUDE_ATTRIBUTES) &&
if( !(options&EXPORT_ATTRIBUTES) &&
node->pkt->pkttype == PKT_USER_ID &&
node->pkt->pkt.user_id->attrib_data ) {
/* Skip until we get to something that is not an attrib
@ -352,8 +509,9 @@ do_export_stream( iobuf_t out, STRLIST users, int secret,
continue;
}
if( secret == 2 && node->pkt->pkttype == PKT_SECRET_KEY ) {
/* we don't want to export the secret parts of the
if( secret == 2 && node->pkt->pkttype == PKT_SECRET_KEY )
{
/* We don't want to export the secret parts of the
* primary key, this is done by using GNU protection mode 1001
*/
int save_mode = node->pkt->pkt.secret_key->protect.s2k.mode;
@ -363,42 +521,91 @@ do_export_stream( iobuf_t out, STRLIST users, int secret,
else
rc = build_packet (out, node->pkt);
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]);
}
else if (secret == 2 && node->pkt->pkttype == PKT_SECRET_SUBKEY
&& (opt.export_options&EXPORT_RESET_SUBKEY_PASSWD))
{
/* If the subkey is protected reset the passphrase to
export an unprotected subkey. This feature is
useful in cases of a subkey copied to an unattended
machine where a passphrase is not required. */
PKT_secret_key *sk_save, *sk;
sha1_warned=1;
}
sk_save = node->pkt->pkt.secret_key;
sk = copy_secret_key (NULL, sk_save);
node->pkt->pkt.secret_key = sk;
log_info (_("about to export an unprotected subkey\n"));
switch (is_secret_key_protected (sk))
{
case -1:
rc = G10ERR_PUBKEY_ALGO;
break;
case 0:
break;
default:
if (sk->protect.s2k.mode == 1001)
; /* No secret parts. */
else if( sk->protect.s2k.mode == 1002 )
; /* Card key stub. */
else
{
rc = check_secret_key( sk, 0 );
}
break;
}
if (rc)
{
node->pkt->pkt.secret_key = sk_save;
free_secret_key (sk);
log_error (_("failed to unprotect the subkey: %s\n"),
g10_errstr (rc));
goto leave;
}
rc = build_packet (out, node->pkt);
node->pkt->pkt.secret_key = sk_save;
free_secret_key (sk);
}
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 %s does not have a "
"simple SK checksum\n"),keystr(sk_keyid));
sha1_warned=1;
}
if ((options&EXPORT_SEXP_FORMAT))
rc = build_sexp (out, node->pkt, &indent);
else
rc = build_packet (out, node->pkt);
}
}
if( rc ) {
log_error("build_packet(%d) failed: %s\n",
node->pkt->pkttype, gpg_strerror (rc) );
node->pkt->pkttype, g10_errstr(rc) );
rc = G10ERR_WRITE_FILE;
goto leave;
}
}
if ((options&EXPORT_SEXP_FORMAT) && indent)
{
for (; indent; indent--)
iobuf_put (out, ')');
iobuf_put (out, '\n');
}
++*any;
if(keyblock_out)
{
@ -416,7 +623,8 @@ do_export_stream( iobuf_t out, STRLIST users, int secret,
rc = 0;
leave:
xfree (desc);
release_subkey_list (subkey_list);
xfree(desc);
keydb_release (kdbhd);
if(rc || keyblock_out==NULL)
release_kbnode( keyblock );
@ -426,6 +634,7 @@ do_export_stream( iobuf_t out, STRLIST users, int secret,
}
static int
write_sexp_line (iobuf_t out, int *indent, const char *text)
{
@ -524,8 +733,8 @@ build_sexp_seckey (iobuf_t out, PACKET *pkt, int *indent)
}
/* For some packet types we write them in a S-Exp like format. This is
still EXPERIMENTAL and subject to change. */
/* For some packet types we write them in a S-expression format. This
is still EXPERIMENTAL and subject to change. */
static int
build_sexp (iobuf_t out, PACKET *pkt, int *indent)
{

View File

@ -1,5 +1,6 @@
/* filter.h
* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
* Copyright (C) 1998, 1999, 2000, 2001, 2003,
* 2005 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -15,18 +16,18 @@
*
* 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
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
#ifndef G10_FILTER_H
#define G10_FILTER_H
#include "types.h"
#include "cipher.h"
#include "iobuf.h"
typedef struct {
MD_HANDLE md; /* catch all */
MD_HANDLE md2; /* if we want to calculate an alternate hash */
gcry_md_hd_t md; /* catch all */
gcry_md_hd_t md2; /* if we want to calculate an alternate hash */
size_t maxbuf_size;
} md_filter_context_t;
@ -49,6 +50,10 @@ typedef struct {
int truncated; /* number of truncated lines */
int qp_detected;
int pgp2mode;
byte eol[3]; /* The end of line characters as a
zero-terminated string. Defaults
(eol[0]=='\0') to whatever the local
platform uses. */
byte *buffer; /* malloced buffer */
unsigned buffer_size; /* and size of this buffer */
@ -87,9 +92,9 @@ typedef struct compress_filter_context_s compress_filter_context_t;
typedef struct {
DEK *dek;
u32 datalen;
CIPHER_HANDLE cipher_hd;
gcry_cipher_hd_t cipher_hd;
int header;
MD_HANDLE mdc_hash;
gcry_md_hd_t mdc_hash;
byte enchash[20];
int create_mdc; /* flag will be set by the cipher filter */
} cipher_filter_context_t;
@ -104,7 +109,7 @@ typedef struct {
int truncated; /* number of truncated lines */
int not_dash_escaped;
int escape_from;
MD_HANDLE md;
gcry_md_hd_t md;
int pending_lf;
int pending_esc;
} text_filter_context_t;
@ -121,35 +126,36 @@ typedef struct {
/* encrypt_filter_context_t defined in main.h */
/*-- mdfilter.c --*/
int md_filter( void *opaque, int control, iobuf_t a, byte *buf, size_t *ret_len);
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 );
/*-- armor.c --*/
int use_armor_filter( iobuf_t a );
int use_armor_filter( IOBUF a );
int armor_filter( void *opaque, int control,
iobuf_t chain, byte *buf, size_t *ret_len);
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,
iobuf_t chain, byte *buf, size_t *ret_len);
void push_compress_filter(IOBUF out,compress_filter_context_t *zfx,int algo);
void push_compress_filter2(IOBUF out,compress_filter_context_t *zfx,
int algo,int rel);
/*-- cipher.c --*/
int cipher_filter( void *opaque, int control,
iobuf_t chain, byte *buf, size_t *ret_len);
IOBUF chain, byte *buf, size_t *ret_len);
/*-- textfilter.c --*/
int text_filter( void *opaque, int control,
iobuf_t chain, byte *buf, size_t *ret_len);
int copy_clearsig_text( iobuf_t out, iobuf_t inp, MD_HANDLE md,
int escape_dash, int escape_from, int pgp2mode );
IOBUF chain, byte *buf, size_t *ret_len);
int copy_clearsig_text (IOBUF out, IOBUF inp, gcry_md_hd_t md,
int escape_dash, int escape_from, int pgp2mode);
/*-- progress.c --*/
int progress_filter (void *opaque, int control,
iobuf_t a, byte *buf, size_t *ret_len);
IOBUF a, byte *buf, size_t *ret_len);
void handle_progress (progress_filter_context_t *pfx,
iobuf_t inp, const char *name);
IOBUF inp, const char *name);
#endif /*G10_FILTER_H*/

View File

@ -1,6 +1,6 @@
/* free-packet.c - cleanup stuff for packets
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003
* Free Software Foundation, Inc.
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003,
* 2005 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -16,7 +16,8 @@
*
* 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
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
#include <config.h>
@ -25,18 +26,18 @@
#include <string.h>
#include <assert.h>
#include "gpg.h"
#include "packet.h"
#include "iobuf.h"
#include "mpi.h"
#include "../common/iobuf.h"
#include "util.h"
#include "cipher.h"
#include "memory.h"
#include "options.h"
#include "options.h"
void
free_symkey_enc( PKT_symkey_enc *enc )
{
xfree (enc);
xfree(enc);
}
void
@ -45,10 +46,10 @@ 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_release(enc->data[0]);
for(i=0; i < n; i++ )
mpi_release ( enc->data[i] );
xfree (enc);
mpi_release( enc->data[i] );
xfree(enc);
}
void
@ -58,14 +59,21 @@ free_seckey_enc( PKT_signature *sig )
n = pubkey_get_nsig( sig->pubkey_algo );
if( !n )
mpi_release (sig->data[0]);
mpi_release(sig->data[0]);
for(i=0; i < n; i++ )
mpi_release ( sig->data[i] );
xfree (sig->revkey);
xfree (sig->hashed);
xfree (sig->unhashed);
xfree (sig);
mpi_release( sig->data[i] );
xfree(sig->revkey);
xfree(sig->hashed);
xfree(sig->unhashed);
if (sig->pka_info)
{
xfree (sig->pka_info->uri);
xfree (sig->pka_info);
}
xfree(sig);
}
@ -75,9 +83,9 @@ 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_release(pk->pkey[0]);
for(i=0; i < n; i++ ) {
mpi_release ( pk->pkey[i] );
mpi_release( pk->pkey[i] );
pk->pkey[i] = NULL;
}
if (pk->prefs) {
@ -89,7 +97,7 @@ release_public_key_parts( PKT_public_key *pk )
pk->user_id = NULL;
}
if (pk->revkey) {
xfree (pk->revkey);
xfree(pk->revkey);
pk->revkey=NULL;
pk->numrevkeys=0;
}
@ -100,7 +108,7 @@ void
free_public_key( PKT_public_key *pk )
{
release_public_key_parts( pk );
xfree (pk);
xfree(pk);
}
@ -150,7 +158,7 @@ copy_public_key ( PKT_public_key *d, PKT_public_key *s)
int n, i;
if( !d )
d = xmalloc (sizeof *d);
d = xmalloc(sizeof *d);
memcpy( d, s, sizeof *d );
d->user_id = scopy_user_id (s->user_id);
d->prefs = copy_prefs (s->prefs);
@ -164,7 +172,7 @@ copy_public_key ( PKT_public_key *d, PKT_public_key *s)
if( !s->revkey && s->numrevkeys )
BUG();
if( s->numrevkeys ) {
d->revkey = xmalloc (sizeof(struct revocation_key)*s->numrevkeys);
d->revkey = xmalloc(sizeof(struct revocation_key)*s->numrevkeys);
memcpy(d->revkey,s->revkey,sizeof(struct revocation_key)*s->numrevkeys);
}
else
@ -194,13 +202,28 @@ copy_public_parts_to_secret_key( PKT_public_key *pk, PKT_secret_key *sk )
sk->keyid[1] = pk->keyid[1];
}
static pka_info_t *
cp_pka_info (const pka_info_t *s)
{
pka_info_t *d = xmalloc (sizeof *s + strlen (s->email));
d->valid = s->valid;
d->checked = s->checked;
d->uri = s->uri? xstrdup (s->uri):NULL;
memcpy (d->fpr, s->fpr, sizeof s->fpr);
strcpy (d->email, s->email);
return d;
}
PKT_signature *
copy_signature( PKT_signature *d, PKT_signature *s )
{
int n, i;
if( !d )
d = xmalloc (sizeof *d);
d = xmalloc(sizeof *d);
memcpy( d, s, sizeof *d );
n = pubkey_get_nsig( s->pubkey_algo );
if( !n )
@ -209,6 +232,7 @@ copy_signature( PKT_signature *d, PKT_signature *s )
for(i=0; i < n; i++ )
d->data[i] = mpi_copy( s->data[i] );
}
d->pka_info = s->pka_info? cp_pka_info (s->pka_info) : NULL;
d->hashed = cp_subpktarea (s->hashed);
d->unhashed = cp_subpktarea (s->unhashed);
if(s->numrevkeys)
@ -241,9 +265,9 @@ release_secret_key_parts( PKT_secret_key *sk )
n = pubkey_get_nskey( sk->pubkey_algo );
if( !n )
mpi_release (sk->skey[0]);
mpi_release(sk->skey[0]);
for(i=0; i < n; i++ ) {
mpi_release ( sk->skey[i] );
mpi_release( sk->skey[i] );
sk->skey[i] = NULL;
}
}
@ -252,7 +276,7 @@ void
free_secret_key( PKT_secret_key *sk )
{
release_secret_key_parts( sk );
xfree (sk);
xfree(sk);
}
PKT_secret_key *
@ -261,29 +285,32 @@ copy_secret_key( PKT_secret_key *d, PKT_secret_key *s )
int n, i;
if( !d )
d = xmalloc (sizeof *d);
d = xmalloc_secure(sizeof *d);
else
release_secret_key_parts (d);
memcpy( d, s, sizeof *d );
n = pubkey_get_nskey( s->pubkey_algo );
if( !n )
d->skey[0] = mpi_copy(s->skey[0]);
d->skey[0] = mpi_copy(s->skey[0]);
else {
for(i=0; i < n; i++ )
d->skey[i] = mpi_copy( s->skey[i] );
d->skey[i] = mpi_copy( s->skey[i] );
}
return d;
}
void
free_comment( PKT_comment *rem )
{
xfree (rem);
xfree(rem);
}
void
free_attributes(PKT_user_id *uid)
{
xfree (uid->attribs);
xfree (uid->attrib_data);
xfree(uid->attribs);
xfree(uid->attrib_data);
uid->attribs=NULL;
uid->attrib_data=NULL;
@ -312,14 +339,14 @@ free_compressed( PKT_compressed *zd )
while( iobuf_read( zd->buf, NULL, 1<<30 ) != -1 )
;
}
xfree (zd);
xfree(zd);
}
void
free_encrypted( PKT_encrypted *ed )
{
if( ed->buf ) { /* have to skip some bytes */
if( iobuf_in_block_mode(ed->buf) ) {
if( ed->is_partial ) {
while( iobuf_read( ed->buf, NULL, 1<<30 ) != -1 )
;
}
@ -333,7 +360,7 @@ free_encrypted( PKT_encrypted *ed )
}
}
}
xfree (ed);
xfree(ed);
}
@ -341,7 +368,7 @@ void
free_plaintext( PKT_plaintext *pt )
{
if( pt->buf ) { /* have to skip some bytes */
if( iobuf_in_block_mode(pt->buf) ) {
if( pt->is_partial ) {
while( iobuf_read( pt->buf, NULL, 1<<30 ) != -1 )
;
}
@ -355,7 +382,7 @@ free_plaintext( PKT_plaintext *pt )
}
}
}
xfree (pt);
xfree(pt);
}
/****************
@ -405,7 +432,7 @@ free_packet( PACKET *pkt )
free_plaintext( pkt->pkt.plaintext );
break;
default:
xfree ( pkt->pkt.generic );
xfree( pkt->pkt.generic );
break;
}
pkt->pkt.generic = NULL;

File diff suppressed because it is too large Load Diff

View File

@ -1,31 +0,0 @@
/* global.h - Local typedefs and constants
* 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_GLOBAL_H
#define GPG_GLOBAL_H
#define MAX_FINGERPRINT_LEN 20
typedef struct kbnode_struct *KBNODE;
typedef struct keydb_search_desc KEYDB_SEARCH_DESC;
#include "gpg.h"
#endif /*GPG_GLOBAL_H*/

2200
g10/gpg.c

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
/* gpg.h - top level include file for gpg etc.
* Copyright (C) 2003 Free Software Foundation, Inc.
* Copyright (C) 2003, 2006 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -32,9 +32,70 @@
#define map_assuan_err(a) \
map_assuan_err_with_source (GPG_ERR_SOURCE_DEFAULT, (a))
#include <gpg-error.h>
#include <gcrypt.h>
/* FIXME: merge this with global.h */
/* Number of bits we accept when reading or writing MPIs. */
#define MAX_EXTERN_MPI_BITS 16384
/* The maximum length of a binary fingerprints. */
#define MAX_FINGERPRINT_LEN 20
/* Forward declarations. */
typedef struct kbnode_struct *KBNODE;
typedef struct keydb_search_desc KEYDB_SEARCH_DESC;
/* Simple wrappers. */
#define g10_errstr(a) gpg_strerror ((a))
/* Mapping of the old erro codes to the gpg-error ones. Fixme: This
is just a temporary solution: We need to do all these gpg_error()
calls in the code. */
#define G10ERR_BAD_KEY GPG_ERR_BAD_KEY
#define G10ERR_BAD_PASS GPG_ERR_BAD_PASS
#define G10ERR_BAD_PUBKEY GPG_ERR_BAD_PUBKEY
#define G10ERR_BAD_SIGN GPG_ERR_BAD_SIGNATURE
#define G10ERR_BAD_URI GPG_ERR_BAD_URI
#define G10ERR_CHECKSUM GPG_ERR_CHECKSUM
#define G10ERR_CIPHER_ALGO GPG_ERR_CIPHER_ALGO
#define G10ERR_CLOSE_FILE GPG_ERR_CLOSE_FILE
#define G10ERR_COMPR_ALGO GPG_ERR_COMPR_ALGO
#define G10ERR_CREATE_FILE GPG_ERR_CREATE_FILE
#define G10ERR_DIGEST_ALGO GPG_ERR_DIGEST_ALGO
#define G10ERR_FILE_EXISTS GPG_ERR_EEXIST
#define G10ERR_GENERAL GPG_ERR_GENERAL
#define G10ERR_INV_ARG GPG_ERR_INV_ARG
#define G10ERR_INV_KEYRING GPG_ERR_INV_KEYRING
#define G10ERR_INV_USER_ID GPG_ERR_INV_USER_ID
#define G10ERR_INVALID_ARMOR GPG_ERR_INV_ARMOR
#define G10ERR_INVALID_PACKET GPG_ERR_INV_PACKET
#define G10ERR_KEYRING_OPEN GPG_ERR_KEYRING_OPEN
#define G10ERR_KEYSERVER GPG_ERR_KEYSERVER
#define G10ERR_NO_DATA GPG_ERR_NO_DATA
#define G10ERR_NO_PUBKEY GPG_ERR_NO_PUBKEY
#define G10ERR_NO_SECKEY GPG_ERR_NO_SECKEY
#define G10ERR_NO_USER_ID GPG_ERR_NO_USER_ID
#define G10ERR_NOT_PROCESSED GPG_ERR_NOT_PROCESSED
#define G10ERR_OPEN_FILE GPG_ERR_OPEN_FILE
#define G10ERR_PASSPHRASE GPG_ERR_PASSPHRASE
#define G10ERR_PUBKEY_ALGO GPG_ERR_PUBKEY_ALGO
#define G10ERR_READ_FILE GPG_ERR_READ_FILE
#define G10ERR_RENAME_FILE GPG_ERR_RENAME_FILE
#define G10ERR_RESOURCE_LIMIT GPG_ERR_RESOURCE_LIMIT
#define G10ERR_SIG_CLASS GPG_ERR_SIG_CLASS
#define G10ERR_TIME_CONFLICT GPG_ERR_TIME_CONFLICT
#define G10ERR_TRUSTDB GPG_ERR_TRUSTDB
#define G10ERR_UNEXPECTED GPG_ERR_UNEXPECTED
#define G10ERR_UNKNOWN_PACKET GPG_ERR_UNKNOWN_PACKET
#define G10ERR_UNSUPPORTED GPG_ERR_UNSUPPORTED
#define G10ERR_UNU_PUBKEY GPG_ERR_UNUSABLE_PUBKEY
#define G10ERR_UNU_SECKEY GPG_ERR_UNUSABLE_SECKEY
#define G10ERR_WRONG_SECKEY GPG_ERR_WRONG_SECKEY
#endif /*GNUPG_G10_GPG_H*/

View File

@ -1,6 +1,6 @@
/* gpgv.c - The GnuPG signature verify utility
* Copyright (C) 1998, 1999, 2000, 2001, 2002,
* 2003 Free Software Foundation, Inc.
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2005,
* 2006 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -16,7 +16,8 @@
*
* 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
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
#include <config.h>
@ -29,23 +30,27 @@
#ifdef HAVE_DOSISH_SYSTEM
#include <fcntl.h> /* for setmode() */
#endif
#ifdef HAVE_LIBREADLINE
#include <stdio.h>
#include <readline/readline.h>
#endif
#define INCLUDED_BY_MAIN_MODULE 1
#include "gpg.h"
#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"
#include "cardglue.h"
enum cmd_and_opt_values { aNull = 0,
@ -79,10 +84,6 @@ static ARGPARSE_OPTS opts[] = {
int g10_errors_seen = 0;
#ifdef __riscos__
RISCOS_GLOBAL_STATICS("GnuPG (gpgv) Heap")
#endif /* __riscos__ */
static const char *
my_strusage( int level )
{
@ -110,23 +111,22 @@ my_strusage( int level )
}
static void
i18n_init(void)
{
#ifdef USE_SIMPLE_GETTEXT
set_gettext_file( PACKAGE_GT );
set_gettext_file (PACKAGE_GT, "Software\\GNU\\GnuPG");
#else
#ifdef ENABLE_NLS
setlocale( LC_ALL, "" );
bindtextdomain( PACKAGE_GT, LOCALEDIR );
textdomain( PACKAGE_GT );
setlocale (LC_ALL, "");
bindtextdomain (PACKAGE_GT, LOCALEDIR);
textdomain (PACKAGE_GT);
#endif
#endif
}
int
main( int argc, char **argv )
{
@ -136,17 +136,13 @@ main( int argc, char **argv )
STRLIST nrings=NULL;
unsigned configlineno;
#ifdef __riscos__
riscos_global_defaults();
#endif /* __riscos__ */
set_strusage (my_strusage);
log_set_prefix ("gpgv", 1);
gnupg_init_signals(0, NULL);
gnupg_init_signals (0, NULL);
i18n_init();
opt.command_fd = -1; /* no command fd */
opt.pgp2_workarounds = 1;
opt.keyserver_options.auto_key_retrieve = 1;
opt.keyserver_options.options|=KEYSERVER_AUTO_KEY_RETRIEVE;
opt.trust_model = TM_ALWAYS;
opt.batch = 1;
@ -164,8 +160,11 @@ main( int argc, char **argv )
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 oVerbose:
opt.verbose++;
opt.list_sigs=1;
gcry_control (GCRYCTL_SET_VERBOSITY, (int)opt.verbose);
break;
case oKeyring: append_to_strlist( &nrings, pargs.r.ret_str); break;
case oStatusFD: set_status_fd( pargs.r.ret_int ); break;
case oLoggerFD:
@ -180,9 +179,7 @@ main( int argc, char **argv )
if( log_get_errorcount(0) )
g10_exit(2);
g10_opt_homedir = opt.homedir;
if( opt.verbose > 1 )
if( opt.verbose > 1 )
set_packet_list_mode(1);
if( !nrings ) /* no keyring given: use default one */
@ -193,7 +190,7 @@ main( int argc, char **argv )
FREE_STRLIST(nrings);
if( (rc = verify_signatures( argc, argv ) ))
log_error("verify signatures failed: %s\n", gpg_strerror (rc) );
log_error("verify signatures failed: %s\n", g10_errstr(rc) );
/* cleanup */
g10_exit(0);
@ -210,14 +207,6 @@ g10_exit( int rc )
}
void
read_trust_options (byte *trust_model,ulong *created,ulong *nextcheck,
byte *marginals,byte *completes,byte *cert_depth)
{
}
/* Stub:
* We have to override the trustcheck from pkclist.c becuase
* this utility assumes that all keys in the keyring are trustworthy
@ -228,6 +217,9 @@ check_signatures_trust( PKT_signature *sig )
return 0;
}
void
read_trust_options(byte *trust_model,ulong *created,ulong *nextcheck,
byte *marginals,byte *completes,byte *cert_depth) {}
/* Stub:
* We don't have the trustdb , so we have to provide some stub functions
@ -240,6 +232,9 @@ cache_disabled_value(PKT_public_key *pk)
return 0;
}
void
check_trustdb_stale(void) {}
int
get_validity_info (PKT_public_key *pk, PKT_user_id *uid)
{
@ -258,7 +253,12 @@ trust_value_to_string (unsigned int value)
return "err";
}
/* Stub: */
const char *
uid_trust_string_fixed(PKT_public_key *key,PKT_user_id *uid)
{
return "err";
}
int
get_ownertrust_info (PKT_public_key *pk)
{
@ -272,35 +272,54 @@ get_ownertrust (PKT_public_key *pk)
}
/* Stub:
/* Stubs:
* Because we only work with trusted keys, it does not make sense to
* get them from a keyserver
*/
struct keyserver_spec *
keyserver_match(struct keyserver_spec *spec) { return NULL; }
int
keyserver_import_keyid( u32 *keyid, void *dummy )
{
return -1;
}
int
keyserver_import_cert(const char *name) { return -1; }
int
keyserver_import_pka(const char *name,unsigned char *fpr) { return -1; }
int
keyserver_import_name(const char *name,struct keyserver_spec *spec)
{
return -1;
}
int
keyserver_import_ldap(const char *name) { return -1; }
/* Stub:
* No encryption here but mainproc links to these functions.
*/
int
get_session_key( PKT_pubkey_enc *k, DEK *dek )
{
return GPG_ERR_GENERAL;
return G10ERR_GENERAL;
}
/* Stub: */
int
get_override_session_key( DEK *dek, const char *string )
{
return GPG_ERR_GENERAL;
return G10ERR_GENERAL;
}
/* Stub: */
int
decrypt_data( void *procctx, PKT_encrypted *ed, DEK *dek )
{
return GPG_ERR_GENERAL;
return G10ERR_GENERAL;
}
@ -318,7 +337,7 @@ display_online_help( const char *keyword )
int
check_secret_key( PKT_secret_key *sk, int n )
{
return GPG_ERR_GENERAL;
return G10ERR_GENERAL;
}
/* Stub:
@ -334,11 +353,25 @@ passphrase_to_dek( u32 *keyid, int pubkey_algo,
return NULL;
}
struct keyserver_spec *parse_preferred_keyserver(PKT_signature *sig) {return NULL;}
struct keyserver_spec *parse_keyserver_uri(const char *uri,int require_scheme,
const char *configname,
unsigned int configlineno)
{
return NULL;
}
void free_keyserver_spec(struct keyserver_spec *keyserver) {}
/* 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;}
#ifdef ENABLE_CARD_SUPPORT
int agent_scd_getattr (const char *name, struct agent_card_info_s *info) {return 0;}
#endif /* ENABLE_CARD_SUPPORT */
/* 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 "?";}
@ -356,10 +389,31 @@ 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_fprintf (FILE *fp, const char *fmt, ... ) { }
void tty_print_string( const byte *p, size_t n ) { }
void tty_print_utf8_string( const byte *p, size_t n ) {}
void tty_print_utf8_string2( const byte *p, size_t n, size_t max_n ) {}
@ -368,10 +422,15 @@ 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;}
#ifdef HAVE_LIBREADLINE
void tty_enable_completion(rl_completion_func_t *completer) {}
void tty_disable_completion(void) {}
#endif
/* 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; }
void destroy_dotlock (DOTLOCK h) {}
int make_dotlock( DOTLOCK h, long timeout ) { return 0;}
int release_dotlock( DOTLOCK h ) {return 0;}
void dotlock_remove_lockfiles(void) {}
void remove_lockfiles(void) {}

View File

@ -1,5 +1,6 @@
/* helptext.c - English help texts
* Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
* Copyright (C) 1998, 1999, 2000, 2001, 2002,
* 2004 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -15,7 +16,8 @@
*
* 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
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
#include <config.h>
@ -58,10 +60,6 @@ static struct helptexts { const char *key; const char *help; } helptexts[] = {
"ultimately trusted\n"
)},
{ "revoked_key.override", N_(
"If you want to use this revoked key anyway, answer \"yes\"."
)},
{ "untrusted_key.override", N_(
"If you want to use this untrusted key anyway, answer \"yes\"."
)},
@ -73,29 +71,17 @@ static struct helptexts { const char *key; const char *help; } helptexts[] = {
{ "keygen.algo", N_(
"Select the algorithm to use.\n"
"\n"
"DSA (aka DSS) is the digital signature algorithm which can only be used\n"
"for signatures. This is the suggested algorithm because verification of\n"
"DSA signatures are much faster than those of ElGamal.\n"
"DSA (aka DSS) is the Digital Signature Algorithm and can only be used\n"
"for signatures.\n"
"\n"
"ElGamal is an algorithm which can be used for signatures and encryption.\n"
"OpenPGP distinguishs between two flavors of this algorithms: an encrypt only\n"
"and a sign+encrypt; actually it is the same, but some parameters must be\n"
"selected in a special way to create a safe key for signatures: this program\n"
"does this but other OpenPGP implementations are not required to understand\n"
"the signature+encryption flavor.\n"
"Elgamal is an encrypt-only algorithm.\n"
"\n"
"The first (primary) key must always be a key which is capable of signing;\n"
"this is the reason why the encryption only ElGamal key is not available in\n"
"this menu."
"RSA may be used for signatures or encryption.\n"
"\n"
"The first (primary) key must always be a key which is capable of signing."
)},
{ "keygen.algo.elg_se", N_(
"Although these keys are defined in RFC2440 they are not suggested\n"
"because they are not supported by all programs and signatures created\n"
"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"
@ -199,7 +185,7 @@ static struct helptexts { const char *key; const char *help; } helptexts[] = {
)},
{ "keyedit.sign_all.okay", N_(
"Answer \"yes\" is you want to sign ALL the user IDs"
"Answer \"yes\" if you want to sign ALL the user IDs"
)},
{ "keyedit.remove.uid.okay", N_(

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,6 @@
/* kbnode.c - keyblock node utility functions
* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
* Copyright (C) 1998, 1999, 2000, 2001, 2002,
* 2005 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -15,7 +16,8 @@
*
* 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
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
#include <config.h>
@ -26,7 +28,6 @@
#include "gpg.h"
#include "util.h"
#include "memory.h"
#include "packet.h"
#include "keydb.h"
@ -43,7 +44,7 @@ alloc_node(void)
if( n )
unused_nodes = n->next;
else
n = xmalloc ( sizeof *n );
n = xmalloc( sizeof *n );
n->next = NULL;
n->pkt = NULL;
n->flag = 0;
@ -60,7 +61,7 @@ free_node( KBNODE n )
n->next = unused_nodes;
unused_nodes = n;
#else
xfree ( n );
xfree( n );
#endif
}
}
@ -96,7 +97,7 @@ release_kbnode( KBNODE n )
n2 = n->next;
if( !is_cloned_kbnode(n) ) {
free_packet( n->pkt );
xfree ( n->pkt );
xfree( n->pkt );
}
free_node( n );
n = n2;
@ -114,8 +115,6 @@ delete_kbnode( KBNODE node )
node->private_flag |= 1;
}
/****************
* Append NODE to ROOT. ROOT must exist!
*/
@ -269,7 +268,7 @@ commit_kbnode( KBNODE *root )
nl->next = n->next;
if( !is_cloned_kbnode(n) ) {
free_packet( n->pkt );
xfree ( n->pkt );
xfree( n->pkt );
}
free_node( n );
changed = 1;
@ -293,7 +292,7 @@ remove_kbnode( KBNODE *root, KBNODE node )
nl->next = n->next;
if( !is_cloned_kbnode(n) ) {
free_packet( n->pkt );
xfree ( n->pkt );
xfree( n->pkt );
}
free_node( n );
}

View File

@ -1,5 +1,5 @@
/* keydb.c - key database dispatcher
* Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
* Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -15,7 +15,8 @@
*
* 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
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
#include <config.h>
@ -71,6 +72,124 @@ static int lock_all (KEYDB_HANDLE hd);
static void unlock_all (KEYDB_HANDLE hd);
/* Handle the creation of a keyring if it does not yet exist. Take
into acount that other processes might have the keyring already
locked. This lock check does not work if the directory itself is
not yet available. */
static int
maybe_create_keyring (char *filename, int force)
{
DOTLOCK lockhd = NULL;
IOBUF iobuf;
int rc;
mode_t oldmask;
char *last_slash_in_filename;
/* A quick test whether the filename already exists. */
if (!access (filename, F_OK))
return 0;
/* If we don't want to create a new file at all, there is no need to
go any further - bail out right here. */
if (!force)
return gpg_error (GPG_ERR_ENOENT);
/* First of all we try to create the home directory. Note, that we
don't do any locking here because any sane application of gpg
would create the home directory by itself and not rely on gpg's
tricky auto-creation which is anyway only done for some home
directory name patterns. */
last_slash_in_filename = strrchr (filename, DIRSEP_C);
*last_slash_in_filename = 0;
if (access(filename, F_OK))
{
static int tried;
if (!tried)
{
tried = 1;
try_make_homedir (filename);
}
if (access (filename, F_OK))
{
rc = gpg_error_from_errno (errno);
*last_slash_in_filename = DIRSEP_C;
goto leave;
}
}
*last_slash_in_filename = DIRSEP_C;
/* To avoid races with other instances of gpg trying to create or
update the keyring (it is removed during an update for a short
time), we do the next stuff in a locked state. */
lockhd = create_dotlock (filename);
if (!lockhd)
{
/* A reason for this to fail is that the directory is not
writable. However, this whole locking stuff does not make
sense if this is the case. An empty non-writable directory
with no keyring is not really useful at all. */
if (opt.verbose)
log_info ("can't allocate lock for `%s'\n", filename );
if (!force)
return G10ERR_OPEN_FILE;
else
return G10ERR_GENERAL;
}
if ( make_dotlock (lockhd, -1) )
{
/* This is something bad. Probably a stale lockfile. */
log_info ("can't lock `%s'\n", filename );
rc = G10ERR_GENERAL;
goto leave;
}
/* Now the real test while we are locked. */
if (!access(filename, F_OK))
{
rc = 0; /* Okay, we may access the file now. */
goto leave;
}
/* The file does not yet exist, create it now. */
oldmask = umask (077);
if (is_secured_filename (filename))
{
iobuf = NULL;
errno = EPERM;
}
else
iobuf = iobuf_create (filename);
umask (oldmask);
if (!iobuf)
{
log_error ( _("error creating keyring `%s': %s\n"),
filename, strerror(errno));
rc = G10ERR_OPEN_FILE;
goto leave;
}
if (!opt.quiet)
log_info (_("keyring `%s' created\n"), filename);
iobuf_close (iobuf);
/* Must invalidate that ugly cache */
iobuf_ioctl (NULL, 2, 0, filename);
rc = 0;
leave:
if (lockhd)
{
release_dotlock (lockhd);
destroy_dotlock (lockhd);
}
return rc;
}
/*
* Register a resource (which currently may only be a keyring file).
* The first keyring which is added by this function is
@ -78,14 +197,14 @@ static void unlock_all (KEYDB_HANDLE hd);
* Note: this function may be called before secure memory is
* available.
* Flag 1 == force
* Flag 2 == default
* Flag 2 == mark resource as primary
* Flag 4 == This is a default resources
*/
int
keydb_add_resource (const char *url, int flags, int secret)
{
static int any_secret, any_public;
const char *resname = url;
iobuf_t iobuf = NULL;
char *filename = NULL;
int force=(flags&1);
int rc = 0;
@ -104,7 +223,7 @@ keydb_add_resource (const char *url, int flags, int secret)
#if !defined(HAVE_DRIVE_LETTERS) && !defined(__riscos__)
else if (strchr (resname, ':')) {
log_error ("invalid key resource URL `%s'\n", url );
rc = GPG_ERR_GENERAL;
rc = G10ERR_GENERAL;
goto leave;
}
#endif /* !HAVE_DRIVE_LETTERS && !__riscos__ */
@ -146,65 +265,18 @@ keydb_add_resource (const char *url, int flags, int secret)
switch (rt) {
case KEYDB_RESOURCE_TYPE_NONE:
log_error ("unknown type of key resource `%s'\n", url );
rc = GPG_ERR_GENERAL;
rc = G10ERR_GENERAL;
goto leave;
case KEYDB_RESOURCE_TYPE_KEYRING:
if (access(filename, F_OK))
{ /* file does not exist */
mode_t oldmask;
char *last_slash_in_filename;
if (!force)
{
rc = gpg_error_from_errno (errno);
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 check again. */
static int tried;
if (!tried)
{
tried = 1;
try_make_homedir (filename);
}
if (access (filename, F_OK))
{
rc = gpg_error_from_errno (errno);
*last_slash_in_filename = DIRSEP_C;
goto leave;
}
}
*last_slash_in_filename = DIRSEP_C;
oldmask=umask(077);
iobuf = iobuf_create (filename);
umask(oldmask);
if (!iobuf)
{
log_error ( _("error creating keyring `%s': %s\n"),
filename, strerror(errno));
rc = gpg_error_from_errno (errno);
goto leave;
}
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 */
rc = maybe_create_keyring (filename, force);
if (rc)
goto leave;
if(keyring_register_filename (filename, secret, &token))
{
if (used_resources >= MAX_KEYDB_RESOURCES)
rc = GPG_ERR_RESOURCE_LIMIT;
rc = G10ERR_RESOURCE_LIMIT;
else
{
if(flags&2)
@ -228,7 +300,7 @@ keydb_add_resource (const char *url, int flags, int secret)
default:
log_error ("resource type of `%s' not supported\n", url);
rc = GPG_ERR_GENERAL;
rc = G10ERR_GENERAL;
goto leave;
}
@ -236,7 +308,18 @@ keydb_add_resource (const char *url, int flags, int secret)
leave:
if (rc)
log_error ("keyblock resource `%s': %s\n", filename, gpg_strerror (rc));
{
/* Secret keyrings are not required in all cases. To avoid
having gpg return failure we use log_info here if the
rewsource is a secret one and marked as default
resource. */
if ((flags&4) && secret)
log_info (_("keyblock resource `%s': %s\n"),
filename, g10_errstr(rc));
else
log_error (_("keyblock resource `%s': %s\n"),
filename, g10_errstr(rc));
}
else if (secret)
any_secret = 1;
else
@ -254,7 +337,7 @@ keydb_new (int secret)
KEYDB_HANDLE hd;
int i, j;
hd = xcalloc (1,sizeof *hd);
hd = xmalloc_clear (sizeof *hd);
hd->found = -1;
assert (used_resources <= MAX_KEYDB_RESOURCES);
@ -414,14 +497,14 @@ keydb_get_keyblock (KEYDB_HANDLE hd, KBNODE *ret_kb)
int rc = 0;
if (!hd)
return GPG_ERR_INV_ARG;
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 = GPG_ERR_GENERAL; /* oops */
rc = G10ERR_GENERAL; /* oops */
break;
case KEYDB_RESOURCE_TYPE_KEYRING:
rc = keyring_get_keyblock (hd->active[hd->found].u.kr, ret_kb);
@ -440,7 +523,7 @@ keydb_update_keyblock (KEYDB_HANDLE hd, KBNODE kb)
int rc = 0;
if (!hd)
return GPG_ERR_INV_ARG;
return G10ERR_INV_ARG;
if ( hd->found < 0 || hd->found >= hd->used)
return -1; /* nothing found */
@ -454,7 +537,7 @@ keydb_update_keyblock (KEYDB_HANDLE hd, KBNODE kb)
switch (hd->active[hd->found].type) {
case KEYDB_RESOURCE_TYPE_NONE:
rc = GPG_ERR_GENERAL; /* oops */
rc = G10ERR_GENERAL; /* oops */
break;
case KEYDB_RESOURCE_TYPE_KEYRING:
rc = keyring_update_keyblock (hd->active[hd->found].u.kr, kb);
@ -476,7 +559,7 @@ keydb_insert_keyblock (KEYDB_HANDLE hd, KBNODE kb)
int idx;
if (!hd)
return GPG_ERR_INV_ARG;
return G10ERR_INV_ARG;
if( opt.dry_run )
return 0;
@ -486,7 +569,7 @@ keydb_insert_keyblock (KEYDB_HANDLE hd, KBNODE kb)
else if ( hd->current >= 0 && hd->current < hd->used)
idx = hd->current;
else
return GPG_ERR_GENERAL;
return G10ERR_GENERAL;
rc = lock_all (hd);
if (rc)
@ -494,7 +577,7 @@ keydb_insert_keyblock (KEYDB_HANDLE hd, KBNODE kb)
switch (hd->active[idx].type) {
case KEYDB_RESOURCE_TYPE_NONE:
rc = GPG_ERR_GENERAL; /* oops */
rc = G10ERR_GENERAL; /* oops */
break;
case KEYDB_RESOURCE_TYPE_KEYRING:
rc = keyring_insert_keyblock (hd->active[idx].u.kr, kb);
@ -515,7 +598,7 @@ keydb_delete_keyblock (KEYDB_HANDLE hd)
int rc = -1;
if (!hd)
return GPG_ERR_INV_ARG;
return G10ERR_INV_ARG;
if ( hd->found < 0 || hd->found >= hd->used)
return -1; /* nothing found */
@ -529,7 +612,7 @@ keydb_delete_keyblock (KEYDB_HANDLE hd)
switch (hd->active[hd->found].type) {
case KEYDB_RESOURCE_TYPE_NONE:
rc = GPG_ERR_GENERAL; /* oops */
rc = G10ERR_GENERAL; /* oops */
break;
case KEYDB_RESOURCE_TYPE_KEYRING:
rc = keyring_delete_keyblock (hd->active[hd->found].u.kr);
@ -552,7 +635,7 @@ keydb_locate_writable (KEYDB_HANDLE hd, const char *reserved)
int rc;
if (!hd)
return GPG_ERR_INV_ARG;
return G10ERR_INV_ARG;
rc = keydb_search_reset (hd); /* this does reset hd->current */
if (rc)
@ -598,7 +681,7 @@ keydb_locate_writable (KEYDB_HANDLE hd, const char *reserved)
* Rebuild the caches of all key resources.
*/
void
keydb_rebuild_caches (void)
keydb_rebuild_caches (int noisy)
{
int i, rc;
@ -611,10 +694,10 @@ keydb_rebuild_caches (void)
case KEYDB_RESOURCE_TYPE_NONE: /* ignore */
break;
case KEYDB_RESOURCE_TYPE_KEYRING:
rc = keyring_rebuild_cache (all_resources[i].token);
rc = keyring_rebuild_cache (all_resources[i].token,noisy);
if (rc)
log_error (_("failed to rebuild keyring cache: %s\n"),
gpg_strerror (rc));
g10_errstr (rc));
break;
}
}
@ -631,7 +714,7 @@ keydb_search_reset (KEYDB_HANDLE hd)
int i, rc = 0;
if (!hd)
return GPG_ERR_INV_ARG;
return G10ERR_INV_ARG;
hd->current = 0;
hd->found = -1;
@ -660,7 +743,7 @@ keydb_search2 (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc,
int rc = -1;
if (!hd)
return GPG_ERR_INV_ARG;
return G10ERR_INV_ARG;
while (rc == -1 && hd->current >= 0 && hd->current < hd->used) {
switch (hd->active[hd->current].type) {

View File

@ -1,5 +1,6 @@
/* keydb.h - Key database
* Copyright (C) 1998, 1999, 2000, 2001, 2003 Free Software Foundation, Inc.
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
* 2006 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -15,14 +16,16 @@
*
* 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
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
#ifndef G10_KEYDB_H
#define G10_KEYDB_H
#include <assuan.h>
#include "types.h"
#include "global.h"
#include "packet.h"
#include "cipher.h"
@ -75,7 +78,7 @@ struct keyblock_pos_struct {
enum resource_type rt;
off_t offset; /* position information */
unsigned count; /* length of the keyblock in packets */
iobuf_t fp; /* used by enum_keyblocks */
iobuf_t fp; /* Used by enum_keyblocks. */
int secret; /* working on a secret keyring */
PACKET *pkt; /* ditto */
int valid;
@ -131,11 +134,11 @@ typedef enum {
struct keydb_search_desc {
KeydbSearchMode mode;
int (*skipfnc)(void *,u32*);
int (*skipfnc)(void *,u32*,PKT_user_id*);
void *skipfncvalue;
union {
const char *name;
char fpr[MAX_FINGERPRINT_LEN];
byte fpr[MAX_FINGERPRINT_LEN];
u32 kid[2];
} u;
int exact;
@ -156,7 +159,7 @@ 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);
void keydb_rebuild_caches (int noisy);
int keydb_search_reset (KEYDB_HANDLE hd);
#define keydb_search(a,b,c) keydb_search2((a),(b),(c),NULL)
int keydb_search2 (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc,
@ -183,14 +186,23 @@ int build_sk_list( STRLIST locusr, SK_LIST *ret_sk_list,
int unlock, unsigned use );
/*-- passphrase.h --*/
assuan_context_t agent_open (int try, const char *orig_codeset);
void agent_close (assuan_context_t ctx);
int have_static_passphrase(void);
void set_passphrase_from_string(const char *pass);
void read_passphrase_from_fd( int fd );
void passphrase_clear_cache ( u32 *keyid, int algo );
void passphrase_clear_cache ( u32 *keyid, const char *cacheid, int algo );
char *ask_passphrase (const char *description,
const char *tryagain_text,
const char *promptid,
const char *prompt,
const char *cacheid, int *canceled);
DEK *passphrase_to_dek( u32 *keyid, int pubkey_algo,
int cipher_algo, STRING2KEY *s2k, int mode,
const char *tryagain_text, int *canceled);
void set_next_passphrase( const char *s );
char *get_last_passphrase(void);
void next_to_last_passphrase(void);
/*-- getkey.c --*/
int classify_user_id( const char *name, KEYDB_SEARCH_DESC *desc);
@ -201,7 +213,7 @@ int get_pubkey_fast ( PKT_public_key *pk, u32 *keyid );
KBNODE get_pubkeyblock( u32 *keyid );
int get_pubkey_byname( PKT_public_key *pk, const char *name,
KBNODE *ret_keyblock, KEYDB_HANDLE *ret_kdbhd,
int include_disabled );
int include_unusable );
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 );
@ -219,27 +231,39 @@ int seckey_available( u32 *keyid );
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_next (GETKEY_CTX ctx, PKT_secret_key *sk, KBNODE *ret_keyblock);
void get_seckey_end( GETKEY_CTX ctx );
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 get_seckeyblock_byfprint (KBNODE *ret_keyblock, const byte *fprint,
size_t fprint_len );
int enum_secret_keys( void **context, PKT_secret_key *sk,
int with_subkeys, int with_spm );
void merge_keys_and_selfsig( KBNODE keyblock );
char*get_user_id_string( u32 *keyid );
char*get_user_id_string_printable( 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_printable( u32 *keyid );
char*get_user_id_native( u32 *keyid );
KEYDB_HANDLE get_ctx_handle(GETKEY_CTX ctx);
void release_akl(void);
int parse_auto_key_locate(char *options);
/*-- keyid.c --*/
int pubkey_letter( int algo );
u32 v3_keyid (gcry_mpi_t a, u32 *ki);
void hash_public_key( gcry_md_hd_t md, PKT_public_key *pk );
size_t keystrlen(void);
const char *keystr(u32 *keyid);
const char *keystr_from_pk(PKT_public_key *pk);
const char *keystr_from_sk(PKT_secret_key *sk);
const char *keystr_from_desc(KEYDB_SEARCH_DESC *desc);
u32 keyid_from_sk( PKT_secret_key *sk, u32 *keyid );
u32 keyid_from_pk( PKT_public_key *pk, u32 *keyid );
u32 keyid_from_sig( PKT_signature *sig, u32 *keyid );
u32 keyid_from_fingerprint( const byte *fprint, size_t fprint_len, u32 *keyid );
u32 keyid_from_fingerprint(const byte *fprint, size_t fprint_len, u32 *keyid);
byte *namehash_from_uid(PKT_user_id *uid);
unsigned nbits_from_pk( PKT_public_key *pk );
unsigned nbits_from_sk( PKT_secret_key *sk );
@ -249,20 +273,16 @@ 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 *revokestr_from_pk( PKT_public_key *pk );
const char *usagestr_from_pk( PKT_public_key *pk );
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 *serialno_and_fpr_from_sk (const unsigned char *sn, size_t snlen,
PKT_secret_key *sk);
/*-- kbnode.c --*/
KBNODE new_kbnode( PACKET *pkt );
KBNODE clone_kbnode( KBNODE node );

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,6 @@
/* keyid.c - key ID and fingerprint handling
* Copyright (C) 1998, 1999, 2000, 2001, 2003 Free Software Foundation, Inc.
* Copyright (C) 1998, 1999, 2000, 2001, 2003,
* 2004, 2006 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -15,7 +16,8 @@
*
* 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
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
#include <config.h>
@ -31,11 +33,9 @@
#include "main.h"
#include "packet.h"
#include "options.h"
#include "mpi.h"
#include "keydb.h"
#include "i18n.h"
int
pubkey_letter( int algo )
{
@ -50,66 +50,93 @@ pubkey_letter( int algo )
}
}
/* This function is useful for v4 fingerprints and v3 or v4 key
signing. */
void
hash_public_key( gcry_md_hd_t md, PKT_public_key *pk )
{
unsigned int n = 6;
unsigned int nb[PUBKEY_MAX_NPKEY];
unsigned int nn[PUBKEY_MAX_NPKEY];
byte *pp[PUBKEY_MAX_NPKEY];
int i;
size_t nbits, nbytes;
int npkey = pubkey_get_npkey (pk->pubkey_algo);
/* Two extra bytes for the expiration date in v3 */
if(pk->version<4)
n+=2;
if (npkey==0 && pk->pkey[0]
&& gcry_mpi_get_flag (pk->pkey[0], GCRYMPI_FLAG_OPAQUE))
{
pp[0] = gcry_mpi_get_opaque (pk->pkey[0], &nbits);
nn[0] = (nbits+7)/8;
n+=nn[0];
}
else
for(i=0; i < npkey; i++ )
{
nb[i] = gcry_mpi_get_nbits (pk->pkey[i]);
if (gcry_mpi_print (GCRYMPI_FMT_PGP, NULL, 0, &nbytes, pk->pkey[i]))
BUG ();
pp[i] = xmalloc (nbytes);
if (gcry_mpi_print (GCRYMPI_FMT_PGP, pp[i], nbytes,
&nbytes, pk->pkey[i]))
BUG ();
nn[i] = nbytes;
n += 2 + nn[i];
}
gcry_md_putc ( md, 0x99 ); /* ctb */
/* What does it mean if n is greater than than 0xFFFF ? */
gcry_md_putc ( md, n >> 8 ); /* 2 byte length header */
gcry_md_putc ( md, n );
gcry_md_putc ( md, pk->version );
gcry_md_putc ( md, pk->timestamp >> 24 );
gcry_md_putc ( md, pk->timestamp >> 16 );
gcry_md_putc ( md, pk->timestamp >> 8 );
gcry_md_putc ( md, pk->timestamp );
if(pk->version<4)
{
u16 days=0;
if(pk->expiredate)
days=(u16)((pk->expiredate - pk->timestamp) / 86400L);
gcry_md_putc ( md, days >> 8 );
gcry_md_putc ( md, days );
}
gcry_md_putc ( md, pk->pubkey_algo );
if(npkey==0 && pk->pkey[0]
&& gcry_mpi_get_flag (pk->pkey[0], GCRYMPI_FLAG_OPAQUE))
{
gcry_md_write (md, pp[0], nn[0]);
}
else
for(i=0; i < npkey; i++ )
{
gcry_md_putc ( md, nb[i]>>8);
gcry_md_putc ( md, nb[i] );
gcry_md_write ( md, pp[i], nn[i] );
xfree(pp[i]);
}
}
static gcry_md_hd_t
do_fingerprint_md( PKT_public_key *pk )
{
gcry_md_hd_t md;
unsigned int n;
unsigned int nn[PUBKEY_MAX_NPKEY];
byte *pp[PUBKEY_MAX_NPKEY];
int i;
int npkey = pubkey_get_npkey( pk->pubkey_algo );
gcry_md_hd_t md;
gcry_md_open (&md, pk->version < 4 ? DIGEST_ALGO_RMD160
: DIGEST_ALGO_SHA1, 0);
if (gcry_md_open (&md, DIGEST_ALGO_SHA1, 0))
BUG ();
hash_public_key(md,pk);
gcry_md_final( md );
n = pk->version < 4 ? 8 : 6;
for(i=0; i < npkey; i++ ) {
size_t nbytes;
if (gcry_mpi_print( GCRYMPI_FMT_PGP, NULL, 0, &nbytes, pk->pkey[i] ))
BUG ();
/* fixme: we should try to allocate a buffer on the stack */
pp[i] = xmalloc(nbytes);
if (gcry_mpi_print ( GCRYMPI_FMT_PGP, pp[i], nbytes, &nbytes,
pk->pkey[i] ))
BUG ();
nn[i] = nbytes;
n += nn[i];
}
gcry_md_putc ( md, 0x99 ); /* ctb */
gcry_md_putc ( md, n >> 8 ); /* 2 byte length header */
gcry_md_putc ( md, n );
if( pk->version < 4 )
gcry_md_putc ( md, 3 );
else
gcry_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 );
}
if( pk->version < 4 ) {
u16 a;
if( pk->expiredate )
a = (u16)((pk->expiredate - pk->timestamp) / 86400L);
else
a = 0;
gcry_md_putc ( md, a >> 8 );
gcry_md_putc ( md, a );
}
gcry_md_putc ( md, pk->pubkey_algo );
for(i=0; i < npkey; i++ ) {
gcry_md_write( md, pp[i], nn[i] );
xfree (pp[i]);
}
gcry_md_final ( md );
return md;
return md;
}
static gcry_md_hd_t
@ -119,13 +146,16 @@ do_fingerprint_md_sk( PKT_secret_key *sk )
int npkey = pubkey_get_npkey( sk->pubkey_algo ); /* npkey is correct! */
int i;
if(npkey==0)
return NULL;
pk.pubkey_algo = sk->pubkey_algo;
pk.version = sk->version;
pk.timestamp = sk->timestamp;
pk.expiredate = sk->expiredate;
pk.pubkey_algo = sk->pubkey_algo;
for( i=0; i < npkey; i++ )
pk.pkey[i] = sk->skey[i];
pk.pkey[i] = sk->skey[i];
return do_fingerprint_md( &pk );
}
@ -154,6 +184,112 @@ v3_keyid (gcry_mpi_t a, u32 *ki)
}
size_t
keystrlen(void)
{
switch(opt.keyid_format)
{
case KF_SHORT:
return 8;
case KF_LONG:
return 16;
case KF_0xSHORT:
return 10;
case KF_0xLONG:
return 18;
default:
BUG();
}
}
const char *
keystr(u32 *keyid)
{
static char keyid_str[19];
switch(opt.keyid_format)
{
case KF_SHORT:
sprintf(keyid_str,"%08lX",(ulong)keyid[1]);
break;
case KF_LONG:
if(keyid[0])
sprintf(keyid_str,"%08lX%08lX",(ulong)keyid[0],(ulong)keyid[1]);
else
sprintf(keyid_str,"%08lX",(ulong)keyid[1]);
break;
case KF_0xSHORT:
sprintf(keyid_str,"0x%08lX",(ulong)keyid[1]);
break;
case KF_0xLONG:
if(keyid[0])
sprintf(keyid_str,"0x%08lX%08lX",(ulong)keyid[0],(ulong)keyid[1]);
else
sprintf(keyid_str,"0x%08lX",(ulong)keyid[1]);
break;
default:
BUG();
}
return keyid_str;
}
const char *
keystr_from_pk(PKT_public_key *pk)
{
keyid_from_pk(pk,NULL);
return keystr(pk->keyid);
}
const char *
keystr_from_sk(PKT_secret_key *sk)
{
keyid_from_sk(sk,NULL);
return keystr(sk->keyid);
}
const char *
keystr_from_desc(KEYDB_SEARCH_DESC *desc)
{
switch(desc->mode)
{
case KEYDB_SEARCH_MODE_LONG_KID:
case KEYDB_SEARCH_MODE_SHORT_KID:
return keystr(desc->u.kid);
case KEYDB_SEARCH_MODE_FPR20:
{
u32 keyid[2];
keyid[0] = ((unsigned char)desc->u.fpr[12] << 24
| (unsigned char)desc->u.fpr[13] << 16
| (unsigned char)desc->u.fpr[14] << 8
| (unsigned char)desc->u.fpr[15]);
keyid[1] = ((unsigned char)desc->u.fpr[16] << 24
| (unsigned char)desc->u.fpr[17] << 16
| (unsigned char)desc->u.fpr[18] << 8
| (unsigned char)desc->u.fpr[19]);
return keystr(keyid);
}
case KEYDB_SEARCH_MODE_FPR16:
return "?v3 fpr?";
default:
BUG();
}
}
/****************
* Get the keyid from the secret key and put it into keyid
@ -162,29 +298,51 @@ v3_keyid (gcry_mpi_t a, u32 *ki)
u32
keyid_from_sk( PKT_secret_key *sk, u32 *keyid )
{
u32 lowbits;
u32 dummy_keyid[2];
u32 lowbits;
u32 dummy_keyid[2];
if( !keyid )
keyid = dummy_keyid;
if( !keyid )
keyid = dummy_keyid;
if( sk->version < 4 && is_RSA(sk->pubkey_algo) ) {
keyid[0] = keyid[1] = 0;
lowbits = pubkey_get_npkey(sk->pubkey_algo) ?
v3_keyid (sk->skey[0], keyid) : 0;
if( sk->keyid[0] || sk->keyid[1] )
{
keyid[0] = sk->keyid[0];
keyid[1] = sk->keyid[1];
lowbits = keyid[1];
}
else {
const byte *dp;
gcry_md_hd_t md;
md = do_fingerprint_md_sk(sk);
dp = gcry_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] ;
lowbits = keyid[1];
gcry_md_close (md);
else if( sk->version < 4 )
{
if( is_RSA(sk->pubkey_algo) )
{
lowbits = (pubkey_get_npkey (sk->pubkey_algo) ?
v3_keyid( sk->skey[0], keyid ) : 0); /* Take n. */
sk->keyid[0]=keyid[0];
sk->keyid[1]=keyid[1];
}
else
sk->keyid[0]=sk->keyid[1]=keyid[0]=keyid[1]=lowbits=0xFFFFFFFF;
}
else
{
const byte *dp;
gcry_md_hd_t md;
md = do_fingerprint_md_sk(sk);
if(md)
{
dp = gcry_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] ;
lowbits = keyid[1];
gcry_md_close (md);
sk->keyid[0] = keyid[0];
sk->keyid[1] = keyid[1];
}
else
sk->keyid[0]=sk->keyid[1]=keyid[0]=keyid[1]=lowbits=0xFFFFFFFF;
}
return lowbits;
return lowbits;
}
@ -195,38 +353,51 @@ 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];
u32 lowbits;
u32 dummy_keyid[2];
if( !keyid )
keyid = dummy_keyid;
if( !keyid )
keyid = dummy_keyid;
if( pk->keyid[0] || pk->keyid[1] ) {
keyid[0] = pk->keyid[0];
keyid[1] = pk->keyid[1];
lowbits = keyid[1];
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) ) {
keyid[0] = keyid[1] = 0;
lowbits = pubkey_get_npkey(pk->pubkey_algo) ?
v3_keyid (pk->pkey[0], keyid) : 0 ;
pk->keyid[0] = keyid[0];
pk->keyid[1] = keyid[1];
else if( pk->version < 4 )
{
if( is_RSA(pk->pubkey_algo) )
{
lowbits = (pubkey_get_npkey (pk->pubkey_algo) ?
v3_keyid ( pk->pkey[0], keyid ) : 0); /* From n. */
pk->keyid[0] = keyid[0];
pk->keyid[1] = keyid[1];
}
else
pk->keyid[0]=pk->keyid[1]=keyid[0]=keyid[1]=lowbits=0xFFFFFFFF;
}
else {
const byte *dp;
gcry_md_hd_t md;
md = do_fingerprint_md(pk);
dp = gcry_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] ;
lowbits = keyid[1];
gcry_md_close (md);
pk->keyid[0] = keyid[0];
pk->keyid[1] = keyid[1];
else
{
const byte *dp;
gcry_md_hd_t md;
md = do_fingerprint_md(pk);
if(md)
{
dp = gcry_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] ;
lowbits = keyid[1];
gcry_md_close (md);
pk->keyid[0] = keyid[0];
pk->keyid[1] = keyid[1];
}
else
pk->keyid[0]=pk->keyid[1]=keyid[0]=keyid[1]=lowbits=0xFFFFFFFF;
}
return lowbits;
return lowbits;
}
@ -282,16 +453,16 @@ namehash_from_uid(PKT_user_id *uid)
{
if(uid->namehash==NULL)
{
uid->namehash=xmalloc (20);
uid->namehash = xmalloc(20);
if(uid->attrib_data)
gcry_md_hash_buffer (GCRY_MD_RMD160, uid->namehash,
uid->attrib_data,uid->attrib_len);
gcry_md_hash_buffer (GCRY_MD_RMD160, uid->namehash,
uid->attrib_data, uid->attrib_len);
else
gcry_md_hash_buffer (GCRY_MD_RMD160, uid->namehash,
uid->name,uid->len);
uid->name, uid->len);
}
return uid->namehash;
}
@ -396,6 +567,46 @@ expirestr_from_sig( PKT_signature *sig )
return mk_datestr (buffer, atime);
}
const char *
revokestr_from_pk( PKT_public_key *pk )
{
static char buffer[11+5];
time_t atime;
if(!pk->revoked.date)
return _("never ");
atime=pk->revoked.date;
return mk_datestr (buffer, atime);
}
const char *
usagestr_from_pk( PKT_public_key *pk )
{
static char buffer[10];
int i = 0;
unsigned int use = pk->pubkey_usage;
if ( use & PUBKEY_USAGE_SIG )
buffer[i++] = 'S';
if ( use & PUBKEY_USAGE_CERT )
buffer[i++] = 'C';
if ( use & PUBKEY_USAGE_ENC )
buffer[i++] = 'E';
if ( (use & PUBKEY_USAGE_AUTH) )
buffer[i++] = 'A';
while (i < 4)
buffer[i++] = ' ';
buffer[i] = 0;
return buffer;
}
const char *
colon_strtime (u32 t)
{
@ -465,145 +676,143 @@ colon_expirestr_from_sig (PKT_signature *sig)
byte *
fingerprint_from_pk( PKT_public_key *pk, byte *array, size_t *ret_len )
{
byte *buf;
const byte *dp;
size_t len;
if( pk->version < 4 && is_RSA(pk->pubkey_algo) ) {
/* RSA in version 3 packets is special */
gcry_md_hd_t md;
gcry_md_open (&md, DIGEST_ALGO_MD5, 0);
if( pubkey_get_npkey( pk->pubkey_algo ) > 1 ) {
size_t nbytes;
if (gcry_mpi_print( GCRYMPI_FMT_USG, NULL, 0, &nbytes,
pk->pkey[0]))
BUG ();
/* fixme: allocate it on the stack */
buf = xmalloc(nbytes);
if (gcry_mpi_print (GCRYMPI_FMT_USG, buf, nbytes, NULL,pk->pkey[0]))
BUG ();
gcry_md_write (md, buf, nbytes);
xfree (buf);
if (gcry_mpi_print( GCRYMPI_FMT_USG, NULL, 0, &nbytes, pk->pkey[1]))
BUG ();
/* fixme: allocate it on the stack */
buf = xmalloc(nbytes);
if (gcry_mpi_print( GCRYMPI_FMT_USG, buf, nbytes, NULL,pk->pkey[1]))
BUG ();
gcry_md_write( md, buf, nbytes );
xfree(buf);
}
gcry_md_final (md);
if( !array )
array = xmalloc ( 16 );
len = 16;
memcpy(array, gcry_md_read (md, DIGEST_ALGO_MD5), 16 );
gcry_md_close (md);
byte *buf;
const byte *dp;
size_t len, nbytes;
int i;
if ( pk->version < 4 )
{
if ( is_RSA(pk->pubkey_algo) )
{
/* RSA in version 3 packets is special. */
gcry_md_hd_t md;
if (gcry_md_open (&md, DIGEST_ALGO_MD5, 0))
BUG ();
if ( pubkey_get_npkey (pk->pubkey_algo) > 1 )
{
for (i=0; i < 2; i++)
{
if (gcry_mpi_print (GCRYMPI_FMT_USG, NULL, 0,
&nbytes, pk->pkey[i]))
BUG ();
/* fixme: Better allocate BUF on the stack */
buf = xmalloc (nbytes);
if (gcry_mpi_print (GCRYMPI_FMT_USG, buf, nbytes,
NULL, pk->pkey[i]))
BUG ();
gcry_md_write (md, buf, nbytes);
xfree (buf);
}
}
gcry_md_final (md);
if (!array)
array = xmalloc (16);
len = 16;
memcpy (array, gcry_md_read (md, DIGEST_ALGO_MD5), 16);
gcry_md_close(md);
}
else
{
if (!array)
array = xmalloc(16);
len = 16;
memset (array,0,16);
}
}
else {
gcry_md_hd_t md;
md = do_fingerprint_md(pk);
dp = gcry_md_read ( md, 0 );
len = gcry_md_get_algo_dlen (gcry_md_get_algo (md));
assert( len <= MAX_FINGERPRINT_LEN );
if( !array )
array = xmalloc ( len );
memcpy(array, dp, len );
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] ;
gcry_md_close (md);
else
{
gcry_md_hd_t md;
md = do_fingerprint_md(pk);
dp = gcry_md_read( md, 0 );
len = gcry_md_get_algo_dlen (gcry_md_get_algo (md));
assert( len <= MAX_FINGERPRINT_LEN );
if (!array)
array = xmalloc ( len );
memcpy (array, dp, len );
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] ;
gcry_md_close( md);
}
*ret_len = len;
return array;
*ret_len = len;
return array;
}
byte *
fingerprint_from_sk( PKT_secret_key *sk, byte *array, size_t *ret_len )
{
byte *buf;
const char *dp;
size_t len;
if( sk->version < 4 && is_RSA(sk->pubkey_algo) ) {
/* RSA in version 3 packets is special */
gcry_md_hd_t md;
gcry_md_open (&md, DIGEST_ALGO_MD5, 0);
if( pubkey_get_npkey( sk->pubkey_algo ) > 1 ) {
size_t nbytes;
if (gcry_mpi_print( GCRYMPI_FMT_USG, NULL, 0, &nbytes, sk->skey[0]))
BUG ();
/* fixme: allocate it on the stack */
buf = xmalloc(nbytes);
if (gcry_mpi_print (GCRYMPI_FMT_USG, buf, nbytes, NULL,sk->skey[0]))
BUG ();
gcry_md_write (md, buf, nbytes);
xfree (buf);
if (gcry_mpi_print( GCRYMPI_FMT_USG, NULL, 0, &nbytes, sk->skey[1]))
BUG ();
/* fixme: allocate it on the stack */
buf = xmalloc(nbytes);
if (gcry_mpi_print( GCRYMPI_FMT_USG, buf,nbytes, NULL, sk->skey[1]))
BUG ();
gcry_md_write( md, buf, nbytes );
xfree(buf);
}
gcry_md_final (md);
if( !array )
array = xmalloc ( 16 );
len = 16;
memcpy(array, gcry_md_read (md, DIGEST_ALGO_MD5), 16 );
gcry_md_close (md);
}
else {
gcry_md_hd_t md;
md = do_fingerprint_md_sk(sk);
dp = gcry_md_read ( md, 0 );
len = gcry_md_get_algo_dlen (gcry_md_get_algo (md));
assert( len <= MAX_FINGERPRINT_LEN );
if( !array )
array = xmalloc ( len );
memcpy(array, dp, len );
gcry_md_close (md);
}
*ret_len = len;
return array;
}
/* Create a serialno/fpr string from the serial number and the secret
* key. caller must free the returned string. There is no error
* return. */
char *
serialno_and_fpr_from_sk (const unsigned char *sn, size_t snlen,
PKT_secret_key *sk)
{
unsigned char fpr[MAX_FINGERPRINT_LEN];
size_t fprlen;
char *buffer, *p;
byte *buf;
const char *dp;
size_t len, nbytes;
int i;
fingerprint_from_sk (sk, fpr, &fprlen);
buffer = p= xmalloc (snlen*2 + 1 + fprlen*2 + 1);
for (i=0; i < snlen; i++, p+=2)
sprintf (p, "%02X", sn[i]);
*p++ = '/';
for (i=0; i < fprlen; i++, p+=2)
sprintf (p, "%02X", fpr[i]);
*p = 0;
return buffer;
if (sk->version < 4)
{
if ( is_RSA(sk->pubkey_algo) )
{
/* RSA in version 3 packets is special. */
gcry_md_hd_t md;
if (gcry_md_open (&md, DIGEST_ALGO_MD5, 0))
BUG ();
if (pubkey_get_npkey( sk->pubkey_algo ) > 1)
{
for (i=0; i < 2; i++)
{
if (gcry_mpi_print (GCRYMPI_FMT_USG, NULL, 0,
&nbytes, sk->skey[i]))
BUG ();
/* fixme: Better allocate BUF on the stack */
buf = xmalloc (nbytes);
if (gcry_mpi_print (GCRYMPI_FMT_USG, buf, nbytes,
NULL, sk->skey[i]))
BUG ();
gcry_md_write (md, buf, nbytes);
xfree (buf);
}
}
gcry_md_final(md);
if (!array)
array = xmalloc (16);
len = 16;
memcpy (array, gcry_md_read (md, DIGEST_ALGO_MD5), 16);
gcry_md_close (md);
}
else
{
if (!array)
array = xmalloc (16);
len=16;
memset (array,0,16);
}
}
else
{
gcry_md_hd_t md;
md = do_fingerprint_md_sk(sk);
if (md)
{
dp = gcry_md_read ( md, 0 );
len = gcry_md_get_algo_dlen ( gcry_md_get_algo (md) );
assert ( len <= MAX_FINGERPRINT_LEN );
if (!array)
array = xmalloc( len );
memcpy (array, dp, len);
gcry_md_close (md);
}
else
{
len = MAX_FINGERPRINT_LEN;
if (!array)
array = xmalloc (len);
memset (array, 0, len);
}
}
*ret_len = len;
return array;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
/* keyring.c - keyring file handling
* Copyright (C) 2001, 2003 Free Software Foundation, Inc.
* Copyright (C) 2001, 2004 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -15,7 +15,8 @@
*
* 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
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
#include <config.h>
@ -73,7 +74,7 @@ struct keyring_handle {
int secret; /* this is for a secret keyring */
struct {
CONST_KR_NAME kr;
iobuf_t iobuf;
IOBUF iobuf;
int eof;
int error;
} current;
@ -102,7 +103,7 @@ new_offset_item (void)
{
struct off_item *k;
k = xcalloc (1,sizeof *k);
k = xmalloc_clear (sizeof *k);
return k;
}
@ -125,7 +126,7 @@ new_offset_hash_table (void)
{
struct off_item **tbl;
tbl = xcalloc (2048, sizeof *tbl);
tbl = xmalloc_clear (2048 * sizeof *tbl);
return tbl;
}
@ -214,6 +215,9 @@ keyring_register_filename (const char *fname, int secret, void **ptr)
}
}
if (secret)
register_secured_file (fname);
kr = xmalloc (sizeof *kr + strlen (fname));
strcpy (kr->fname, fname);
kr->secret = !!secret;
@ -255,7 +259,7 @@ keyring_new (void *token, int secret)
assert (resource && !resource->secret == !secret);
hd = xcalloc (1,sizeof *hd);
hd = xmalloc_clear (sizeof *hd);
hd->resource = resource;
hd->secret = !!secret;
active_handles++;
@ -304,7 +308,7 @@ keyring_lock (KEYRING_HANDLE hd, int yes)
kr->lockhd = create_dotlock( kr->fname );
if (!kr->lockhd) {
log_info ("can't allocate lock for `%s'\n", kr->fname );
rc = GPG_ERR_GENERAL;
rc = G10ERR_GENERAL;
}
}
}
@ -319,7 +323,7 @@ keyring_lock (KEYRING_HANDLE hd, int yes)
;
else if (make_dotlock (kr->lockhd, -1) ) {
log_info ("can't lock `%s'\n", kr->fname );
rc = GPG_ERR_GENERAL;
rc = G10ERR_GENERAL;
}
else
kr->is_locked = 1;
@ -356,7 +360,7 @@ keyring_get_keyblock (KEYRING_HANDLE hd, KBNODE *ret_kb)
PACKET *pkt;
int rc;
KBNODE keyblock = NULL, node, lastnode;
iobuf_t a;
IOBUF a;
int in_cert = 0;
int pk_no = 0;
int uid_no = 0;
@ -369,15 +373,16 @@ keyring_get_keyblock (KEYRING_HANDLE hd, KBNODE *ret_kb)
return -1; /* no successful search */
a = iobuf_open (hd->found.kr->fname);
if (!a) {
log_error ("can't open `%s'\n", hd->found.kr->fname);
return GPG_ERR_KEYRING_OPEN;
}
if (!a)
{
log_error(_("can't open `%s'\n"), hd->found.kr->fname);
return G10ERR_KEYRING_OPEN;
}
if (iobuf_seek (a, hd->found.offset) ) {
log_error ("can't seek `%s'\n", hd->found.kr->fname);
iobuf_close(a);
return GPG_ERR_KEYRING_OPEN;
return G10ERR_KEYRING_OPEN;
}
pkt = xmalloc (sizeof *pkt);
@ -387,15 +392,15 @@ keyring_get_keyblock (KEYRING_HANDLE hd, KBNODE *ret_kb)
save_mode = set_packet_list_mode(0);
while ((rc=parse_packet (a, pkt)) != -1) {
hd->found.n_packets++;
if (gpg_err_code (rc) == GPG_ERR_UNKNOWN_PACKET) {
if (rc == G10ERR_UNKNOWN_PACKET) {
free_packet (pkt);
init_packet (pkt);
continue;
}
if (rc) {
log_error ("keyring_get_keyblock: read error: %s\n",
gpg_strerror (rc) );
rc = GPG_ERR_INV_KEYRING;
g10_errstr(rc) );
rc = G10ERR_INV_KEYRING;
break;
}
if (pkt->pkttype == PKT_COMPRESSED) {
@ -478,7 +483,7 @@ keyring_get_keyblock (KEYRING_HANDLE hd, KBNODE *ret_kb)
/* Make sure that future search operations fail immediately when
* we know that we are working on a invalid keyring
*/
if (gpg_err_code (rc) == GPG_ERR_INV_KEYRING)
if (rc == G10ERR_INV_KEYRING)
hd->current.error = rc;
return rc;
@ -496,7 +501,7 @@ keyring_update_keyblock (KEYRING_HANDLE hd, KBNODE kb)
/* need to know the number of packets - do a dummy get_keyblock*/
rc = keyring_get_keyblock (hd, NULL);
if (rc) {
log_error ("re-reading keyblock failed: %s\n", gpg_strerror (rc));
log_error ("re-reading keyblock failed: %s\n", g10_errstr (rc));
return rc;
}
if (!hd->found.n_packets)
@ -540,7 +545,7 @@ keyring_insert_keyblock (KEYRING_HANDLE hd, KBNODE kb)
fname = hd->resource? hd->resource->fname:NULL;
if (!fname)
return GPG_ERR_GENERAL;
return G10ERR_GENERAL;
/* close this one otherwise we will lose the position for
* a next search. Fixme: it would be better to adjust the position
@ -572,7 +577,7 @@ keyring_delete_keyblock (KEYRING_HANDLE hd)
/* need to know the number of packets - do a dummy get_keyblock*/
rc = keyring_get_keyblock (hd, NULL);
if (rc) {
log_error ("re-reading keyblock failed: %s\n", gpg_strerror (rc));
log_error ("re-reading keyblock failed: %s\n", g10_errstr (rc));
return rc;
}
if (!hd->found.n_packets)
@ -629,7 +634,7 @@ prepare_search (KEYRING_HANDLE hd)
if (hd->current.kr && !hd->current.eof) {
if ( !hd->current.iobuf )
return GPG_ERR_GENERAL; /* position invalid after a modify */
return G10ERR_GENERAL; /* position invalid after a modify */
return 0; /* okay */
}
@ -654,11 +659,12 @@ prepare_search (KEYRING_HANDLE hd)
hd->current.eof = 0;
hd->current.iobuf = iobuf_open (hd->current.kr->fname);
if (!hd->current.iobuf) {
if (!hd->current.iobuf)
{
hd->current.error = gpg_error_from_errno (errno);
log_error ("can't open `%s'\n", hd->current.kr->fname );
log_error(_("can't open `%s'\n"), hd->current.kr->fname );
return hd->current.error;
}
}
return 0;
}
@ -776,7 +782,7 @@ prepare_word_match (const byte *name)
int c;
/* the original length is always enough for the pattern */
p = pattern = xmalloc (strlen(name)+1);
p = pattern = xmalloc(strlen(name)+1);
do {
/* skip leading delimiters */
while( *name && !word_match_chars[*name] )
@ -1071,7 +1077,7 @@ keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc,
goto found;
break;
default:
rc = GPG_ERR_INV_ARG;
rc = G10ERR_INV_ARG;
goto found;
}
}
@ -1085,7 +1091,7 @@ keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc,
for (n=any_skip?0:ndesc; n < ndesc; n++)
{
if (desc[n].skipfnc
&& desc[n].skipfnc (desc[n].skipfncvalue, aki))
&& desc[n].skipfnc (desc[n].skipfncvalue, aki, uid))
break;
}
if (n == ndesc)
@ -1141,7 +1147,7 @@ keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc,
static int
create_tmp_file (const char *template,
char **r_bakfname, char **r_tmpfname, iobuf_t *r_fp)
char **r_bakfname, char **r_tmpfname, IOBUF *r_fp)
{
char *bakfname, *tmpfname;
mode_t oldmask;
@ -1184,15 +1190,22 @@ create_tmp_file (const char *template,
/* Create the temp file with limited access */
oldmask=umask(077);
*r_fp = iobuf_create (tmpfname);
if (is_secured_filename (tmpfname))
{
*r_fp = NULL;
errno = EPERM;
}
else
*r_fp = iobuf_create (tmpfname);
umask(oldmask);
if (!*r_fp) {
int tmperr = gpg_error_from_errno (errno);
log_error ("can't create `%s': %s\n", tmpfname, strerror(errno) );
if (!*r_fp)
{
int rc = gpg_error_from_errno (errno);
log_error(_("can't create `%s': %s\n"), tmpfname, strerror(errno) );
xfree (tmpfname);
xfree (bakfname);
return tmperr;
}
return rc;
}
*r_bakfname = bakfname;
*r_tmpfname = tmpfname;
@ -1219,10 +1232,10 @@ rename_tmp_file (const char *bakfname, const char *tmpfname,
#endif
if (rename (fname, bakfname) )
{
int tmperr = gpg_error_from_errno (errno);
rc = gpg_error_from_errno (errno);
log_error ("renaming `%s' to `%s' failed: %s\n",
fname, bakfname, strerror(errno) );
return tmperr;
return rc;
}
}
@ -1230,11 +1243,14 @@ rename_tmp_file (const char *bakfname, const char *tmpfname,
#if defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__)
remove( fname );
#endif
if (secret)
unregister_secured_file (fname);
if (rename (tmpfname, fname) )
{
rc = gpg_error_from_errno (errno);
log_error ("renaming `%s' to `%s' failed: %s\n",
log_error (_("renaming `%s' to `%s' failed: %s\n"),
tmpfname, fname, strerror(errno) );
register_secured_file (fname);
if (secret)
{
log_info(_("WARNING: 2 files with confidential"
@ -1269,7 +1285,7 @@ rename_tmp_file (const char *bakfname, const char *tmpfname,
static int
write_keyblock (iobuf_t fp, KBNODE keyblock)
write_keyblock (IOBUF fp, KBNODE keyblock)
{
KBNODE kbctx = NULL, node;
int rc;
@ -1282,7 +1298,7 @@ write_keyblock (iobuf_t fp, KBNODE keyblock)
if ( (rc = build_packet (fp, node->pkt) ))
{
log_error ("build_packet(%d) failed: %s\n",
node->pkt->pkttype, gpg_strerror (rc) );
node->pkt->pkttype, g10_errstr(rc) );
return rc;
}
if (node->pkt->pkttype == PKT_SIGNATURE)
@ -1299,11 +1315,12 @@ write_keyblock (iobuf_t fp, KBNODE keyblock)
iobuf_put (fp, 0xb0); /* old style packet 12, 1 byte len*/
iobuf_put (fp, 2); /* 2 bytes */
iobuf_put (fp, 0); /* unused */
if (iobuf_put (fp, cacheval)) {
int tmperr = gpg_error_from_errno (errno);
log_error ("writing sigcache packet failed\n");
return tmperr;
}
if (iobuf_put (fp, cacheval))
{
rc = gpg_error_from_errno (errno);
log_error ("writing sigcache packet failed\n");
return rc;
}
}
}
return 0;
@ -1315,13 +1332,13 @@ write_keyblock (iobuf_t fp, KBNODE keyblock)
* This is only done for the public keyrings.
*/
int
keyring_rebuild_cache (void *token)
keyring_rebuild_cache (void *token,int noisy)
{
KEYRING_HANDLE hd;
KEYDB_SEARCH_DESC desc;
KBNODE keyblock = NULL, node;
const char *lastresname = NULL, *resname;
iobuf_t tmpfp = NULL;
IOBUF tmpfp = NULL;
char *tmpfilename = NULL;
char *bakfilename = NULL;
int rc;
@ -1361,8 +1378,8 @@ keyring_rebuild_cache (void *token)
if (rc)
goto leave;
lastresname = resname;
if (!opt.quiet)
log_info (_("checking keyring `%s'\n"), resname);
if (noisy && !opt.quiet)
log_info (_("caching keyring `%s'\n"), resname);
rc = create_tmp_file (resname, &bakfilename, &tmpfilename, &tmpfp);
if (rc)
goto leave;
@ -1372,7 +1389,7 @@ keyring_rebuild_cache (void *token)
rc = keyring_get_keyblock (hd, &keyblock);
if (rc)
{
log_error ("keyring_get_keyblock failed: %s\n", gpg_strerror (rc));
log_error ("keyring_get_keyblock failed: %s\n", g10_errstr(rc));
goto leave;
}
assert (keyblock->pkt->pkttype == PKT_PUBLIC_KEY);
@ -1380,16 +1397,24 @@ keyring_rebuild_cache (void *token)
/* check all signature to set the signature's cache flags */
for (node=keyblock; node; node=node->next)
{
/* Note that this doesn't cache the result of a revocation
issued by a designated revoker. This is because the pk
in question does not carry the revkeys as we haven't
merged the key and selfsigs. It is questionable whether
this matters very much since there are very very few
designated revoker revocation packets out there. */
if (node->pkt->pkttype == PKT_SIGNATURE)
{
/* Note that this doesn't cache the result of a
revocation issued by a designated revoker. This is
because the pk in question does not carry the revkeys
as we haven't merged the key and selfsigs. It is
questionable whether this matters very much since
there are very very few designated revoker revocation
packets out there. */
check_key_signature (keyblock, node, NULL);
PKT_signature *sig=node->pkt->pkt.signature;
if(!opt.no_sig_cache && sig->flags.checked && sig->flags.valid
&& (openpgp_md_test_algo(sig->digest_algo)
|| openpgp_pk_test_algo(sig->pubkey_algo)))
sig->flags.checked=sig->flags.valid=0;
else
check_key_signature (keyblock, node, NULL);
sigcount++;
}
}
@ -1399,8 +1424,8 @@ keyring_rebuild_cache (void *token)
if (rc)
goto leave;
if ( !(++count % 50) && !opt.quiet)
log_info(_("%lu keys checked so far (%lu signatures)\n"),
if ( !(++count % 50) && noisy && !opt.quiet)
log_info(_("%lu keys cached so far (%lu signatures)\n"),
count, sigcount );
} /* end main loop */
@ -1408,10 +1433,11 @@ keyring_rebuild_cache (void *token)
rc = 0;
if (rc)
{
log_error ("keyring_search failed: %s\n", gpg_strerror (rc));
log_error ("keyring_search failed: %s\n", g10_errstr(rc));
goto leave;
}
log_info(_("%lu keys checked (%lu signatures)\n"), count, sigcount );
if(noisy || opt.verbose)
log_info(_("%lu keys cached (%lu signatures)\n"), count, sigcount );
if (tmpfp)
{
if (iobuf_close (tmpfp))
@ -1452,17 +1478,16 @@ static int
do_copy (int mode, const char *fname, KBNODE root, int secret,
off_t start_offset, unsigned int n_packets )
{
iobuf_t fp, newfp;
IOBUF fp, newfp;
int rc=0;
char *bakfname = NULL;
char *tmpfname = NULL;
/* Open the source file. Because we do a rname, we have to check the
/* Open the source file. Because we do a rename, we have to check the
permissions of the file */
if (access (fname, W_OK))
return gpg_error_from_errno (errno);
fp = iobuf_open (fname);
if (mode == 1 && !fp && errno == ENOENT) {
/* insert mode but file does not exist: create a new file */
@ -1470,14 +1495,19 @@ do_copy (int mode, const char *fname, KBNODE root, int secret,
mode_t oldmask;
oldmask=umask(077);
newfp = iobuf_create (fname);
if (!secret && is_secured_filename (fname)) {
newfp = NULL;
errno = EPERM;
}
else
newfp = iobuf_create (fname);
umask(oldmask);
if( !newfp ) {
int tmperr = gpg_error_from_errno (errno);
log_error (_("%s: can't create: %s\n"),
fname, strerror(errno));
return tmperr;
}
if( !newfp )
{
rc = gpg_error_from_errno (errno);
log_error (_("can't create `%s': %s\n"), fname, strerror(errno));
return rc;
}
if( !opt.quiet )
log_info(_("%s: keyring created\n"), fname );
@ -1485,38 +1515,44 @@ do_copy (int mode, const char *fname, KBNODE root, int secret,
while ( (node = walk_kbnode( root, &kbctx, 0 )) ) {
if( (rc = build_packet( newfp, node->pkt )) ) {
log_error("build_packet(%d) failed: %s\n",
node->pkt->pkttype, gpg_strerror (rc) );
node->pkt->pkttype, g10_errstr(rc) );
iobuf_cancel(newfp);
return rc;
}
}
if (iobuf_close(newfp)) {
int tmperr = gpg_error_from_errno (errno);
if( iobuf_close(newfp) ) {
rc = gpg_error_from_errno (errno);
log_error ("%s: close failed: %s\n", fname, strerror(errno));
return tmperr;
return rc;
}
return 0; /* ready */
}
if( !fp ) {
if( !fp )
{
rc = gpg_error_from_errno (errno);
log_error ("%s: can't open: %s\n", fname, strerror(errno) );
log_error(_("can't open `%s': %s\n"), fname, strerror(errno) );
goto leave;
}
}
/* create the new file */
/* Create the new file. */
rc = create_tmp_file (fname, &bakfname, &tmpfname, &newfp);
if (rc) {
iobuf_close(fp);
goto leave;
}
if (secret)
register_secured_file (tmpfname);
if( mode == 1 ) { /* insert */
/* copy everything to the new file */
rc = copy_all_packets (fp, newfp);
if( rc != -1 ) {
log_error("%s: copy to `%s' failed: %s\n",
fname, tmpfname, gpg_strerror (rc) );
fname, tmpfname, g10_errstr(rc) );
iobuf_close(fp);
if (secret)
unregister_secured_file (tmpfname);
iobuf_cancel(newfp);
goto leave;
}
@ -1528,8 +1564,10 @@ do_copy (int mode, const char *fname, KBNODE root, int secret,
rc = copy_some_packets( fp, newfp, start_offset );
if( rc ) { /* should never get EOF here */
log_error ("%s: copy to `%s' failed: %s\n",
fname, tmpfname, gpg_strerror (rc) );
fname, tmpfname, g10_errstr(rc) );
iobuf_close(fp);
if (secret)
unregister_secured_file (tmpfname);
iobuf_cancel(newfp);
goto leave;
}
@ -1538,8 +1576,10 @@ do_copy (int mode, const char *fname, KBNODE root, int secret,
rc = skip_some_packets( fp, n_packets );
if( rc ) {
log_error("%s: skipping %u packets failed: %s\n",
fname, n_packets, gpg_strerror (rc));
fname, n_packets, g10_errstr(rc));
iobuf_close(fp);
if (secret)
unregister_secured_file (tmpfname);
iobuf_cancel(newfp);
goto leave;
}
@ -1549,6 +1589,8 @@ do_copy (int mode, const char *fname, KBNODE root, int secret,
rc = write_keyblock (newfp, root);
if (rc) {
iobuf_close(fp);
if (secret)
unregister_secured_file (tmpfname);
iobuf_cancel(newfp);
goto leave;
}
@ -1559,8 +1601,10 @@ do_copy (int mode, const char *fname, KBNODE root, int secret,
rc = copy_all_packets( fp, newfp );
if( rc != -1 ) {
log_error("%s: copy to `%s' failed: %s\n",
fname, tmpfname, gpg_strerror (rc) );
fname, tmpfname, g10_errstr(rc) );
iobuf_close(fp);
if (secret)
unregister_secured_file (tmpfname);
iobuf_cancel(newfp);
goto leave;
}
@ -1582,7 +1626,7 @@ do_copy (int mode, const char *fname, KBNODE root, int secret,
rc = rename_tmp_file (bakfname, tmpfname, fname, secret);
leave:
xfree (bakfname);
xfree (tmpfname);
xfree(bakfname);
xfree(tmpfname);
return rc;
}

View File

@ -15,14 +15,13 @@
*
* 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
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
#ifndef GPG_KEYRING_H
#define GPG_KEYRING_H 1
#include "global.h"
typedef struct keyring_handle *KEYRING_HANDLE;
@ -41,6 +40,6 @@ 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, size_t *descindex);
int keyring_rebuild_cache (void *);
int keyring_rebuild_cache (void *token,int noisy);
#endif /*GPG_KEYRING_H*/

View File

@ -1,4 +1,23 @@
/* Keyserver internals */
/* keyserver-internal.h - Keyserver internals
* Copyright (C) 2001, 2002, 2004, 2005, 2006 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
#ifndef _KEYSERVER_INTERNAL_H_
#define _KEYSERVER_INTERNAL_H_
@ -8,14 +27,28 @@
#include "../common/iobuf.h"
#include "types.h"
void parse_keyserver_options(char *options);
int parse_keyserver_uri(char *uri,
const char *configname,unsigned int configlineno);
int parse_keyserver_options(char *options);
void free_keyserver_spec(struct keyserver_spec *keyserver);
struct keyserver_spec *keyserver_match(struct keyserver_spec *spec);
struct keyserver_spec *parse_keyserver_uri(const char *string,
int require_scheme,
const char *configname,
unsigned int configlineno);
struct keyserver_spec *parse_preferred_keyserver(PKT_signature *sig);
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_import_fprint(const byte *fprint,size_t fprint_len,
struct keyserver_spec *keyserver);
int keyserver_import_keyid(u32 *keyid,struct keyserver_spec *keyserver);
int keyserver_refresh(STRLIST users);
int keyserver_search(STRLIST tokens);
int keyserver_fetch(STRLIST urilist);
int keyserver_import_cert(const char *name,
unsigned char **fpr,size_t *fpr_len);
int keyserver_import_pka(const char *name,unsigned char **fpr,size_t *fpr_len);
int keyserver_import_name(const char *name,unsigned char **fpr,size_t *fpr_len,
struct keyserver_spec *keyserver);
int keyserver_import_ldap(const char *name,
unsigned char **fpr,size_t *fpr_len);
#endif /* !_KEYSERVER_INTERNAL_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,6 @@
/* main.h
* Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
* 2006 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -15,28 +16,36 @@
*
* 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
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
#ifndef G10_MAIN_H
#define G10_MAIN_H
#include "types.h"
#include "gpg.h"
#include "../common/iobuf.h"
#include "mpi.h"
#include "cipher.h"
#include "keydb.h"
/* It could be argued that the default cipher should be 3DES rather
than CAST5, and the default compression should be 0
(i.e. uncompressed) rather than 1 (zip). */
#define DEFAULT_CIPHER_ALGO CIPHER_ALGO_CAST5
#define DEFAULT_DIGEST_ALGO DIGEST_ALGO_SHA1
#define DEFAULT_COMPRESS_ALGO 1
(i.e. uncompressed) rather than 1 (zip). However, the real world
issues of speed and size come into play here. */
typedef struct {
int header_okay;
PK_LIST pk_list;
cipher_filter_context_t cfx;
#define DEFAULT_CIPHER_ALGO CIPHER_ALGO_CAST5
#define DEFAULT_DIGEST_ALGO DIGEST_ALGO_SHA1
#define DEFAULT_COMPRESS_ALGO COMPRESS_ALGO_ZIP
#define DEFAULT_S2K_DIGEST_ALGO DIGEST_ALGO_SHA1
#define S2K_DIGEST_ALGO (opt.s2k_digest_algo?opt.s2k_digest_algo:DEFAULT_S2K_DIGEST_ALGO)
typedef struct
{
int header_okay;
PK_LIST pk_list;
DEK *symkey_dek;
STRING2KEY *symkey_s2k;
cipher_filter_context_t cfx;
} encrypt_filter_context_t;
struct groupitem
@ -46,7 +55,7 @@ struct groupitem
struct groupitem *next;
};
/*-- g10.c --*/
/*-- gpg.c --*/
extern int g10_errors_seen;
#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5 )
@ -64,18 +73,19 @@ char *make_radix64_string( const byte *data, size_t len );
/*-- misc.c --*/
void trap_unaligned(void);
int disable_core_dumps(void);
void register_secured_file (const char *fname);
void unregister_secured_file (const char *fname);
int is_secured_file (int fd);
int is_secured_filename (const char *fname);
u16 checksum_u16( unsigned n );
u16 checksum( byte *p, unsigned n );
u16 checksum_mpi( gcry_mpi_t a );
u32 buffer_to_u32( const byte *buffer );
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_test_algo( int algo );
int openpgp_pk_algo_usage ( int algo );
int openpgp_md_test_algo( int algo );
int openpgp_md_map_name (const char *string);
int openpgp_cipher_map_name (const char *string);
int openpgp_pk_map_name (const char *string);
#ifdef USE_IDEA
void idea_cipher_warn( int show );
@ -91,9 +101,10 @@ struct expando_args
};
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);
void deprecated_command (const char *name);
const char *compress_algo_to_string(int algo);
int string_to_compress_algo(const char *string);
int check_compress_algo(int algo);
@ -106,10 +117,19 @@ struct parse_options
{
char *name;
unsigned int bit;
char **value;
char *help;
};
int parse_options(char *str,unsigned int *options,struct parse_options *opts);
char *optsep(char **stringp);
char *argsplit(char *string);
int parse_options(char *str,unsigned int *options,
struct parse_options *opts,int noisy);
char *unescape_percent_string (const unsigned char *s);
int has_invalid_email_chars (const char *s);
int is_valid_mailbox (const char *name);
const char *get_libexecdir (void);
int path_access(const char *file,int mode);
/* Temporary helpers. */
int pubkey_get_npkey( int algo );
@ -117,31 +137,24 @@ int pubkey_get_nskey( int algo );
int pubkey_get_nsig( int algo );
int pubkey_get_nenc( int algo );
unsigned int pubkey_nbits( int algo, gcry_mpi_t *pkey );
/* MPI helpers. */
int mpi_write( iobuf_t out, gcry_mpi_t a );
int mpi_write_opaque( iobuf_t out, gcry_mpi_t a );
gcry_mpi_t mpi_read(iobuf_t inp, unsigned int *ret_nread, int secure );
gcry_mpi_t mpi_read_opaque(iobuf_t inp, unsigned int *ret_nread );
int mpi_print( FILE *fp, gcry_mpi_t a, int mode );
/*-- helptext.c --*/
void display_online_help( const char *keyword );
/*-- encode.c --*/
int setup_symkey(STRING2KEY **symkey_s2k,DEK **symkey_dek);
int encode_symmetric( const char *filename );
int encode_store( const char *filename );
int encode_crypt( const char *filename, STRLIST remusr );
int encode_crypt( const char *filename, STRLIST remusr, int use_symkey );
void encode_crypt_files(int nfiles, char **files, STRLIST remusr);
int encrypt_filter( void *opaque, int control,
iobuf_t a, byte *buf, size_t *ret_len);
/*-- sign.c --*/
int complete_sig( PKT_signature *sig, PKT_secret_key *sk, MD_HANDLE md );
int complete_sig( PKT_signature *sig, PKT_secret_key *sk, gcry_md_hd_t 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 );
@ -149,31 +162,43 @@ int sign_symencrypt_file (const char *fname, STRLIST locusr);
/*-- sig-check.c --*/
int check_revocation_keys (PKT_public_key *pk, PKT_signature *sig);
int check_backsig(PKT_public_key *main_pk,PKT_public_key *sub_pk,
PKT_signature *backsig);
int check_key_signature( KBNODE root, KBNODE node, int *is_selfsig );
int check_key_signature2( KBNODE root, KBNODE node, PKT_public_key *check_pk,
PKT_public_key *ret_pk, int *is_selfsig,
u32 *r_expiredate, int *r_expired );
PKT_public_key *ret_pk, int *is_selfsig,
u32 *r_expiredate, int *r_expired );
/*-- delkey.c --*/
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 );
void keyedit_menu( const char *username, STRLIST locusr,
STRLIST commands, int quiet, int seckey_check );
void show_basic_key_info (KBNODE keyblock);
/*-- keygen.c --*/
u32 ask_expire_interval(int object);
u32 parse_expire_string(const char *string);
u32 ask_expire_interval(int object,const char *def_expire);
u32 ask_expiredate(void);
void generate_keypair( const char *fname, const char *card_serialno );
void generate_keypair( const char *fname, const char *card_serialno,
const char *backup_encryption_dir );
int keygen_set_std_prefs (const char *string,int personal);
PKT_user_id *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_keyserver_url(PKT_signature *sig, void *opaque);
int keygen_add_notations(PKT_signature *sig,void *opaque);
int keygen_add_revkey(PKT_signature *sig, void *opaque);
int make_backsig(PKT_signature *sig,PKT_public_key *pk,
PKT_public_key *sub_pk,PKT_secret_key *sub_sk);
int generate_subkeypair( KBNODE pub_keyblock, KBNODE sec_keyblock );
#ifdef ENABLE_CARD_SUPPORT
int generate_card_subkeypair (KBNODE pub_keyblock, KBNODE sec_keyblock,
int keyno, const char *serialno);
int save_unprotected_key_to_card (PKT_secret_key *sk, int keyno);
#endif
/*-- openfile.c --*/
int overwrite_filep( const char *fname );
@ -185,29 +210,29 @@ void try_make_homedir( const char *fname );
/*-- seskey.c --*/
void make_session_key( DEK *dek );
gcry_mpi_t encode_session_key( DEK *dek, unsigned int nbits);
gcry_mpi_t 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, gcry_mpi_t a );
gcry_mpi_t encode_session_key( DEK *dek, unsigned nbits );
gcry_mpi_t encode_md_value( PKT_public_key *pk, PKT_secret_key *sk,
gcry_md_hd_t md, int hash_algo );
/*-- import.c --*/
int parse_import_options(char *str,unsigned int *options);
int parse_import_options(char *str,unsigned int *options,int noisy);
void import_keys( char **fnames, int nnames,
void *stats_hd, unsigned int options );
int import_keys_stream( iobuf_t inp,
void *stats_hd, unsigned int options );
int import_keys_stream( iobuf_t inp,void *stats_hd,unsigned char **fpr,
size_t *fpr_len,unsigned int options );
void *import_new_stats_handle (void);
void import_release_stats_handle (void *p);
void import_print_stats (void *hd);
int collapse_uids( KBNODE *keyblock );
int auto_create_card_key_stub ( const char *serialnostr,
const unsigned char *fpr1,
const unsigned char *fpr2,
const unsigned char *fpr3);
/*-- export.c --*/
int parse_export_options(char *str,unsigned int *options);
int parse_export_options(char *str,unsigned int *options,int noisy);
int export_pubkeys( STRLIST users, unsigned int options );
int export_pubkeys_stream( iobuf_t out, STRLIST users,
KBNODE *keyblock_out, unsigned int options );
@ -221,7 +246,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 gen_desig_revoke( const char *uname, STRLIST locusr);
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 );
@ -230,17 +255,20 @@ 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 print_subpackets_colon(PKT_signature *sig);
void reorder_keyblock (KBNODE keyblock);
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 print_revokers(PKT_public_key *pk);
void show_policy_url(PKT_signature *sig,int indent,int mode);
void show_keyserver_url(PKT_signature *sig,int indent,int mode);
void show_notation(PKT_signature *sig,int indent,int mode);
void show_notation(PKT_signature *sig,int indent,int mode,int which);
void dump_attribs(const PKT_user_id *uid,
PKT_public_key *pk,PKT_secret_key *sk);
void set_attrib_fd(int fd);
void print_seckey_info (PKT_secret_key *sk);
void print_pubkey_info (FILE *fp, PKT_public_key *pk);
void print_card_key_info (FILE *fp, KBNODE keyblock);
/*-- verify.c --*/
void print_file_status( int status, const char *name, int what );
@ -249,24 +277,26 @@ int verify_files( int nfiles, char **files );
/*-- decrypt.c --*/
int decrypt_message( const char *filename );
void decrypt_messages(int nfiles, char **files);
void decrypt_messages(int nfiles, char *files[]);
/*-- plaintext.c --*/
int hash_datafiles( MD_HANDLE md, MD_HANDLE md2,
int hash_datafiles( gcry_md_hd_t md, gcry_md_hd_t md2,
STRLIST files, const char *sigfilename, int textmode );
/*-- pipemode.c --*/
void run_in_pipemode (void);
/*-- card-util.c --*/
void change_pin (int no, int allow_admin);
void card_status (FILE *fp, char *serialnobuf, size_t serialnobuflen);
void card_edit (STRLIST commands);
/*-- signal.c --*/
void init_signals(void);
void pause_on_sigusr( int which );
void block_all_signals(void);
void unblock_all_signals(void);
#ifdef ENABLE_CARD_SUPPORT
/*-- card-util.c --*/
void change_pin (int no, int allow_admin);
void card_status (FILE *fp, char *serialno, size_t serialnobuflen);
void card_edit (STRLIST commands);
int card_generate_subkey (KBNODE pub_keyblock, KBNODE sec_keyblock);
int card_store_subkey (KBNODE node, int use);
#endif
#endif /*G10_MAIN_H*/

File diff suppressed because it is too large Load Diff

View File

@ -15,7 +15,8 @@
*
* 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
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
#include <config.h>
@ -25,9 +26,9 @@
#include <errno.h>
#include <assert.h>
#include "gpg.h"
#include "errors.h"
#include "iobuf.h"
#include "memory.h"
#include "util.h"
#include "filter.h"
@ -38,7 +39,7 @@
*/
int
md_filter( void *opaque, int control,
iobuf_t a, byte *buf, size_t *ret_len)
IOBUF a, byte *buf, size_t *ret_len)
{
size_t size = *ret_len;
md_filter_context_t *mfx = opaque;
@ -67,8 +68,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);
gcry_md_close(mfx->md);
gcry_md_close(mfx->md2);
mfx->md = NULL;
mfx->md2 = NULL;
mfx->maxbuf_size = 0;

1045
g10/misc.c

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,6 @@
/* openfile.c
* Copyright (C) 1998, 1999, 2000, 2001, 2003 Free Software Foundation, Inc.
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004,
* 2005 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -15,7 +16,8 @@
*
* 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
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
#include <config.h>
@ -31,7 +33,6 @@
#include "gpg.h"
#include "util.h"
#include "memory.h"
#include "ttyio.h"
#include "options.h"
#include "main.h"
@ -66,8 +67,8 @@
int
overwrite_filep( const char *fname )
{
if( !fname || (*fname == '-' && !fname[1]) )
return 1; /* writing to stdout is always okay */
if( iobuf_is_pipe_filename (fname) )
return 1; /* Writing to stdout is always okay */
if( access( fname, F_OK ) )
return 1; /* does not exist */
@ -84,8 +85,10 @@ overwrite_filep( const char *fname )
return 0; /* do not overwrite */
tty_printf(_("File `%s' exists. "), fname);
if( cpr_enabled () )
tty_printf ("\n");
if( cpr_get_answer_is_yes("openfile.overwrite.okay",
_("Overwrite (y/N)? ")) )
_("Overwrite? (y/N) ")) )
return 1;
return 0;
}
@ -100,20 +103,20 @@ make_outfile_name( const char *iname )
{
size_t n;
if( (!iname || (*iname=='-' && !iname[1]) ))
return xstrdup ("-");
if ( iobuf_is_pipe_filename (iname) )
return xstrdup("-");
n = strlen(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 = xstrdup ( iname );
char *buf = xstrdup( iname );
buf[n-4] = 0;
return buf;
}
else if( n > 5 && !CMP_FILENAME(iname+n-5, EXTSEP_S "sign") ) {
char *buf = xstrdup ( iname );
char *buf = xstrdup( iname );
buf[n-5] = 0;
return buf;
}
@ -144,19 +147,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 = xmalloc (n);
prompt = xmalloc(n);
if( defname )
sprintf(prompt, "%s [%s]: ", s, defname );
else
sprintf(prompt, "%s: ", s );
tty_enable_completion(NULL);
fname = cpr_get("openfile.askoutname", prompt );
cpr_kill_prompt();
xfree (prompt);
tty_disable_completion();
xfree(prompt);
if( !*fname ) {
xfree ( fname ); fname = NULL;
xfree( fname ); fname = NULL;
fname = defname; defname = NULL;
}
xfree (defname);
xfree(defname);
if (fname)
trim_spaces (fname);
return fname;
@ -165,21 +170,22 @@ ask_outfile_name( const char *name, size_t namelen )
/****************
* Make an output filename for the inputfile INAME.
* Returns an iobuf_t and an errorcode
* Returns an IOBUF and an errorcode
* Mode 0 = use ".gpg"
* 1 = use ".asc"
* 2 = use ".sig"
*/
int
open_outfile( const char *iname, int mode, iobuf_t *a )
open_outfile( const char *iname, int mode, IOBUF *a )
{
int rc = 0;
*a = NULL;
if( (!iname || (*iname=='-' && !iname[1])) && !opt.outfile ) {
if( !(*a = iobuf_create(NULL)) ) {
if( iobuf_is_pipe_filename (iname) && !opt.outfile ) {
*a = iobuf_create(NULL);
if( !*a ) {
rc = gpg_error_from_errno (errno);
log_error(_("%s: can't open: %s\n"), "[stdout]", strerror(errno) );
log_error(_("can't open `%s': %s\n"), "[stdout]", strerror(errno) );
}
else if( opt.verbose )
log_info(_("writing to stdout\n"));
@ -207,7 +213,7 @@ open_outfile( const char *iname, int mode, iobuf_t *a )
const char *newsfx = mode==1 ? ".asc" :
mode==2 ? ".sig" : ".gpg";
buf = xmalloc (strlen(iname)+4+1);
buf = xmalloc(strlen(iname)+4+1);
strcpy(buf,iname);
dot = strchr(buf, '.' );
if ( dot && dot > buf && dot[1] && strlen(dot) <= 4
@ -223,7 +229,7 @@ open_outfile( const char *iname, int mode, iobuf_t *a )
if (!buf)
#endif /* USE_ONLY_8DOT3 */
{
buf = xmalloc (strlen(iname)+4+1);
buf = xmalloc(strlen(iname)+4+1);
strcpy(stpcpy(buf,iname), mode==1 ? EXTSEP_S "asc" :
mode==2 ? EXTSEP_S "sig" : EXTSEP_S "gpg");
}
@ -237,7 +243,7 @@ open_outfile( const char *iname, int mode, iobuf_t *a )
if ( !tmp || !*tmp )
{
xfree (tmp);
rc = GPG_ERR_EEXIST;
rc = gpg_error (GPG_ERR_EEXIST);
break;
}
xfree (buf);
@ -246,17 +252,27 @@ open_outfile( const char *iname, int mode, iobuf_t *a )
if( !rc )
{
if( !(*a = iobuf_create( name )) )
if (is_secured_filename (name) )
{
*a = NULL;
errno = EPERM;
}
else
*a = iobuf_create( name );
if( !*a )
{
rc = gpg_error_from_errno (errno);
log_error(_("%s: can't create: %s\n"), name, strerror(errno) );
log_error(_("can't create `%s': %s\n"), name, strerror(errno) );
}
else if( opt.verbose )
log_info(_("writing to `%s'\n"), name );
}
xfree (buf);
xfree(buf);
}
if (*a)
iobuf_ioctl (*a,3,1,NULL); /* disable fd caching */
return rc;
}
@ -265,26 +281,32 @@ open_outfile( const char *iname, int mode, iobuf_t *a )
* Try to open a file without the extension ".sig" or ".asc"
* Return NULL if such a file is not available.
*/
iobuf_t
IOBUF
open_sigfile( const char *iname, progress_filter_context_t *pfx )
{
iobuf_t a = NULL;
IOBUF a = NULL;
size_t len;
if( iname && !(*iname == '-' && !iname[1]) ) {
if( !iobuf_is_pipe_filename (iname) ) {
len = strlen(iname);
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 = xstrdup (iname);
buf = xstrdup(iname);
buf[len-(buf[len-1]=='n'?5:4)] = 0 ;
a = iobuf_open( buf );
if (a && is_secured_file (iobuf_get_fd (a)))
{
iobuf_close (a);
a = NULL;
errno = EPERM;
}
if( a && opt.verbose )
log_info(_("assuming signed data in `%s'\n"), buf );
if (a && pfx)
handle_progress (pfx, a, buf);
xfree (buf);
xfree(buf);
}
}
return a;
@ -308,23 +330,34 @@ copy_options_file( const char *destdir )
if( opt.dry_run )
return;
fname = xmalloc ( strlen(datadir) + strlen(destdir)
+ strlen (SKELEXT) + 15 );
fname = xmalloc( strlen(datadir) + strlen(destdir) + 15 );
strcpy(stpcpy(fname, datadir), DIRSEP_S "gpg-conf" SKELEXT );
src = fopen( fname, "r" );
if (src && is_secured_file (fileno (src)))
{
fclose (src);
src = NULL;
errno = EPERM;
}
if( !src ) {
log_error(_("%s: can't open: %s\n"), fname, strerror(errno) );
xfree (fname);
log_error(_("can't open `%s': %s\n"), fname, strerror(errno) );
xfree(fname);
return;
}
strcpy(stpcpy(fname, destdir), DIRSEP_S "gpg" EXTSEP_S "conf" );
oldmask=umask(077);
dst = fopen( fname, "w" );
if ( is_secured_filename (fname) )
{
dst = NULL;
errno = EPERM;
}
else
dst = fopen( fname, "w" );
umask(oldmask);
if( !dst ) {
log_error(_("%s: can't create: %s\n"), fname, strerror(errno) );
log_error(_("can't create `%s': %s\n"), fname, strerror(errno) );
fclose( src );
xfree (fname);
xfree(fname);
return;
}
@ -354,7 +387,7 @@ copy_options_file( const char *destdir )
log_info (_("WARNING: options in `%s'"
" are not yet active during this run\n"),
fname);
xfree (fname);
xfree(fname);
}
@ -380,10 +413,10 @@ try_make_homedir( const char *fname )
&& !compare_filenames( fname, defhome ) )
) {
if( mkdir( fname, S_IRUSR|S_IWUSR|S_IXUSR ) )
log_fatal( _("%s: can't create directory: %s\n"),
log_fatal( _("can't create directory `%s': %s\n"),
fname, strerror(errno) );
else if( !opt.quiet )
log_info( _("%s: directory created\n"), fname );
log_info( _("directory `%s' created\n"), fname );
copy_options_file( fname );
/* log_info(_("you have to start GnuPG again, " */
/* "so it can read the new configuration file\n") ); */

View File

@ -1,6 +1,6 @@
/* options.h
* Copyright (C) 1998, 1999, 2000, 2001, 2002,
* 2003 Free Software Foundation, Inc.
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
* 2006 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -16,17 +16,17 @@
*
* 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
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
#ifndef G10_OPTIONS_H
#define G10_OPTIONS_H
#include <sys/types.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)
@ -37,155 +37,215 @@
#endif
EXTERN_UNLESS_MAIN_MODULE
struct {
int verbose;
int quiet;
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: 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 def_cert_check_level;
int sk_comments;
int no_version;
int marginals_needed;
int completes_needed;
int max_cert_depth;
const char *homedir;
const char *agent_program;
char *display; /* 5 options to be passed to the gpg-agent */
char *ttyname;
char *ttytype;
char *lc_ctype;
char *lc_messages;
struct
{
int verbose;
int quiet;
unsigned debug;
int armor;
char *outfile;
off_t max_output;
int dry_run;
int list_only;
int textmode;
int expert;
const char *def_sig_expire;
int ask_sig_expire;
const char *def_cert_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: 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 compress_algo;
int compress_level;
int bz2_compress_level;
int bz2_decompress_lowmem;
const char *def_secret_key;
char *def_recipient;
int def_recipient_self;
int def_cert_level;
int min_cert_level;
int ask_cert_level;
int no_version;
int marginals_needed;
int completes_needed;
int max_cert_depth;
const char *homedir;
const char *agent_program;
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;
/* TM_CLASSIC must be zero to accomodate trustdbs generated before
we started storing the trust model inside the trustdb. */
enum {TM_CLASSIC=0, TM_PGP=1, TM_ALWAYS, TM_AUTO} trust_model;
unsigned int force_ownertrust;
enum
{
CO_GNUPG=0, CO_RFC2440, CO_RFC1991, CO_PGP2, CO_PGP6, CO_PGP7, CO_PGP8
} compliance;
int pgp2_workarounds;
unsigned int emulate_bugs; /* bug emulation flags EMUBUG_xxxx */
int shm_coprocess;
const char *set_filename;
STRLIST comments;
int throw_keyid;
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;
char *keyserver_uri;
char *keyserver_scheme;
char *keyserver_host;
char *keyserver_port;
char *keyserver_opaque;
int skip_verify;
int compress_keys;
int compress_sigs;
/* TM_CLASSIC must be zero to accomodate trustdbs generated before
we started storing the trust model inside the trustdb. */
enum
{
TM_CLASSIC=0, TM_PGP=1, TM_EXTERNAL=2, TM_ALWAYS, TM_DIRECT, TM_AUTO
} trust_model;
int force_ownertrust;
enum
{
CO_GNUPG=0, CO_RFC2440, CO_RFC1991, CO_PGP2, CO_PGP6, CO_PGP7, CO_PGP8
} compliance;
enum
{
KF_SHORT, KF_LONG, KF_0xSHORT, KF_0xLONG
} keyid_format;
int pgp2_workarounds;
int shm_coprocess;
const char *set_filename;
STRLIST comments;
int throw_keyid;
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;
struct keyserver_spec
{
char *uri;
char *scheme;
char *auth;
char *host;
char *port;
char *path;
char *opaque;
STRLIST options;
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;
int try_dns_srv;
unsigned int import_options;
unsigned int export_options;
STRLIST other;
} keyserver_options;
int exec_disable;
int exec_path_set;
unsigned int direct_uri:1;
} flags;
struct keyserver_spec *next;
} *keyserver;
struct
{
unsigned int options;
unsigned int import_options;
unsigned int export_options;
unsigned int list_options;
unsigned int verify_options;
char *def_preference_list;
prefitem_t *personal_cipher_prefs;
prefitem_t *personal_digest_prefs;
prefitem_t *personal_compress_prefs;
int no_perm_warn;
int no_mdc_warn;
char *temp_dir;
int no_encrypt_to;
int interactive;
STRLIST sig_notation_data;
STRLIST cert_notation_data;
STRLIST sig_policy_url;
STRLIST cert_policy_url;
STRLIST sig_keyserver_url;
int use_embedded_filename;
int allow_non_selfsigned_uid;
int allow_freeform_uid;
int no_literal;
ulong set_filesize;
int fast_list_mode;
int fixed_list_mode;
int ignore_time_conflict;
int ignore_valid_from;
int ignore_crc_error;
int ignore_mdc_error;
int command_fd;
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;
struct groupitem *grouplist;
int strict;
int mangle_dos_filenames;
int enable_progress_filter;
STRLIST other;
} keyserver_options;
int exec_disable;
int exec_path_set;
unsigned int import_options;
unsigned int export_options;
unsigned int list_options;
unsigned int verify_options;
char *def_preference_list;
prefitem_t *personal_cipher_prefs;
prefitem_t *personal_digest_prefs;
prefitem_t *personal_compress_prefs;
int no_perm_warn;
int no_mdc_warn;
char *temp_dir;
int no_encrypt_to;
int interactive;
struct notation *sig_notations;
struct notation *cert_notations;
STRLIST sig_policy_url;
STRLIST cert_policy_url;
STRLIST sig_keyserver_url;
STRLIST cert_subpackets;
STRLIST sig_subpackets;
int use_embedded_filename;
int allow_non_selfsigned_uid;
int allow_freeform_uid;
int no_literal;
ulong set_filesize;
int fast_list_mode;
int fixed_list_mode;
int ignore_time_conflict;
int ignore_valid_from;
int ignore_crc_error;
int ignore_mdc_error;
int command_fd;
const char *override_session_key;
int show_session_key;
int use_agent;
const char *gpg_agent_info;
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;
struct groupitem *grouplist;
int strict;
int mangle_dos_filenames;
int enable_progress_filter;
unsigned int screen_columns;
unsigned int screen_lines;
byte *show_subpackets;
int rfc2440_text;
/* If true, let write failures on the status-fd exit the process. */
int exit_on_status_write_error;
/* If > 0, limit the number of card insertion prompts to this
value. */
int limit_card_insert_tries;
#ifdef ENABLE_CARD_SUPPORT
/* FIXME: We don't needs this here as it is done in scdaemon. */
const char *ctapi_driver; /* Library to access the ctAPI. */
const char *pcsc_driver; /* Library to access the PC/SC system. */
int disable_ccid; /* Disable the use of the internal CCID driver. */
#endif /*ENABLE_CARD_SUPPORT*/
struct
{
/* If set, require an 0x19 backsig to be present on signatures
made by signing subkeys. If not set, a missing backsig is not
an error (but an invalid backsig still is). */
unsigned int require_cross_cert:1;
} flags;
/* Linked list of ways to find a key if the key isn't on the local
keyring. */
struct akl
{
enum {AKL_CERT, AKL_PKA, AKL_LDAP, AKL_KEYSERVER, AKL_SPEC} type;
struct keyserver_spec *spec;
struct akl *next;
} *auto_key_locate;
/* True if multiple concatenated signatures may be verified. */
int allow_multisig_verification;
} opt;
#define EMUBUG_MDENCODE 4
/* CTRL is used to keep some global variables we currently can't
avoid. Future concurrent versions of gpg will put it into a per
request structure CTRL. */
EXTERN_UNLESS_MAIN_MODULE
struct {
int in_auto_key_retrieve; /* True if we are doing an
auto_key_retrieve. */
} glo_ctrl;
#define DBG_PACKET_VALUE 1 /* debug packet reading/writing */
#define DBG_MPI_VALUE 2 /* debug mpi details */
@ -199,15 +259,24 @@ struct {
#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_CARD_IO_VALUE 2048 /* debug smart card I/O. */
#define DBG_PACKET (opt.debug & DBG_PACKET_VALUE)
#define DBG_CIPHER (opt.debug & DBG_CIPHER_VALUE)
#define DBG_FILTER (opt.debug & DBG_FILTER_VALUE)
#define DBG_CACHE (opt.debug & DBG_CACHE_VALUE)
#define DBG_TRUST (opt.debug & DBG_TRUST_VALUE)
#define DBG_HASHING (opt.debug & DBG_HASHING_VALUE)
#define DBG_EXTPROG (opt.debug & DBG_EXTPROG_VALUE)
#define DBG_CARD_IO (opt.debug & DBG_CARD_IO_VALUE)
/* FIXME: We need to check whey we did not put this into opt. */
#define DBG_MEMORY memory_debug_mode
#define DBG_MEMSTAT memory_stat_debug_mode
EXTERN_UNLESS_MAIN_MODULE int memory_debug_mode;
EXTERN_UNLESS_MAIN_MODULE int memory_stat_debug_mode;
#define GNUPG (opt.compliance==CO_GNUPG)
#define RFC1991 (opt.compliance==CO_RFC1991 || opt.compliance==CO_PGP2)
@ -217,39 +286,54 @@ struct {
#define PGP7 (opt.compliance==CO_PGP7)
#define PGP8 (opt.compliance==CO_PGP8)
/* Various option flags */
/* Various option flags. Note that there should be no common string
names between the IMPORT_ and EXPORT_ flags as they can be mixed in
the keyserver-options option. */
#define IMPORT_ALLOW_LOCAL_SIGS 1
#define IMPORT_REPAIR_PKS_SUBKEY_BUG 2
#define IMPORT_FAST_IMPORT 4
#define IMPORT_SK2PK 8
#define IMPORT_LOCAL_SIGS (1<<0)
#define IMPORT_REPAIR_PKS_SUBKEY_BUG (1<<1)
#define IMPORT_FAST (1<<2)
#define IMPORT_SK2PK (1<<3)
#define IMPORT_MERGE_ONLY (1<<4)
#define IMPORT_MINIMAL (1<<5)
#define IMPORT_CLEAN (1<<6)
#define EXPORT_INCLUDE_NON_RFC 1
#define EXPORT_INCLUDE_LOCAL_SIGS 2
#define EXPORT_INCLUDE_ATTRIBUTES 4
#define EXPORT_INCLUDE_SENSITIVE_REVKEYS 8
#define EXPORT_SEXP_FORMAT 16
#define EXPORT_LOCAL_SIGS (1<<0)
#define EXPORT_ATTRIBUTES (1<<1)
#define EXPORT_SENSITIVE_REVKEYS (1<<2)
#define EXPORT_RESET_SUBKEY_PASSWD (1<<3)
#define EXPORT_MINIMAL (1<<4)
#define EXPORT_CLEAN (1<<5)
#define LIST_SHOW_PHOTOS (1<<0)
#define LIST_SHOW_POLICY_URLS (1<<1)
#define LIST_SHOW_STD_NOTATIONS (1<<2)
#define LIST_SHOW_USER_NOTATIONS (1<<3)
#define LIST_SHOW_NOTATIONS (LIST_SHOW_STD_NOTATIONS|LIST_SHOW_USER_NOTATIONS)
#define LIST_SHOW_KEYSERVER_URLS (1<<4)
#define LIST_SHOW_UID_VALIDITY (1<<5)
#define LIST_SHOW_UNUSABLE_UIDS (1<<6)
#define LIST_SHOW_UNUSABLE_SUBKEYS (1<<7)
#define LIST_SHOW_KEYRING (1<<8)
#define LIST_SHOW_SIG_EXPIRE (1<<9)
#define LIST_SHOW_SIG_SUBPACKETS (1<<10)
#define LIST_SHOW_PHOTOS 1
#define LIST_SHOW_POLICY 2
#define LIST_SHOW_NOTATION 4
#define LIST_SHOW_KEYSERVER 8
#define LIST_SHOW_VALIDITY 16
#define LIST_SHOW_LONG_KEYID 32
#define LIST_SHOW_KEYRING 64
#define LIST_SHOW_SIG_EXPIRE 128
#define VERIFY_SHOW_PHOTOS (1<<0)
#define VERIFY_SHOW_POLICY_URLS (1<<1)
#define VERIFY_SHOW_STD_NOTATIONS (1<<2)
#define VERIFY_SHOW_USER_NOTATIONS (1<<3)
#define VERIFY_SHOW_NOTATIONS (VERIFY_SHOW_STD_NOTATIONS|VERIFY_SHOW_USER_NOTATIONS)
#define VERIFY_SHOW_KEYSERVER_URLS (1<<4)
#define VERIFY_SHOW_UID_VALIDITY (1<<5)
#define VERIFY_SHOW_UNUSABLE_UIDS (1<<6)
#define VERIFY_PKA_LOOKUPS (1<<7)
#define VERIFY_PKA_TRUST_INCREASE (1<<8)
#define VERIFY_SHOW_PHOTOS 1
#define VERIFY_SHOW_POLICY 2
#define VERIFY_SHOW_NOTATION 4
#define VERIFY_SHOW_KEYSERVER 8
#define VERIFY_SHOW_VALIDITY 16
#define VERIFY_SHOW_LONG_KEYID 32
#define KEYSERVER_USE_TEMP_FILES (1<<0)
#define KEYSERVER_KEEP_TEMP_FILES (1<<1)
#define KEYSERVER_ADD_FAKE_V3 (1<<2)
#define KEYSERVER_AUTO_KEY_RETRIEVE (1<<3)
#define KEYSERVER_HONOR_KEYSERVER_URL (1<<4)
#define KEYSERVER_HONOR_PKA_RECORD (1<<5)
#endif /*G10_OPTIONS_H*/

View File

@ -1,6 +1,6 @@
/* packet.h - packet definitions
* Copyright (C) 1998, 1999, 2000, 2001, 2002,
* 2003 Free Software Foundation, Inc.
/* packet.h - OpenPGP packet definitions
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
* 2006 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -16,21 +16,18 @@
*
* 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
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
#ifndef G10_PACKET_H
#define G10_PACKET_H
#include "gpg.h"
#include <gcrypt.h>
#include "types.h"
#include "../common/iobuf.h"
#include "../jnlib/strlist.h"
#include "cipher.h"
#include "filter.h"
#include "global.h"
#define DEBUG_PARSE_PACKET 1
@ -124,36 +121,56 @@ struct revocation_key {
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; /* At least one policy URL is present */
unsigned notation:1; /* At least one notation is present */
unsigned pref_ks:1; /* At least one preferred keyserver 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 */
/* (PUBKEY_ALGO_xxx) */
byte digest_algo; /* algorithm used for digest (DIGEST_ALGO_xxxx) */
byte trust_depth;
byte trust_value;
const byte *trust_regexp;
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 */
gcry_mpi_t data[PUBKEY_MAX_NSIG];
/* Object to keep information about a PKA DNS record. */
typedef struct
{
int valid; /* An actual PKA record exists for EMAIL. */
int checked; /* Set to true if the FPR has been checked against the
actual key. */
char *uri; /* Malloced string with the URI. NULL if the URI is
not available.*/
unsigned char fpr[20]; /* The fingerprint as stored in the PKA RR. */
char email[1];/* The email address from the notation data. */
} pka_info_t;
/* Object to keep information pertaining to a signature. */
typedef struct
{
struct
{
unsigned checked:1; /* Signature has been checked. */
unsigned valid:1; /* Signature is good (if checked is set). */
unsigned chosen_selfsig:1; /* A selfsig that is the chosen one. */
unsigned unknown_critical:1;
unsigned exportable:1;
unsigned revocable:1;
unsigned policy_url:1; /* At least one policy URL is present */
unsigned notation:1; /* At least one notation is present */
unsigned pref_ks:1; /* At least one preferred keyserver is present */
unsigned expired:1;
unsigned pka_tried:1; /* Set if we tried to retrieve the PKA record. */
} flags;
u32 keyid[2]; /* 64 bit keyid */
u32 timestamp; /* Signature made (seconds since Epoch). */
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 */
/* (PUBKEY_ALGO_xxx) */
byte digest_algo; /* Algorithm used for digest (DIGEST_ALGO_xxxx). */
byte trust_depth;
byte trust_value;
const byte *trust_regexp;
struct revocation_key **revkey;
int numrevkeys;
pka_info_t *pka_info; /* Malloced PKA data or NULL if not
available. See also flags.pka_tried. */
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. */
gcry_mpi_t data[PUBKEY_MAX_NSIG];
} PKT_signature;
#define ATTRIB_IMAGE 1
@ -165,41 +182,57 @@ struct user_attribute {
u32 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;
byte *namehash;
int help_key_usage;
u32 help_key_expire;
int help_full_count;
int help_marginal_count;
int is_primary; /* 2 if set via the primary flag, 1 if calculated */
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;
int ks_modify;
u32 created; /* according to the self-signature */
byte selfsigversion;
char name[1];
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;
byte *namehash;
int help_key_usage;
u32 help_key_expire;
int help_full_count;
int help_marginal_count;
int is_primary; /* 2 if set via the primary flag, 1 if calculated */
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)*/
u32 created; /* according to the self-signature */
byte selfsigversion;
struct
{
/* TODO: Move more flags here */
unsigned mdc:1;
unsigned ks_modify:1;
unsigned compacted:1;
} flags;
char name[1];
} PKT_user_id;
struct revoke_info
{
/* revoked at this date */
u32 date;
/* the keyid of the revoking key (selfsig or designated revoker) */
u32 keyid[2];
/* the algo of the revoking key */
byte algo;
};
/****************
* Note about the pkey/skey elements: We assume that the secret keys
* has the same elemts as the public key at the begin of the array, so
* that npkey < nskey and it is possible to compare the secret and
* public keys by comparing the first npkey elements of pkey against skey.
* public keys by comparing the first npkey elements of pkey againts skey.
*/
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 */
struct revoke_info revoked;
byte hdrbytes; /* number of header bytes */
byte version;
byte selfsigversion; /* highest version of all of the self-sigs */
@ -208,10 +241,13 @@ typedef struct {
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_revoked; /* key has been revoked, 1 if by the
owner, 2 if by a designated revoker */
int maybe_revoked; /* a designated revocation is present, but
without the key to check it */
int is_valid; /* key (especially subkey) is valid */
int dont_cache; /* do not cache this */
ulong local_id; /* internal use, valid if > 0 */
byte backsig; /* 0=none, 1=bad, 2=good */
u32 main_keyid[2]; /* keyid of the primary key */
u32 keyid[2]; /* calculated by keyid_from_pk() */
byte is_primary;
@ -273,15 +309,16 @@ typedef struct {
u32 len; /* reserved */
byte new_ctb;
byte algorithm;
iobuf_t buf; /* iobuf_t reference */
iobuf_t buf; /* IOBUF reference */
} PKT_compressed;
typedef struct {
u32 len; /* length of encrypted data */
int extralen; /* this is (blocksize+2) */
byte new_ctb; /* uses a new CTB */
byte is_partial; /* partial length encoded */
byte mdc_method; /* > 0: integrity protected encrypted data packet */
iobuf_t buf; /* iobuf_t reference */
iobuf_t buf; /* IOBUF reference */
} PKT_encrypted;
typedef struct {
@ -295,7 +332,7 @@ typedef struct {
typedef struct {
u32 len; /* length of encrypted data */
iobuf_t buf; /* iobuf_t reference */
iobuf_t buf; /* IOBUF reference */
byte new_ctb;
byte is_partial; /* partial length encoded */
int mode;
@ -364,9 +401,25 @@ typedef enum {
SIGSUBPKT_REVOC_REASON =29, /* reason for revocation */
SIGSUBPKT_FEATURES =30, /* feature flags */
SIGSUBPKT_SIGNATURE =32, /* embedded signature */
SIGSUBPKT_FLAG_CRITICAL=128
} sigsubpkttype_t;
struct notation
{
char *name;
char *value;
char *altvalue;
unsigned char *bdat;
size_t blen;
struct
{
unsigned int critical:1;
unsigned int ignore:1;
} flags;
struct notation *next;
};
/*-- mainproc.c --*/
int proc_packets( void *ctx, iobuf_t a );
@ -407,6 +460,8 @@ int copy_some_packets( iobuf_t inp, iobuf_t out, off_t stopoff );
int skip_some_packets( iobuf_t inp, unsigned n );
#endif
int parse_signature( iobuf_t inp, int pkttype, unsigned long pktlen,
PKT_signature *sig );
const byte *enum_sig_subpkt ( const subpktarea_t *subpkts,
sigsubpkttype_t reqtype,
size_t *ret_n, int *start, int *critical );
@ -427,7 +482,6 @@ PACKET *create_gpg_control ( ctrlpkttype_t type,
/*-- build-packet.c --*/
int build_packet( iobuf_t inp, PACKET *pkt );
u32 calc_packet_length( PACKET *pkt );
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 );
@ -435,6 +489,9 @@ int delete_sig_subpkt(subpktarea_t *buffer, sigsubpkttype_t type );
void build_attribute_subpkt(PKT_user_id *uid,byte type,
const void *buf,u32 buflen,
const void *header,u32 headerlen);
struct notation *string_to_notation(const char *string,int is_utf8);
struct notation *sig_to_notation(PKT_signature *sig);
void free_notation(struct notation *notation);
/*-- free-packet.c --*/
void free_symkey_enc( PKT_symkey_enc *enc );
@ -463,8 +520,8 @@ int cmp_user_ids( PKT_user_id *a, PKT_user_id *b );
/*-- sig-check.c --*/
int signature_check( PKT_signature *sig, MD_HANDLE digest );
int signature_check2( PKT_signature *sig, MD_HANDLE digest, u32 *r_expiredate,
int signature_check( PKT_signature *sig, gcry_md_hd_t digest );
int signature_check2( PKT_signature *sig, gcry_md_hd_t digest, u32 *r_expiredate,
int *r_expired, int *r_revoked, PKT_public_key *ret_pk );
/*-- seckey-cert.c --*/
@ -485,13 +542,10 @@ 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 *create_failed );
int ask_for_detached_datafile( MD_HANDLE md, MD_HANDLE md2,
int nooutput, int clearsig );
int ask_for_detached_datafile( gcry_md_hd_t md, gcry_md_hd_t md2,
const char *inname, int textmode );
/*-- comment.c --*/
int write_comment( iobuf_t 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,

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 @@
/* photoid.c - photo ID handling code
* Copyright (C) 2001, 2002 Free Software Foundation, Inc.
* Copyright (C) 2001, 2002, 2005 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -15,7 +15,8 @@
*
* 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
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
#include <config.h>
@ -28,6 +29,8 @@
# define VER_PLATFORM_WIN32_WINDOWS 1
# endif
#endif
#include "gpg.h"
#include "packet.h"
#include "status.h"
#include "exec.h"
@ -35,21 +38,23 @@
#include "util.h"
#include "i18n.h"
#include "iobuf.h"
#include "memory.h"
#include "options.h"
#include "main.h"
#include "photoid.h"
#include "ttyio.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 *
generate_photo_id(PKT_public_key *pk,const char *photo_name)
{
PKT_user_id *uid;
int error=1,i;
unsigned int len;
char *filename=NULL;
char *filename;
byte *photo=NULL;
byte header[16];
iobuf_t file;
IOBUF file;
int overflow;
header[0]=0x10; /* little side of photo header length */
header[1]=0; /* big side of photo header length */
@ -60,48 +65,78 @@ PKT_user_id *generate_photo_id(PKT_public_key *pk)
header[i]=0;
#define EXTRA_UID_NAME_SPACE 71
uid=xcalloc (1,sizeof(*uid)+71);
uid=xmalloc_clear(sizeof(*uid)+71);
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"));
if(photo_name && *photo_name)
filename=make_filename(photo_name,(void *)NULL);
else
{
tty_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"));
filename=NULL;
}
while(photo==NULL)
{
printf("\n");
if(filename==NULL)
{
char *tempname;
xfree (filename);
tty_printf("\n");
filename=cpr_get("photoid.jpeg.add",
_("Enter JPEG filename for photo ID: "));
tty_enable_completion(NULL);
if(strlen(filename)==0)
goto scram;
tempname=cpr_get("photoid.jpeg.add",
_("Enter JPEG filename for photo ID: "));
tty_disable_completion();
filename=make_filename(tempname,(void *)NULL);
xfree(tempname);
if(strlen(filename)==0)
goto scram;
}
file=iobuf_open(filename);
if (file && is_secured_file (iobuf_get_fd (file)))
{
iobuf_close (file);
file = NULL;
errno = EPERM;
}
if(!file)
{
log_error(_("Unable to open photo \"%s\": %s\n"),
log_error(_("unable to open JPEG file `%s': %s\n"),
filename,strerror(errno));
xfree(filename);
filename=NULL;
continue;
}
len=iobuf_get_filelength(file);
if(len>6144)
len=iobuf_get_filelength(file, &overflow);
if(len>6144 || overflow)
{
printf("This JPEG is really large (%d bytes) !\n",len);
tty_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)? ")))
_("Are you sure you want to use it? (y/N) ")))
{
iobuf_close(file);
xfree(filename);
filename=NULL;
continue;
}
}
photo=xmalloc (len);
photo=xmalloc(len);
iobuf_read(file,photo,len);
iobuf_close(file);
@ -109,9 +144,11 @@ PKT_user_id *generate_photo_id(PKT_public_key *pk)
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);
xfree (photo);
log_error(_("`%s' is not a JPEG file\n"),filename);
xfree(photo);
photo=NULL;
xfree(filename);
filename=NULL;
continue;
}
@ -132,8 +169,10 @@ PKT_user_id *generate_photo_id(PKT_public_key *pk)
goto scram;
case 0:
free_attributes(uid);
xfree (photo);
xfree(photo);
photo=NULL;
xfree(filename);
filename=NULL;
continue;
}
}
@ -143,13 +182,13 @@ PKT_user_id *generate_photo_id(PKT_public_key *pk)
uid->ref=1;
scram:
xfree (filename);
xfree (photo);
xfree(filename);
xfree(photo);
if(error)
{
free_attributes(uid);
xfree (uid);
xfree(uid);
return NULL;
}
@ -283,7 +322,7 @@ void show_photos(const struct user_attribute *attrs,
if(!command)
goto fail;
name=xmalloc (16+strlen(EXTSEP_S)+
name=xmalloc(16+strlen(EXTSEP_S)+
strlen(image_type_to_string(args.imagetype,0))+1);
/* Make the filename. Notice we are not using the image
@ -302,7 +341,7 @@ void show_photos(const struct user_attribute *attrs,
if(exec_write(&spawn,NULL,command,name,1,1)!=0)
{
xfree (name);
xfree(name);
goto fail;
}
@ -311,7 +350,7 @@ void show_photos(const struct user_attribute *attrs,
image_type_to_string(args.imagetype,2));
#endif
xfree (name);
xfree(name);
fwrite(&attrs[i].data[offset],attrs[i].len-offset,1,spawn->tochild);

View File

@ -15,7 +15,8 @@
*
* 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
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
/* Photo ID functions */
@ -25,7 +26,7 @@
#include "packet.h"
PKT_user_id *generate_photo_id(PKT_public_key *pk);
PKT_user_id *generate_photo_id(PKT_public_key *pk,const char *filename);
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,

View File

@ -1,317 +0,0 @@
/* 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_t 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_t 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,6 +1,6 @@
/* plaintext.c - process plaintext packets
* Copyright (C) 1998, 1999, 2000, 2001, 2002,
* 2003 Free Software Foundation, Inc.
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004,
* 2005, 2006 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -16,7 +16,8 @@
*
* 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
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
#include <config.h>
@ -25,13 +26,13 @@
#include <string.h>
#include <errno.h>
#include <assert.h>
#include <sys/types.h>
#ifdef HAVE_DOSISH_SYSTEM
#include <fcntl.h> /* for setmode() */
#endif
#include "gpg.h"
#include "util.h"
#include "memory.h"
#include "options.h"
#include "packet.h"
#include "ttyio.h"
@ -41,7 +42,6 @@
#include "i18n.h"
/****************
* Handle a plaintext packet. If MFX is not NULL, update the MDs
* Note: we should use the filter stuff here, but we have to add some
@ -50,27 +50,41 @@
*/
int
handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx,
int nooutput, int clearsig, int *create_failed )
int nooutput, int clearsig )
{
char *fname = NULL;
FILE *fp = NULL;
static off_t count=0;
int rc = 0;
int c;
int convert = pt->mode == 't';
int convert = (pt->mode == 't' || pt->mode == 'u');
#ifdef __riscos__
int filetype = 0xfff;
#endif
int dummy_create_failed;
if (!create_failed)
create_failed = &dummy_create_failed;
*create_failed = 0;
/* Let people know what the plaintext info is. This allows the
receiving program to try and do something different based on
the format code (say, recode UTF-8 to local). */
if(!nooutput && is_status_enabled())
{
char status[50];
sprintf(status,"%X %lu ",(byte)pt->mode,(ulong)pt->timestamp);
write_status_text_and_buffer(STATUS_PLAINTEXT,
status,pt->name,pt->namelen,0);
if(!pt->is_partial)
{
sprintf(status,"%lu",(ulong)pt->len);
write_status_text(STATUS_PLAINTEXT_LENGTH,status);
}
}
/* create the filename as C string */
if( nooutput )
;
else if( opt.outfile ) {
fname = xmalloc ( strlen( opt.outfile ) + 1);
fname = xmalloc( strlen( opt.outfile ) + 1);
strcpy(fname, opt.outfile );
}
else if( pt->namelen == 8 && !memcmp( pt->name, "_CONSOLE", 8 ) ) {
@ -82,8 +96,7 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx,
if( !fname )
fname = ask_outfile_name( pt->name, pt->namelen );
if( !fname ) {
*create_failed = 1;
rc = GPG_ERR_GENERAL;
rc = gpg_error (GPG_ERR_GENERAL) /* Can't create file. */
goto leave;
}
}
@ -93,20 +106,20 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx,
if( nooutput )
;
else if( !*fname || (*fname=='-' && !fname[1])) {
/* no filename or "-" given; write to stdout */
else if ( iobuf_is_pipe_filename (fname) || !*fname)
{
/* No filename or "-" given; write to stdout. */
fp = stdout;
#ifdef HAVE_DOSISH_SYSTEM
setmode ( fileno(fp) , O_BINARY );
#endif
}
}
else {
while( !overwrite_filep (fname) ) {
char *tmp = ask_outfile_name (NULL, 0);
if ( !tmp || !*tmp ) {
xfree (tmp);
*create_failed = 1;
rc = GPG_ERR_GENERAL;
rc = G10ERR_CREATE_FILE;
goto leave;
}
xfree (fname);
@ -117,26 +130,34 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx,
#ifndef __riscos__
if( fp || nooutput )
;
else if( !(fp = fopen(fname,"wb")) ) {
rc = gpg_error_from_errno (errno);
else if (is_secured_filename (fname))
{
errno = EPERM;
log_error(_("error creating `%s': %s\n"), fname, strerror(errno) );
*create_failed = 1;
rc = G10ERR_CREATE_FILE;
goto leave;
}
else if( !(fp = fopen(fname,"wb")) ) {
log_error(_("error creating `%s': %s\n"), fname, strerror(errno) );
rc = G10ERR_CREATE_FILE;
goto leave;
}
#else /* __riscos__ */
/* Convert all '.' in fname to '/' -- we don't create directories! */
for( c=0; fname[c]; ++c )
if( fname[c] == '.' )
fname[c] = '/';
/* If no output filename was given, i.e. we constructed it,
convert all '.' in fname to '/' but not vice versa as
we don't create directories! */
if( !opt.outfile )
for( c=0; fname[c]; ++c )
if( fname[c] == '.' )
fname[c] = '/';
if( fp || nooutput )
;
else {
fp = fopen(fname,"wb");
if( !fp ) {
rc == gpg_error_from_errno (errno);
log_error(_("error creating `%s': %s\n"), fname, strerror(errno) );
*create_failed = 1;
rc = G10ERR_CREATE_FILE;
if (errno == 106)
log_info("Do output file and input file have the same name?\n");
goto leave;
@ -156,15 +177,21 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx,
#endif /* __riscos__ */
if( !pt->is_partial ) {
/* we have an actual length (which might be zero). */
assert( !clearsig );
/* We have an actual length (which might be zero). */
if (clearsig) {
log_error ("clearsig encountered while not expected\n");
rc = G10ERR_UNEXPECTED;
goto leave;
}
if( convert ) { /* text mode */
for( ; pt->len; pt->len-- ) {
if( (c = iobuf_get(pt->buf)) == -1 ) {
rc = gpg_error_from_errno (errno);
log_error("Problem reading source (%u bytes remaining)\n",
(unsigned)pt->len);
goto leave;
rc = gpg_error_from_errno (errno);
log_error ("problem reading source (%u bytes remaining)\n",
(unsigned)pt->len);
goto leave;
}
if( mfx->md )
gcry_md_putc (mfx->md, c );
@ -172,65 +199,93 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx,
if( c == '\r' ) /* convert to native line ending */
continue; /* fixme: this hack might be too simple */
#endif
if( fp ) {
if( putc( c, fp ) == EOF ) {
rc = gpg_error_from_errno (errno);
if( fp )
{
if(opt.max_output && (++count)>opt.max_output)
{
log_error("Error writing to `%s': %s\n",
fname,"exceeded --max-output limit\n");
rc = gpg_error (GPG_ERR_GENERAL);
goto leave;
}
else if( putc( c, fp ) == EOF )
{
log_error("Error writing to `%s': %s\n",
fname, strerror(errno) );
rc = G10ERR_WRITE_FILE;
goto leave;
}
}
}
}
}
}
else { /* binary mode */
byte *buffer = xmalloc ( 32768 );
byte *buffer = xmalloc( 32768 );
while( pt->len ) {
int len = pt->len > 32768 ? 32768 : pt->len;
len = iobuf_read( pt->buf, buffer, len );
if( len == -1 ) {
rc = gpg_error_from_errno (errno);
log_error("Problem reading source (%u bytes remaining)\n",
(unsigned)pt->len);
xfree ( buffer );
rc = G10ERR_READ_FILE;
xfree( buffer );
goto leave;
}
if( mfx->md )
gcry_md_write( mfx->md, buffer, len );
if( fp ) {
if( fwrite( buffer, 1, len, fp ) != len ) {
rc = gpg_error_from_errno (errno);
gcry_md_write ( mfx->md, buffer, len );
if( fp )
{
if(opt.max_output && (count+=len)>opt.max_output)
{
log_error("Error writing to `%s': %s\n",
fname,"exceeded --max-output limit\n");
rc = G10ERR_WRITE_FILE;
xfree( buffer );
goto leave;
}
else if( fwrite( buffer, 1, len, fp ) != len )
{
log_error("Error writing to `%s': %s\n",
fname, strerror(errno) );
xfree ( buffer );
rc = G10ERR_WRITE_FILE;
xfree( buffer );
goto leave;
}
}
}
}
pt->len -= len;
}
xfree ( buffer );
xfree( 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 */
#endif
if( fp ) {
if( putc( c, fp ) == EOF ) {
rc = gpg_error_from_errno (errno);
if( fp )
{
if(opt.max_output && (++count)>opt.max_output)
{
log_error("Error writing to `%s': %s\n",
fname,"exceeded --max-output limit\n");
rc = G10ERR_WRITE_FILE;
goto leave;
}
else if( putc( c, fp ) == EOF )
{
log_error("Error writing to `%s': %s\n",
fname, strerror(errno) );
rc = G10ERR_WRITE_FILE;
goto leave;
}
}
}
}
}
}
else { /* binary mode */
byte *buffer = xmalloc ( 32768 );
byte *buffer = xmalloc( 32768 );
int eof;
for( eof=0; !eof; ) {
/* Why do we check for len < 32768:
@ -245,18 +300,27 @@ 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 );
if( fp ) {
if( fwrite( buffer, 1, len, fp ) != len ) {
rc = gpg_error_from_errno (errno);
md_write( mfx->md, buffer, len );
if( fp )
{
if(opt.max_output && (count+=len)>opt.max_output)
{
log_error("Error writing to `%s': %s\n",
fname, strerror(errno) );
xfree ( buffer );
fname,"exceeded --max-output limit\n");
rc = G10ERR_WRITE_FILE;
xfree( buffer );
goto leave;
}
else if( fwrite( buffer, 1, len, fp ) != len ) {
log_error("Error writing to `%s': %s\n",
fname, strerror(errno) );
rc = G10ERR_WRITE_FILE;
xfree( buffer );
goto leave;
}
}
}
}
xfree ( buffer );
xfree( buffer );
}
pt->buf = NULL;
}
@ -264,19 +328,28 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx,
int state = 0;
while( (c = iobuf_get(pt->buf)) != -1 ) {
if( fp ) {
if( putc( c, fp ) == EOF ) {
rc = gpg_error_from_errno (errno);
if( fp )
{
if(opt.max_output && (++count)>opt.max_output)
{
log_error("Error writing to `%s': %s\n",
fname, strerror(errno) );
fname,"exceeded --max-output limit\n");
rc = G10ERR_WRITE_FILE;
goto leave;
}
}
}
else if( putc( c, fp ) == EOF )
{
log_error("Error writing to `%s': %s\n",
fname, strerror(errno) );
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 ) {
@ -285,18 +358,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 );
}
}
}
@ -305,9 +378,9 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx,
}
if( fp && fp != stdout && fclose(fp) ) {
rc = gpg_error_from_errno (errno);
log_error("Error closing `%s': %s\n", fname, strerror(errno) );
fp = NULL;
rc = G10ERR_WRITE_FILE;
goto leave;
}
fp = NULL;
@ -315,12 +388,12 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx,
leave:
if( fp && fp != stdout )
fclose(fp);
xfree (fname);
xfree(fname);
return rc;
}
static void
do_hash( MD_HANDLE md, MD_HANDLE md2, iobuf_t fp, int textmode )
do_hash( gcry_md_hd_t md, gcry_md_hd_t md2, IOBUF fp, int textmode )
{
text_filter_context_t tfx;
int c;
@ -365,12 +438,12 @@ do_hash( MD_HANDLE md, MD_HANDLE md2, iobuf_t fp, int textmode )
* INFILE is the name of the input file.
*/
int
ask_for_detached_datafile( MD_HANDLE md, MD_HANDLE md2,
ask_for_detached_datafile (gcry_md_hd_t md, gcry_md_hd_t md2,
const char *inname, int textmode )
{
progress_filter_context_t pfx;
char *answer = NULL;
iobuf_t fp;
IOBUF fp;
int rc = 0;
fp = open_sigfile( inname, &pfx ); /* open default file */
@ -379,24 +452,37 @@ ask_for_detached_datafile( MD_HANDLE md, MD_HANDLE md2,
int any=0;
tty_printf(_("Detached signature.\n"));
do {
xfree (answer);
answer = cpr_get("detached_signature.filename",
char *name;
xfree(answer);
tty_enable_completion(NULL);
name = cpr_get("detached_signature.filename",
_("Please enter name of data file: "));
tty_disable_completion();
cpr_kill_prompt();
answer=make_filename(name,(void *)NULL);
xfree(name);
if( any && !*answer ) {
rc = GPG_ERR_GENERAL;
rc = gpg_error (GPG_ERR_GENERAL); /*G10ERR_READ_FILE*/
goto leave;
}
fp = iobuf_open(answer);
if (fp && is_secured_file (iobuf_get_fd (fp)))
{
iobuf_close (fp);
fp = NULL;
errno = EPERM;
}
if( !fp && errno == ENOENT ) {
tty_printf("No such file, try again or hit enter to quit.\n");
any++;
}
else if( !fp ) {
rc = gpg_error_from_errno (errno);
log_error("can't open `%s': %s\n", answer, strerror(errno) );
else if( !fp )
{
log_error(_("can't open `%s': %s\n"), answer, strerror(errno));
rc = G10ERR_READ_FILE;
goto leave;
}
}
} while( !fp );
}
@ -410,7 +496,7 @@ ask_for_detached_datafile( MD_HANDLE md, MD_HANDLE md2,
iobuf_close(fp);
leave:
xfree (answer);
xfree(answer);
return rc;
}
@ -421,11 +507,11 @@ ask_for_detached_datafile( MD_HANDLE md, MD_HANDLE md2,
* If FILES is NULL, hash stdin.
*/
int
hash_datafiles( MD_HANDLE md, MD_HANDLE md2, STRLIST files,
hash_datafiles( gcry_md_hd_t md, gcry_md_hd_t md2, STRLIST files,
const char *sigfilename, int textmode )
{
progress_filter_context_t pfx;
iobuf_t fp;
IOBUF fp;
STRLIST sl;
if( !files ) {
@ -437,17 +523,22 @@ hash_datafiles( MD_HANDLE md, MD_HANDLE md2, STRLIST files,
return 0;
}
log_error (_("no signed data\n"));
return GPG_ERR_NO_DATA;
return gpg_error (GPG_ERR_NO_DATA);
}
for (sl=files; sl; sl = sl->next ) {
fp = iobuf_open( sl->d );
if (fp && is_secured_file (iobuf_get_fd (fp)))
{
iobuf_close (fp);
fp = NULL;
errno = EPERM;
}
if( !fp ) {
int tmperr = gpg_error_from_errno (errno);
log_error(_("can't open signed data `%s'\n"),
print_fname_stdin(sl->d));
return tmperr;
return G10ERR_OPEN_FILE;
}
handle_progress (&pfx, fp, sl->d);
do_hash( md, md2, fp, textmode );

View File

@ -1,4 +1,4 @@
/* progress.c
/* progress.c - emit progress status lines
* Copyright (C) 2003 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
@ -15,7 +15,8 @@
*
* 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
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
#include <config.h>
@ -33,7 +34,7 @@
*/
int
progress_filter (void *opaque, int control,
iobuf_t a, byte *buf, size_t *ret_len)
IOBUF a, byte *buf, size_t *ret_len)
{
int rc = 0;
progress_filter_context_t *pfx = opaque;
@ -96,7 +97,7 @@ progress_filter (void *opaque, int control,
}
void
handle_progress (progress_filter_context_t *pfx, iobuf_t inp, const char *name)
handle_progress (progress_filter_context_t *pfx, IOBUF inp, const char *name)
{
off_t filesize = 0;
@ -106,8 +107,8 @@ handle_progress (progress_filter_context_t *pfx, iobuf_t inp, const char *name)
if (!is_status_enabled ())
return;
if (name && *name && !(*name == '-' && !name[1]))
filesize = iobuf_get_filelength (inp);
if ( !iobuf_is_pipe_filename (name) && *name )
filesize = iobuf_get_filelength (inp, NULL);
else if (opt.set_filesize)
filesize = opt.set_filesize;

View File

@ -1,6 +1,6 @@
/* pubkey-enc.c - public key encoded packet handling
* Copyright (C) 1998, 1999, 2000, 2001, 2002,
* 2003 Free Software Foundation, Inc.
* 2006 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -16,7 +16,8 @@
*
* 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
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
#include <config.h>
@ -27,9 +28,7 @@
#include "gpg.h"
#include "util.h"
#include "memory.h"
#include "packet.h"
#include "mpi.h"
#include "keydb.h"
#include "trustdb.h"
#include "cipher.h"
@ -38,7 +37,7 @@
#include "main.h"
#include "i18n.h"
#include "pkglue.h"
#include "call-agent.h"
static int get_it( PKT_pubkey_enc *k,
DEK *dek, PKT_secret_key *sk, u32 *keyid );
@ -77,12 +76,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, PUBKEY_USAGE_ENC);
rc = openpgp_pk_test_algo2 (k->pubkey_algo, PUBKEY_USAGE_ENC);
if( rc )
goto leave;
if( (k->keyid[0] || k->keyid[1]) && !opt.try_all_secrets ) {
sk = xcalloc (1, sizeof *sk );
sk = xmalloc_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 );
@ -95,34 +94,49 @@ get_session_key( PKT_pubkey_enc *k, DEK *dek )
for(;;) {
if( sk )
free_secret_key( sk );
sk = xcalloc (1, sizeof *sk );
sk = xmalloc_clear( sizeof *sk );
rc=enum_secret_keys( &enum_context, sk, 1, 0);
if( rc ) {
rc = GPG_ERR_NO_SECKEY;
rc = G10ERR_NO_SECKEY;
break;
}
if( sk->pubkey_algo != k->pubkey_algo )
continue;
keyid_from_sk( sk, keyid );
log_info(_("anonymous recipient; trying secret key %08lX ...\n"),
(ulong)keyid[1] );
log_info(_("anonymous recipient; trying secret key %s ...\n"),
keystr(keyid));
if(!opt.try_all_secrets && !is_status_enabled())
{
p=get_last_passphrase();
set_next_passphrase(p);
xfree (p);
xfree(p);
}
rc = check_secret_key( sk, opt.try_all_secrets?1:-1 ); /* ask
only
once */
if( !rc )
{
rc = get_it( k, dek, sk, keyid );
if( !rc ) {
/* Successfully checked the secret key (either it was
a card, had no passphrase, or had the right
passphrase) but couldn't decrypt the session key,
so thus that key is not the anonymous recipient.
Move the next passphrase into last for the next
round. We only do this if the secret key was
successfully checked as in the normal case,
check_secret_key handles this for us via
passphrase_to_dek */
if(rc)
next_to_last_passphrase();
}
if( !rc )
{
log_info(_("okay, we are the anonymous recipient.\n") );
break;
}
}
}
enum_secret_keys( &enum_context, NULL, 0, 0 ); /* free context */
}
@ -138,15 +152,17 @@ static int
get_it( PKT_pubkey_enc *enc, DEK *dek, PKT_secret_key *sk, u32 *keyid )
{
int rc;
gcry_mpi_t plain_dek = NULL;
gcry_mpi_t plain_dek = NULL;
byte *frame = NULL;
unsigned n, nframe;
u16 csum, csum2;
int card = 0;
if (sk->is_protected && sk->protect.s2k.mode == 1002)
{ /* FIXME: Note that we do only support RSA for now. */
char *rbuf;
{ /* Note, that we only support RSA for now. */
#ifdef ENABLE_CARD_SUPPORT
unsigned char *rbuf;
size_t rbuflen;
char *snbuf;
unsigned char *indata = NULL;
@ -154,9 +170,8 @@ get_it( PKT_pubkey_enc *enc, DEK *dek, PKT_secret_key *sk, u32 *keyid )
snbuf = serialno_and_fpr_from_sk (sk->protect.iv, sk->protect.ivlen, sk);
if (gcry_mpi_aprint (GCRYMPI_FMT_USG, &indata, &indatalen,
enc->data[0]))
BUG();
if (gcry_mpi_aprint (GCRYMPI_FMT_USG, &indata, &indatalen, enc->data[0]))
BUG ();
rc = agent_scd_pkdecrypt (snbuf, indata, indatalen, &rbuf, &rbuflen);
xfree (snbuf);
@ -167,148 +182,145 @@ get_it( PKT_pubkey_enc *enc, DEK *dek, PKT_secret_key *sk, u32 *keyid )
frame = rbuf;
nframe = rbuflen;
card = 1;
#else
rc = gpg_error (GPG_ERR_NOT_SUPPORTED);
goto leave;
#endif /*!ENABLE_CARD_SUPPORT*/
}
else
{
rc = pk_decrypt (sk->pubkey_algo, &plain_dek, enc->data, sk->skey);
rc = pk_decrypt (sk->pubkey_algo, &plain_dek, enc->data, sk->skey );
if( rc )
goto leave;
goto leave;
if (gcry_mpi_aprint (GCRYMPI_FMT_USG, &frame, &nframe, plain_dek))
BUG();
gcry_mpi_release (plain_dek); plain_dek = NULL;
}
/* Now get the DEK (data encryption key) from the frame
*
* Old versions encode the DEK in in this format (msb is left):
*
* 0 1 DEK(16 bytes) CSUM(2 bytes) 0 RND(n bytes) 2
*
* Later versions encode the DEK like this:
*
* 0 2 RND(n bytes) 0 A DEK(k bytes) CSUM(2 bytes)
*
* (mpi_get_buffer already removed the leading zero).
*
* RND are non-zero randow bytes.
* A is the cipher algorithm
* DEK is the encryption key (session key) with length k
* CSUM
*/
if( DBG_CIPHER )
log_printhex ("DEK frame:", frame, nframe );
n=0;
if (!card)
{
if( n + 7 > nframe )
{ rc = GPG_ERR_WRONG_SECKEY; goto leave; }
if( frame[n] == 1 && frame[nframe-1] == 2 ) {
log_info(_("old encoding of the DEK is not supported\n"));
rc = GPG_ERR_CIPHER_ALGO;
goto leave;
}
if( frame[n] != 2 ) /* somethink is wrong */
{ rc = GPG_ERR_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 = GPG_ERR_WRONG_SECKEY; goto leave; }
dek->keylen = nframe - (n+1) - 2;
dek->algo = frame[n++];
if( dek->algo == CIPHER_ALGO_IDEA )
write_status(STATUS_RSA_OR_IDEA);
rc = openpgp_cipher_test_algo (dek->algo);
if( rc ) {
if( !opt.quiet && gpg_err_code (rc) == GPG_ERR_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 = GPG_ERR_WRONG_SECKEY;
goto leave;
}
/* copy the key to DEK and compare the checksum */
csum = frame[nframe-2] << 8;
csum |= frame[nframe-1];
memcpy( dek->key, frame+n, dek->keylen );
for( csum2=0, n=0; n < dek->keylen; n++ )
csum2 += dek->key[n];
if( csum != csum2 ) {
rc = GPG_ERR_WRONG_SECKEY;
goto leave;
}
if( DBG_CIPHER )
log_printhex ("DEK is:", dek->key, dek->keylen );
/* check that the algo is in the preferences and whether it has expired */
{
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 != 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 (aki[0]==keyid[0] && aki[1]==keyid[1]) {
pk = k->pkt->pkt.public_key;
break;
}
/* Now get the DEK (data encryption key) from the frame
*
* Old versions encode the DEK in in this format (msb is left):
*
* 0 1 DEK(16 bytes) CSUM(2 bytes) 0 RND(n bytes) 2
*
* Later versions encode the DEK like this:
*
* 0 2 RND(n bytes) 0 A DEK(k bytes) CSUM(2 bytes)
*
* (mpi_get_buffer already removed the leading zero).
*
* RND are non-zero randow bytes.
* A is the cipher algorithm
* DEK is the encryption key (session key) with length k
* CSUM
*/
if( DBG_CIPHER )
log_hexdump("DEK frame:", frame, nframe );
n=0;
if (!card)
{
if( n + 7 > nframe )
{ 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 = G10ERR_CIPHER_ALGO;
goto leave;
}
if( frame[n] != 2 ) /* somethink is wrong */
{ rc = G10ERR_WRONG_SECKEY; goto leave; }
for(n++; n < nframe && frame[n]; n++ ) /* skip the random bytes */
;
n++; /* and the zero byte */
}
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) );
}
if( n + 4 > nframe )
{ rc = G10ERR_WRONG_SECKEY; goto leave; }
dek->keylen = nframe - (n+1) - 2;
dek->algo = frame[n++];
if( dek->algo == CIPHER_ALGO_IDEA )
write_status(STATUS_RSA_OR_IDEA);
rc = openpgp_cipher_test_algo (dek->algo);
if( rc ) {
if( !opt.quiet && gpg_err_code (rc) == GPG_ERR_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 = GPG_ERR_WRONG_SECKEY;
goto leave;
}
if ( pk && pk->is_revoked ) {
log_info( _("NOTE: key has been revoked") );
putc( '\n', log_get_stream() );
show_revocation_reason( pk, 1 );
/* copy the key to DEK and compare the checksum */
csum = frame[nframe-2] << 8;
csum |= frame[nframe-1];
memcpy( dek->key, frame+n, dek->keylen );
for( csum2=0, n=0; n < dek->keylen; n++ )
csum2 += dek->key[n];
if( csum != csum2 ) {
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 = 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
&& !opt.quiet
&& !is_algo_in_prefs( pkb, PREFTYPE_SYM, dek->algo ))
log_info (_("WARNING: cipher algorithm %s not found in recipient"
" preferences\n"), gcry_cipher_algo_name (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 (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 %s expired at %s\n"),
keystr(keyid), asctimestamp( pk->expiredate) );
}
}
if ( pk && pk->is_revoked ) {
log_info( _("NOTE: key has been revoked") );
putc( '\n', log_get_stream() );
show_revocation_reason( pk, 1 );
}
release_kbnode (pkb);
rc = 0;
}
release_kbnode (pkb);
rc = 0;
}
leave:
gcry_mpi_release (plain_dek);
xfree (frame);
return rc;
leave:
gcry_mpi_release (plain_dek);
xfree (frame);
return rc;
}
@ -324,21 +336,21 @@ get_override_session_key( DEK *dek, const char *string )
int i;
if ( !string )
return GPG_ERR_BAD_KEY;
return G10ERR_BAD_KEY;
dek->algo = atoi(string);
if ( dek->algo < 1 )
return GPG_ERR_BAD_KEY;
return G10ERR_BAD_KEY;
if ( !(s = strchr ( string, ':' )) )
return GPG_ERR_BAD_KEY;
return G10ERR_BAD_KEY;
s++;
for(i=0; i < DIM(dek->key) && *s; i++, s +=2 ) {
int c = hextobyte ( s );
if (c == -1)
return GPG_ERR_BAD_KEY;
return G10ERR_BAD_KEY;
dek->key[i] = c;
}
if ( *s )
return GPG_ERR_BAD_KEY;
return G10ERR_BAD_KEY;
dek->keylen = i;
return 0;
}

View File

@ -1,5 +1,6 @@
/* revoke.c
* Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003,
* 2004 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -15,7 +16,8 @@
*
* 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
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
#include <config.h>
@ -26,11 +28,11 @@
#include <assert.h>
#include <ctype.h>
#include "gpg.h"
#include "options.h"
#include "packet.h"
#include "errors.h"
#include "keydb.h"
#include "memory.h"
#include "util.h"
#include "main.h"
#include "ttyio.h"
@ -59,15 +61,15 @@ revocation_reason_build_cb( PKT_signature *sig, void *opaque )
ud = native_to_utf8( reason->desc );
buflen += strlen(ud);
}
buffer = xmalloc ( buflen );
buffer = xmalloc( buflen );
*buffer = reason->code;
if( ud ) {
memcpy(buffer+1, ud, strlen(ud) );
xfree ( ud );
xfree( ud );
}
build_sig_subpkt( sig, SIGSUBPKT_REVOC_REASON, buffer, buflen );
xfree ( buffer );
xfree( buffer );
return 0;
}
@ -76,7 +78,7 @@ revocation_reason_build_cb( PKT_signature *sig, void *opaque )
and pick a user ID that has a uid signature, and include it if
possible. */
static int
export_minimal_pk(iobuf_t out,KBNODE keyblock,
export_minimal_pk(IOBUF out,KBNODE keyblock,
PKT_signature *revsig,PKT_signature *revkey)
{
KBNODE node;
@ -89,8 +91,8 @@ export_minimal_pk(iobuf_t out,KBNODE keyblock,
node=find_kbnode(keyblock,PKT_PUBLIC_KEY);
if(!node)
{
log_error(_("key incomplete\n"));
return GPG_ERR_GENERAL;
log_error("key incomplete\n");
return G10ERR_GENERAL;
}
keyid_from_pk(node->pkt->pkt.public_key,keyid);
@ -99,7 +101,7 @@ export_minimal_pk(iobuf_t out,KBNODE keyblock,
rc=build_packet(out,&pkt);
if(rc)
{
log_error(_("build_packet failed: %s\n"), gpg_strerror (rc) );
log_error(_("build_packet failed: %s\n"), g10_errstr(rc) );
return rc;
}
@ -113,7 +115,7 @@ export_minimal_pk(iobuf_t out,KBNODE keyblock,
rc=build_packet(out,&pkt);
if(rc)
{
log_error(_("build_packet failed: %s\n"), gpg_strerror (rc) );
log_error(_("build_packet failed: %s\n"), g10_errstr(rc) );
return rc;
}
}
@ -125,7 +127,7 @@ export_minimal_pk(iobuf_t out,KBNODE keyblock,
rc=build_packet(out,&pkt);
if(rc)
{
log_error(_("build_packet failed: %s\n"), gpg_strerror (rc) );
log_error(_("build_packet failed: %s\n"), g10_errstr(rc) );
return rc;
}
}
@ -142,8 +144,8 @@ export_minimal_pk(iobuf_t out,KBNODE keyblock,
break;
else
{
log_error(_("key %08lX incomplete\n"),(ulong)keyid[1]);
return GPG_ERR_GENERAL;
log_error(_("key %s has no user IDs\n"),keystr(keyid));
return G10ERR_GENERAL;
}
}
@ -171,7 +173,7 @@ export_minimal_pk(iobuf_t out,KBNODE keyblock,
rc=build_packet(out,&pkt);
if(rc)
{
log_error(_("build_packet failed: %s\n"), gpg_strerror (rc) );
log_error(_("build_packet failed: %s\n"), g10_errstr(rc) );
return rc;
}
@ -183,7 +185,7 @@ export_minimal_pk(iobuf_t out,KBNODE keyblock,
rc=build_packet(out,&pkt);
if(rc)
{
log_error(_("build_packet failed: %s\n"), gpg_strerror (rc) );
log_error(_("build_packet failed: %s\n"), g10_errstr(rc) );
return rc;
}
}
@ -195,39 +197,41 @@ export_minimal_pk(iobuf_t out,KBNODE keyblock,
* Generate a revocation certificate for UNAME via a designated revoker
*/
int
gen_desig_revoke( const char *uname )
gen_desig_revoke( const char *uname, STRLIST locusr )
{
int rc = 0;
armor_filter_context_t afx;
PKT_public_key *pk = NULL;
PKT_secret_key *sk = NULL;
PKT_signature *sig = NULL;
iobuf_t out = 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;
SK_LIST sk_list=NULL;
if( opt.batch ) {
log_error(_("sorry, can't do this in batch mode\n"));
return GPG_ERR_GENERAL;
}
if( opt.batch )
{
log_error(_("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) : GPG_ERR_INV_USER_ID;
rc = desc.mode? keydb_search (kdbhd, &desc, 1) : G10ERR_INV_USER_ID;
if (rc) {
log_error (_("key `%s' not found: %s\n"),uname, gpg_strerror (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"), gpg_strerror (rc) );
log_error (_("error reading keyblock: %s\n"), g10_errstr(rc) );
goto leave;
}
@ -243,6 +247,13 @@ gen_desig_revoke( const char *uname )
keyid_from_pk(pk,keyid);
if(locusr)
{
rc=build_sk_list(locusr,&sk_list,0,PUBKEY_USAGE_CERT);
if(rc)
goto leave;
}
/* Are we a designated revoker for this key? */
if(!pk->revkey && pk->numrevkeys)
@ -250,12 +261,39 @@ gen_desig_revoke( const char *uname )
for(i=0;i<pk->numrevkeys;i++)
{
SK_LIST list;
if(sk)
free_secret_key(sk);
sk=xcalloc (1,sizeof(*sk));
if(sk_list)
{
for(list=sk_list;list;list=list->next)
{
byte fpr[MAX_FINGERPRINT_LEN];
size_t fprlen;
rc=get_seckey_byfprint(sk,pk->revkey[i].fpr,MAX_FINGERPRINT_LEN);
fingerprint_from_sk(list->sk,fpr,&fprlen);
/* Don't get involved with keys that don't have 160
bit fingerprints */
if(fprlen!=20)
continue;
if(memcmp(fpr,pk->revkey[i].fpr,20)==0)
break;
}
if(list)
sk=copy_secret_key(NULL,list->sk);
else
continue;
}
else
{
sk=xmalloc_secure_clear(sizeof(*sk));
rc=get_seckey_byfprint(sk,pk->revkey[i].fpr,MAX_FINGERPRINT_LEN);
}
/* We have the revocation key */
if(!rc)
@ -275,7 +313,7 @@ gen_desig_revoke( const char *uname )
tty_printf("\n");
if( !cpr_get_answer_is_yes("gen_desig_revoke.okay",
_("Create a revocation certificate for this key? ")) )
_("Create a designated revocation certificate for this key? (y/N) ")))
continue;
/* get the reason for the revocation (this is always v4) */
@ -294,7 +332,8 @@ gen_desig_revoke( const char *uname )
goto leave;
afx.what = 1;
afx.hdrlines = "Comment: A revocation certificate should follow\n";
afx.hdrlines = "Comment: A designated revocation certificate"
" should follow\n";
iobuf_push_filter( out, armor_filter, &afx );
/* create it */
@ -302,7 +341,7 @@ gen_desig_revoke( const char *uname )
0, 0, 0,
revocation_reason_build_cb, reason );
if( rc ) {
log_error(_("make_keysig_packet failed: %s\n"), gpg_strerror (rc));
log_error(_("make_keysig_packet failed: %s\n"), g10_errstr(rc));
goto leave;
}
@ -371,7 +410,7 @@ gen_desig_revoke( const char *uname )
}
if(!any)
log_error(_("no revocation keys found for `%s'\n"),uname);
log_error(_("no revocation keys found for \"%s\"\n"),uname);
leave:
if( pk )
@ -381,6 +420,8 @@ gen_desig_revoke( const char *uname )
if( sig )
free_seckey_enc( sig );
release_sk_list(sk_list);
if( rc )
iobuf_cancel(out);
else
@ -403,17 +444,18 @@ gen_revoke( const char *uname )
PKT_public_key *pk = NULL;
PKT_signature *sig = NULL;
u32 sk_keyid[2];
iobuf_t out = NULL;
IOBUF out = NULL;
KBNODE keyblock = NULL, pub_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 GPG_ERR_GENERAL;
}
if( opt.batch )
{
log_error(_("can't do this in batch mode\n"));
return G10ERR_GENERAL;
}
memset( &afx, 0, sizeof afx);
init_packet( &pkt );
@ -423,16 +465,17 @@ gen_revoke( const char *uname )
*/
kdbhd = keydb_new (1);
classify_user_id (uname, &desc);
rc = desc.mode? keydb_search (kdbhd, &desc, 1) : GPG_ERR_INV_USER_ID;
if (rc) {
log_error (_("secret key `%s' not found: %s\n"),
uname, gpg_strerror (rc));
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;
}
}
rc = keydb_get_keyblock (kdbhd, &keyblock );
if( rc ) {
log_error (_("error reading keyblock: %s\n"), gpg_strerror (rc) );
log_error (_("error reading keyblock: %s\n"), g10_errstr(rc) );
goto leave;
}
@ -447,14 +490,14 @@ gen_revoke( const char *uname )
keyid_from_sk( sk, sk_keyid );
print_seckey_info (sk);
pk = xcalloc (1, sizeof *pk );
pk = xmalloc_clear( sizeof *pk );
/* FIXME: We should get the public key direct from the secret one */
pub_keyblock=get_pubkeyblock(sk_keyid);
if(!pub_keyblock)
{
log_error(_("no corresponding public key: %s\n"), gpg_strerror (rc) );
log_error(_("no corresponding public key: %s\n"), g10_errstr(rc) );
goto leave;
}
@ -466,16 +509,17 @@ gen_revoke( const char *uname )
if( cmp_public_secret_key( pk, sk ) ) {
log_error(_("public key does not match secret key!\n") );
rc = GPG_ERR_GENERAL;
rc = G10ERR_GENERAL;
goto leave;
}
tty_printf("\n");
if( !cpr_get_answer_is_yes("gen_revoke.okay",
_("Create a revocation certificate for this key? ")) ){
_("Create a revocation certificate for this key? (y/N) ")) )
{
rc = 0;
goto leave;
}
}
if(sk->version>=4 || opt.force_v4_certs) {
/* get the reason for the revocation */
@ -489,13 +533,17 @@ gen_revoke( const char *uname )
switch( is_secret_key_protected( sk ) ) {
case -1:
log_error(_("unknown protection algorithm\n"));
rc = GPG_ERR_PUBKEY_ALGO;
rc = G10ERR_PUBKEY_ALGO;
break;
case -3:
tty_printf (_("Secret parts of primary key are not available.\n"));
rc = G10ERR_NO_SECKEY;
break;
case 0:
tty_printf(_("NOTE: This key is not protected!\n"));
break;
default:
rc = check_secret_key( sk, 0 );
rc = check_secret_key( sk, 0 );
break;
}
if( rc )
@ -517,7 +565,7 @@ gen_revoke( const char *uname )
opt.force_v4_certs?4:0, 0, 0,
revocation_reason_build_cb, reason );
if( rc ) {
log_error(_("make_keysig_packet failed: %s\n"), gpg_strerror (rc));
log_error(_("make_keysig_packet failed: %s\n"), g10_errstr(rc));
goto leave;
}
@ -537,7 +585,7 @@ gen_revoke( const char *uname )
rc = build_packet( out, &pkt );
if( rc ) {
log_error(_("build_packet failed: %s\n"), gpg_strerror (rc) );
log_error(_("build_packet failed: %s\n"), g10_errstr(rc) );
goto leave;
}
}
@ -581,7 +629,7 @@ ask_revocation_reason( int key_rev, int cert_rev, int hint )
do {
code=-1;
xfree (description);
xfree(description);
description = NULL;
tty_printf(_("Please select the reason for the revocation:\n"));
@ -612,7 +660,7 @@ ask_revocation_reason( int key_rev, int cert_rev, int hint )
n = -1;
else
n = atoi(answer);
xfree (answer);
xfree(answer);
if( n == 0 ) {
code = 0x00; /* no particular reason */
code_text = text_0;
@ -644,25 +692,25 @@ ask_revocation_reason( int key_rev, int cert_rev, int hint )
trim_trailing_ws( answer, strlen(answer) );
cpr_kill_prompt();
if( !*answer ) {
xfree (answer);
xfree(answer);
break;
}
{
char *p = make_printable_string( answer, strlen(answer), 0 );
xfree (answer);
xfree(answer);
answer = p;
}
if( !description )
description = xstrdup (answer);
description = xstrdup(answer);
else {
char *p = xmalloc ( strlen(description) + strlen(answer) + 2 );
char *p = xmalloc( strlen(description) + strlen(answer) + 2 );
strcpy(stpcpy(stpcpy( p, description),"\n"),answer);
xfree (description);
xfree(description);
description = p;
}
xfree (answer);
xfree(answer);
}
tty_printf(_("Reason for revocation: %s\n"), code_text );
@ -672,9 +720,9 @@ ask_revocation_reason( int key_rev, int cert_rev, int hint )
tty_printf("%s\n", description );
} while( !cpr_get_answer_is_yes("ask_revocation_reason.okay",
_("Is this okay? ")) );
_("Is this okay? (y/N) ")) );
reason = xmalloc ( sizeof *reason );
reason = xmalloc( sizeof *reason );
reason->code = code;
reason->desc = description;
return reason;
@ -684,7 +732,7 @@ void
release_revocation_reason_info( struct revocation_reason_info *reason )
{
if( reason ) {
xfree ( reason->desc );
xfree ( reason );
xfree( reason->desc );
xfree( reason );
}
}

View File

@ -1,6 +1,6 @@
/* seckey-cert.c - secret key certificate packet handling
* Copyright (C) 1998, 1999, 2000, 2001, 2002,
* 2003 Free Software Foundation, Inc.
* 2006 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -16,7 +16,8 @@
*
* 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
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
#include <config.h>
@ -27,9 +28,7 @@
#include "gpg.h"
#include "util.h"
#include "memory.h"
#include "packet.h"
#include "mpi.h"
#include "keydb.h"
#include "cipher.h"
#include "main.h"
@ -42,21 +41,21 @@ static int
do_check( PKT_secret_key *sk, const char *tryagain_text, int mode,
int *canceled )
{
gpg_error_t err;
byte *buffer;
u16 csum=0;
int i, res;
unsigned nbytes;
gpg_error_t rc;
unsigned int nbytes;
if( sk->is_protected ) { /* remove the protection */
DEK *dek = NULL;
u32 keyid[4]; /* 4! because we need two of them */
CIPHER_HANDLE cipher_hd=NULL;
gcry_cipher_hd_t cipher_hd=NULL;
PKT_secret_key *save_sk;
if( sk->protect.s2k.mode == 1001 ) {
log_info(_("secret key parts are not available\n"));
return GPG_ERR_GENERAL;
return G10ERR_GENERAL;
}
if( sk->protect.algo == CIPHER_ALGO_NONE )
BUG();
@ -68,8 +67,14 @@ do_check( PKT_secret_key *sk, const char *tryagain_text, int mode,
write_status (STATUS_RSA_OR_IDEA);
idea_cipher_warn (0);
}
return GPG_ERR_CIPHER_ALGO;
return G10ERR_CIPHER_ALGO;
}
if(gcry_md_test_algo (sk->protect.s2k.hash_algo))
{
log_info(_("protection digest %d is not supported\n"),
sk->protect.s2k.hash_algo);
return G10ERR_DIGEST_ALGO;
}
keyid_from_sk( sk, keyid );
keyid[2] = keyid[3] = 0;
if( !sk->is_primary ) {
@ -80,39 +85,45 @@ do_check( PKT_secret_key *sk, const char *tryagain_text, int mode,
&sk->protect.s2k, mode,
tryagain_text, canceled );
if (!dek && canceled && *canceled)
return GPG_ERR_GENERAL;
return G10ERR_GENERAL;
rc = gcry_cipher_open (&cipher_hd, sk->protect.algo,
GCRY_CIPHER_MODE_CFB,
GCRY_CIPHER_SECURE
| (sk->protect.algo >= 100 ?
0 : GCRY_CIPHER_ENABLE_SYNC));
if (rc)
log_fatal ("cipher open failed: %s\n", gpg_strerror (rc) );
rc = gcry_cipher_setkey (cipher_hd, dek->key, dek->keylen);
if (rc)
log_fatal ("set key failed: %s\n", gpg_strerror (rc) );
err = gcry_cipher_open (&cipher_hd, sk->protect.algo,
GCRY_CIPHER_MODE_CFB,
(GCRY_CIPHER_SECURE
| (sk->protect.algo >= 100 ?
0 : GCRY_CIPHER_ENABLE_SYNC)));
if (err)
log_fatal ("cipher open failed: %s\n", gpg_strerror (err) );
xfree (dek);
err = gcry_cipher_setkey (cipher_hd, dek->key, dek->keylen);
if (err)
log_fatal ("set key failed: %s\n", gpg_strerror (err) );
xfree(dek);
save_sk = copy_secret_key( NULL, sk );
gcry_cipher_setiv (cipher_hd, sk->protect.iv, sk->protect.ivlen);
gcry_cipher_setiv ( cipher_hd, sk->protect.iv, sk->protect.ivlen );
csum = 0;
if( sk->version >= 4 ) {
int ndata;
unsigned int ndatabits;
int ndata;
unsigned int ndatabits;
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 );
assert ( gcry_mpi_get_flag (sk->skey[i], GCRYMPI_FLAG_OPAQUE ));
p = gcry_mpi_get_opaque ( sk->skey[i], &ndatabits );
ndata = (ndatabits+7)/8;
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 );
gcry_mpi_release ( sk->skey[i] ); sk->skey[i] = NULL ;
data = xmalloc_secure ( ndata );
gcry_cipher_decrypt ( cipher_hd, data, ndata, p, ndata );
gcry_mpi_release (sk->skey[i]); sk->skey[i] = NULL ;
p = data;
if (sk->protect.sha1chk) {
/* This is the new SHA1 checksum method to detect
@ -126,18 +137,19 @@ do_check( PKT_secret_key *sk, const char *tryagain_text, int mode,
gcry_md_hd_t h;
if ( gcry_md_open (&h, DIGEST_ALGO_SHA1, 1))
BUG(); /* algo not available */
BUG(); /* Algo not available. */
gcry_md_write (h, data, ndata - 20);
gcry_md_final (h);
if (!memcmp (gcry_md_read (h, DIGEST_ALGO_SHA1),
data + ndata - 20, 20) ) {
/* digest does match. We have to keep the old
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);
}
}
gcry_md_close (h);
}
}
@ -156,24 +168,27 @@ do_check( PKT_secret_key *sk, const char *tryagain_text, int mode,
}
}
}
/* must check it here otherwise the mpi_read_xx would fail
/* 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++ ) {
assert( gcry_is_secure( p ) );
res = gcry_mpi_scan( &sk->skey[i], GCRYMPI_FMT_PGP,
p, ndata, &nbytes);
if( res )
log_bug ("gcry_mpi_scan failed in do_check: %s\n",
gpg_strerror (res));
if ( gcry_mpi_scan( &sk->skey[i], GCRYMPI_FMT_PGP,
p, ndata, &nbytes))
{
/* Checksum was okay, but not correctly
decrypted. */
sk->csum = 0;
csum = 1;
break;
}
ndata -= nbytes;
p += nbytes;
}
/* Note: at this point ndata should be 2 for a simple
checksum or 20 for the sha1 digest */
}
xfree (data);
xfree(data);
}
else {
for(i=pubkey_get_npkey(sk->pubkey_algo);
@ -182,12 +197,12 @@ do_check( PKT_secret_key *sk, const char *tryagain_text, int mode,
int ndata;
unsigned int ndatabits;
assert( gcry_mpi_get_flag (sk->skey[i], GCRYMPI_FLAG_OPAQUE));
p = gcry_mpi_get_opaque( sk->skey[i], &ndatabits );
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 (ndata >= 2);
assert (ndata == ((p[0] << 8 | p[1]) + 7)/8 + 2);
buffer = gcry_xmalloc_secure (ndata);
buffer = xmalloc_secure (ndata);
gcry_cipher_sync (cipher_hd);
buffer[0] = p[0];
buffer[1] = p[1];
@ -195,33 +210,39 @@ do_check( PKT_secret_key *sk, const char *tryagain_text, int mode,
p+2, ndata-2);
csum += checksum (buffer, ndata);
gcry_mpi_release (sk->skey[i]);
res = gcry_mpi_scan( &sk->skey[i], GCRYMPI_FMT_USG,
buffer, ndata, &ndata );
if( res )
log_bug ("gcry_mpi_scan failed in do_check: %s\n",
gpg_strerror (res));
assert (sk->skey[i]);
err = gcry_mpi_scan( &sk->skey[i], GCRYMPI_FMT_USG,
buffer, ndata, &ndata );
xfree (buffer);
if (err)
{
/* Checksum was okay, but not correctly
decrypted. */
sk->csum = 0;
csum = 1;
break;
}
/* csum += checksum_mpi (sk->skey[i]); */
}
}
gcry_cipher_close (cipher_hd);
/* now let's see whether we have used the right passphrase */
gcry_cipher_close ( cipher_hd );
/* Now let's see whether we have used the correct passphrase. */
if( csum != sk->csum ) {
copy_secret_key( sk, save_sk );
passphrase_clear_cache ( keyid, sk->pubkey_algo );
passphrase_clear_cache ( keyid, NULL, sk->pubkey_algo );
free_secret_key( save_sk );
return gpg_error (GPG_ERR_BAD_PASSPHRASE);
return G10ERR_BAD_PASS;
}
/* The checksum may fail, so we also check the key itself. */
res = pk_check_secret_key ( sk->pubkey_algo, sk->skey );
if( res ) {
copy_secret_key( sk, save_sk );
passphrase_clear_cache ( keyid, NULL, sk->pubkey_algo );
free_secret_key( save_sk );
return G10ERR_BAD_PASS;
}
/* the checksum may fail, so we also check the key itself */
res = pk_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 gpg_error (GPG_ERR_BAD_PASSPHRASE);
}
free_secret_key( save_sk );
sk->is_protected = 0;
}
@ -232,7 +253,7 @@ do_check( PKT_secret_key *sk, const char *tryagain_text, int mode,
csum += checksum_mpi( sk->skey[i] );
}
if( csum != sk->csum )
return GPG_ERR_CHECKSUM;
return G10ERR_CHECKSUM;
}
return 0;
@ -252,7 +273,7 @@ check_secret_key( PKT_secret_key *sk, int n )
int i,mode;
if (sk && sk->is_protected && sk->protect.s2k.mode == 1002)
return 0; /* Let the scdaemon handle it. */
return 0; /* Let the scdaemon handle this. */
if(n<0)
{
@ -265,7 +286,7 @@ check_secret_key( PKT_secret_key *sk, int n )
if( n < 1 )
n = (opt.batch && !opt.use_agent)? 1 : 3; /* use the default value */
for(i=0; i < n && gpg_err_code (rc) == GPG_ERR_BAD_PASSPHRASE; i++ ) {
for(i=0; i < n && gpg_err_code (rc) == G10ERR_BAD_PASS; i++ ) {
int canceled = 0;
const char *tryagain = NULL;
if (i) {
@ -273,8 +294,7 @@ check_secret_key( PKT_secret_key *sk, int n )
log_info (_("%s ...\n"), _(tryagain));
}
rc = do_check( sk, tryagain, mode, &canceled );
if( gpg_err_code (rc) == GPG_ERR_BAD_PASSPHRASE
&& is_status_enabled() ) {
if ( gpg_err_code (rc) == G10ERR_BAD_PASS && is_status_enabled () ) {
u32 kid[2];
char buf[50];
@ -296,13 +316,14 @@ check_secret_key( PKT_secret_key *sk, int n )
* check whether the secret key is protected.
* Returns: 0 not protected, -1 on error or the protection algorithm
* -2 indicates a card stub.
* -3 indicates a not-online stub.
*/
int
is_secret_key_protected( PKT_secret_key *sk )
{
return sk->is_protected?
sk->protect.s2k.mode == 1002? -2
: sk->protect.algo : 0;
sk->protect.s2k.mode == 1002? -2 :
sk->protect.s2k.mode == 1001? -3 : sk->protect.algo : 0;
}
@ -324,54 +345,52 @@ protect_secret_key( PKT_secret_key *sk, DEK *dek )
if( !sk->is_protected ) { /* okay, apply the protection */
gcry_cipher_hd_t cipher_hd=NULL;
if( openpgp_cipher_test_algo( sk->protect.algo ) )
{
rc = gpg_error (GPG_ERR_CIPHER_ALGO); /* unsupport
protection
algorithm */
}
if ( openpgp_cipher_test_algo ( sk->protect.algo ) ) {
/* Unsupport protection algorithm. */
rc = gpg_error (GPG_ERR_CIPHER_ALGO);
}
else {
print_cipher_algo_note( sk->protect.algo );
rc = gcry_cipher_open (&cipher_hd, sk->protect.algo,
if ( gcry_cipher_open (&cipher_hd, sk->protect.algo,
GCRY_CIPHER_MODE_CFB,
GCRY_CIPHER_SECURE
| (sk->protect.algo >= 100 ?
0 : GCRY_CIPHER_ENABLE_SYNC) );
if (rc)
(GCRY_CIPHER_SECURE
| (sk->protect.algo >= 100 ?
0 : GCRY_CIPHER_ENABLE_SYNC))) )
BUG();
if( gcry_cipher_setkey( cipher_hd, dek->key, dek->keylen ) )
if ( gcry_cipher_setkey ( cipher_hd, dek->key, dek->keylen ) )
log_info(_("WARNING: Weak key detected"
" - please change passphrase again.\n"));
sk->protect.ivlen = gcry_cipher_get_algo_blklen(sk->protect.algo);
sk->protect.ivlen = gcry_cipher_get_algo_blklen (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 */
gcry_create_nonce (sk->protect.iv, sk->protect.ivlen);
gcry_cipher_setiv( cipher_hd, sk->protect.iv, sk->protect.ivlen );
gcry_cipher_setiv (cipher_hd, sk->protect.iv, sk->protect.ivlen);
if( sk->version >= 4 ) {
unsigned char *bufarr[PUBKEY_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, bufarr+j,
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, bufarr+j,
narr+j, sk->skey[i]))
BUG();
nbits[j] = gcry_mpi_get_nbits( sk->skey[i] );
BUG();
nbits[j] = gcry_mpi_get_nbits (sk->skey[i]);
ndata += narr[j] + 2;
}
for( ; j < PUBKEY_MAX_NSKEY; j++ )
bufarr[j] = NULL;
}
for ( ; j < PUBKEY_MAX_NSKEY; j++ )
bufarr[j] = NULL;
ndata += opt.simple_sk_checksum? 2 : 20; /* for checksum */
data = xmalloc_secure ( ndata );
data = xmalloc_secure( ndata );
p = data;
for(j=0; j < PUBKEY_MAX_NSKEY && bufarr[j]; j++ ) {
p[0] = nbits[j] >> 8 ;
@ -379,7 +398,7 @@ protect_secret_key( PKT_secret_key *sk, DEK *dek )
p += 2;
memcpy(p, bufarr[j], narr[j] );
p += narr[j];
xfree (bufarr[j]);
xfree(bufarr[j]);
}
if (opt.simple_sk_checksum) {
@ -395,10 +414,10 @@ protect_secret_key( PKT_secret_key *sk, DEK *dek )
gcry_md_hd_t h;
if (gcry_md_open (&h, GCRY_MD_SHA1, 1))
BUG(); /* algo not available */
BUG(); /* Algo not available. */
gcry_md_write (h, data, ndata - 20);
gcry_md_final (h);
memcpy (p, gcry_md_read (h, GCRY_MD_SHA1), 20);
memcpy (p, gcry_md_read (h, DIGEST_ALGO_SHA1), 20);
p += 20;
gcry_md_close (h);
sk->csum = csum = 0;
@ -406,14 +425,15 @@ protect_secret_key( PKT_secret_key *sk, DEK *dek )
}
assert( p == data+ndata );
gcry_cipher_encrypt( cipher_hd, data, ndata, NULL, 0 );
for(i = pubkey_get_npkey(sk->pubkey_algo);
i < pubkey_get_nskey(sk->pubkey_algo); i++ ) {
gcry_mpi_release ( sk->skey[i] );
gcry_cipher_encrypt (cipher_hd, data, ndata, NULL, 0);
for (i = pubkey_get_npkey(sk->pubkey_algo);
i < pubkey_get_nskey(sk->pubkey_algo); i++ )
{
gcry_mpi_release (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] = gcry_mpi_set_opaque (NULL, data, ndata*8 );
}
else {
csum = 0;
@ -423,30 +443,33 @@ protect_secret_key( PKT_secret_key *sk, DEK *dek )
unsigned int nbits;
csum += checksum_mpi (sk->skey[i]);
if( gcry_mpi_aprint( GCRYMPI_FMT_USG, &buffer,
&nbytes, sk->skey[i] ) )
BUG();
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 ));
data = xmalloc (nbytes+2);
nbits = gcry_mpi_get_nbits (sk->skey[i]);
assert (!gcry_mpi_get_flag (sk->skey[i],
GCRYMPI_FLAG_OPAQUE));
data = xmalloc (nbytes+2); /* fixme: need xtrymalloc. */
nbits = gcry_mpi_get_nbits (sk->skey[i]);
assert (nbytes == (nbits + 7)/8);
data[0] = nbits >> 8;
data[1] = nbits;
gcry_cipher_encrypt (cipher_hd, data+2, nbytes,
buffer, nbytes);
xfree ( buffer );
xfree( buffer );
gcry_mpi_release (sk->skey[i]);
sk->skey[i] = gcry_mpi_set_opaque (NULL, data,
(nbytes+2)*8);
sk->skey[i] = gcry_mpi_set_opaque (NULL,
data, (nbytes+2)*8 );
}
sk->csum = csum;
}
sk->is_protected = 1;
gcry_cipher_close( cipher_hd );
gcry_cipher_close (cipher_hd);
}
}
return rc;
}

View File

@ -1,5 +1,6 @@
/* seskey.c - make sesssion keys etc.
* Copyright (C) 1998, 1999, 2000, 2001, 2003 Free Software Foundation, Inc.
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004,
* 2006 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -15,7 +16,8 @@
*
* 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
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
#include <config.h>
@ -27,10 +29,9 @@
#include "gpg.h"
#include "util.h"
#include "cipher.h"
#include "mpi.h"
#include "main.h"
#include "i18n.h"
#include "options.h"
/****************
* Make a session key and put it into DEK
@ -38,35 +39,33 @@
void
make_session_key( DEK *dek )
{
gcry_cipher_hd_t chd;
int i, rc;
gcry_cipher_hd_t chd;
int i, rc;
dek->keylen = gcry_cipher_get_algo_keylen (dek->algo);
dek->keylen = gcry_cipher_get_algo_keylen (dek->algo);
if (gcry_cipher_open (&chd, dek->algo, GCRY_CIPHER_MODE_CFB,
if (gcry_cipher_open (&chd, 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 );
for (i=0; i < 16; i++ )
{
rc = gcry_cipher_setkey (chd, dek->key, dek->keylen);
if (!rc)
{
gcry_cipher_close (chd);
return;
}
if (gpg_err_code (rc) != GPG_ERR_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 );
}
log_fatal (_("cannot avoid weak key for symmetric cipher; "
"tried %d times!\n"), i);
BUG();
gcry_randomize (dek->key, dek->keylen, GCRY_STRONG_RANDOM );
for (i=0; i < 16; i++ )
{
rc = gcry_cipher_setkey (chd, dek->key, dek->keylen);
if (!rc)
{
gcry_cipher_close (chd);
return;
}
if (gpg_err_code (rc) != GPG_ERR_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);
}
log_fatal (_("cannot avoid weak key for symmetric cipher; "
"tried %d times!\n"), i);
}
@ -85,7 +84,7 @@ encode_session_key (DEK *dek, unsigned int nbits)
u16 csum;
gcry_mpi_t a;
/* the current limitation is that we can only use a session key
/* The current limitation is that we can only use a session key
* whose length is a multiple of BITS_PER_MPI_LIMB
* I think we can live with that.
*/
@ -110,14 +109,14 @@ encode_session_key (DEK *dek, unsigned int nbits)
for( p = dek->key, i=0; i < dek->keylen; i++ )
csum += *p++;
frame = gcry_xmalloc_secure ( nframe );
frame = xmalloc_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);
/* replace zero bytes by new values */
/* Replace zero bytes by new values. */
for(;;) {
int j, k;
byte *pp;
@ -128,36 +127,35 @@ encode_session_key (DEK *dek, unsigned int nbits)
k++;
if( !k )
break; /* okay: no zero bytes */
k += k/128; /* better get some more */
pp = gcry_random_bytes_secure( k, GCRY_STRONG_RANDOM);
for(j=0; j < i && k ; j++ )
k += k/128 + 3; /* better get some more */
pp = gcry_random_bytes_secure (k, GCRY_STRONG_RANDOM);
for(j=0; j < i && k ;) {
if( !p[j] )
p[j] = pp[--k];
xfree (pp);
if (p[j])
j++;
}
xfree(pp);
}
memcpy( frame+n, p, i );
xfree (p);
xfree(p);
n += i;
frame[n++] = 0;
frame[n++] = dek->algo;
memcpy( frame+n, dek->key, dek->keylen ); n += dek->keylen;
frame[n++] = csum >>8;
frame[n++] = csum;
assert (n == nframe);
if (DBG_CIPHER)
log_printhex ("encoded session key:", frame, nframe );
assert( n == nframe );
if (gcry_mpi_scan( &a, GCRYMPI_FMT_USG, frame, n, &nframe))
BUG();
xfree (frame);
xfree(frame);
return a;
}
static gcry_mpi_t
do_encode_md( gcry_md_hd_t md, int algo, size_t len, unsigned nbits,
const byte *asn, size_t asnlen, int v3compathack )
const byte *asn, size_t asnlen )
{
int nframe = (nbits+7) / 8;
byte *frame;
@ -170,14 +168,14 @@ do_encode_md( gcry_md_hd_t md, int algo, size_t len, unsigned nbits,
/* We encode the MD in this way:
*
* 0 A PAD(n bytes) 0 ASN(asnlen bytes) MD(len bytes)
* 0 1 PAD(n bytes) 0 ASN(asnlen bytes) MD(len bytes)
*
* PAD consists of FF bytes.
*/
frame = gcry_md_is_secure (md)? xmalloc_secure (nframe): xmalloc (nframe);
frame = gcry_md_is_secure (md)? xmalloc_secure (nframe) : xmalloc (nframe);
n = 0;
frame[n++] = 0;
frame[n++] = v3compathack? algo : 1; /* block type */
frame[n++] = 1; /* block type */
i = nframe - len - asnlen -3 ;
assert( i > 1 );
memset( frame+n, 0xff, i ); n += i;
@ -185,36 +183,83 @@ do_encode_md( gcry_md_hd_t md, int algo, size_t len, unsigned nbits,
memcpy( frame+n, asn, asnlen ); n += asnlen;
memcpy( frame+n, gcry_md_read (md, algo), len ); n += len;
assert( n == nframe );
if (gcry_mpi_scan( &a, GCRYMPI_FMT_USG, frame, n, &nframe ))
BUG();
xfree (frame);
xfree(frame);
/* Note that PGP before version 2.3 encoded the MD as:
*
* 0 1 MD(16 bytes) 0 PAD(n bytes) 1
*
* The MD is always 16 bytes here because it's always MD5. We do
* not support pre-v2.3 signatures, but I'm including this comment
* so the information is easily found in the future.
*/
return a;
}
/****************
* 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 flag forces the old behaviour.
* If it's for a DSA signature, make sure that the hash is large
* enough to fill up q. If the hash is too big, take the leftmost
* bits.
*/
gcry_mpi_t
encode_md_value (int pubkey_algo, gcry_md_hd_t md, int hash_algo,
unsigned int nbits, int v3compathack )
encode_md_value (PKT_public_key *pk, PKT_secret_key *sk,
gcry_md_hd_t md, int hash_algo)
{
int algo = hash_algo? hash_algo : gcry_md_get_algo (md);
gcry_mpi_t frame;
if (pubkey_algo == GCRY_PK_DSA)
assert(hash_algo);
assert(pk || sk);
if((pk?pk->pubkey_algo:sk->pubkey_algo) == GCRY_PK_DSA)
{
size_t n = gcry_md_get_algo_dlen(hash_algo);
if (n != 20)
{
log_error (_("DSA requires the use of a 160 bit hash algorithm\n"));
return NULL;
}
if (gcry_mpi_scan( &frame, GCRYMPI_FMT_USG,
gcry_md_read (md, hash_algo), n, &n ) )
/* It's a DSA signature, so find out the size of q. */
unsigned int qbytes = gcry_mpi_get_nbits (pk?pk->pkey[1]:sk->skey[1]);
size_t n;
/* Make sure it is a multiple of 8 bits. */
if(qbytes%8)
{
log_error(_("DSA requires the hash length to be a"
" multiple of 8 bits\n"));
return NULL;
}
/* Don't allow any q smaller than 160 bits. This might need a
revisit as the DSA2 design firms up, but for now, we don't
want someone to issue signatures from a key with a 16-bit q
or something like that, which would look correct but allow
trivial forgeries. Yes, I know this rules out using MD5 with
DSA. ;) */
if(qbytes<160)
{
log_error(_("DSA key %s uses an unsafe (%u bit) hash\n"),
pk?keystr_from_pk(pk):keystr_from_sk(sk),qbytes);
return NULL;
}
qbytes/=8;
/* Check if we're too short. Too long is safe as we'll
automatically left-truncate. */
if(gcry_md_get_algo_dlen (hash_algo) < qbytes)
{
log_error(_("DSA key %s requires a %u bit or larger hash\n"),
pk?keystr_from_pk(pk):keystr_from_sk(sk),qbytes*8);
return NULL;
}
if (gcry_mpi_scan (&frame, GCRYMPI_FMT_USG,
gcry_md_read (md, hash_algo), n, &n))
BUG();
}
else
@ -222,23 +267,19 @@ encode_md_value (int pubkey_algo, gcry_md_hd_t md, int hash_algo,
gpg_error_t rc;
byte *asn;
size_t asnlen;
rc = gcry_md_algo_info( algo, GCRYCTL_GET_ASNOID, NULL, &asnlen);
rc = gcry_md_algo_info (hash_algo, GCRYCTL_GET_ASNOID, NULL, &asnlen);
if (rc)
log_fatal("can't get OID of algo %d: %s\n",
algo, gpg_strerror (rc));
log_fatal ("can't get OID of algo %d: %s\n",
hash_algo, gpg_strerror (rc));
asn = xmalloc (asnlen);
if( gcry_md_algo_info( algo, GCRYCTL_GET_ASNOID, asn, &asnlen ) )
if ( gcry_md_algo_info (hash_algo, GCRYCTL_GET_ASNOID, asn, &asnlen) )
BUG();
frame = do_encode_md( md, algo, gcry_md_get_algo_dlen( algo ),
nbits, asn, asnlen, v3compathack );
frame = do_encode_md (md, hash_algo, gcry_md_get_algo_dlen (hash_algo),
gcry_mpi_get_nbits (pk?pk->pkey[0]:sk->skey[0]),
asn, asnlen);
xfree (asn);
}
return frame;
}

View File

@ -1,6 +1,6 @@
/* sig-check.c - Check a signature
* Copyright (C) 1998, 1999, 2000, 2001, 2002,
* 2003 Free Software Foundation, Inc.
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003,
* 2004, 2006 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -16,7 +16,8 @@
*
* 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
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
#include <config.h>
@ -28,8 +29,6 @@
#include "gpg.h"
#include "util.h"
#include "packet.h"
#include "memory.h"
#include "mpi.h"
#include "keydb.h"
#include "cipher.h"
#include "main.h"
@ -38,13 +37,17 @@
#include "options.h"
#include "pkglue.h"
struct cmp_help_context_s {
PKT_signature *sig;
MD_HANDLE md;
/* Context used by the compare function. */
struct cmp_help_context_s
{
PKT_signature *sig;
gcry_md_hd_t md;
};
static int do_check( PKT_public_key *pk, PKT_signature *sig, MD_HANDLE digest,
static int do_check( PKT_public_key *pk, PKT_signature *sig,
gcry_md_hd_t digest,
int *r_expired, int *r_revoked, PKT_public_key *ret_pk);
/****************
@ -53,37 +56,72 @@ static int do_check( PKT_public_key *pk, PKT_signature *sig, MD_HANDLE digest,
* is able to append some data, before finalizing the digest.
*/
int
signature_check( PKT_signature *sig, MD_HANDLE digest )
signature_check (PKT_signature *sig, gcry_md_hd_t digest)
{
return signature_check2( sig, digest, NULL, NULL, NULL, NULL );
}
int
signature_check2( PKT_signature *sig, MD_HANDLE digest, u32 *r_expiredate,
signature_check2 (PKT_signature *sig, gcry_md_hd_t digest, u32 *r_expiredate,
int *r_expired, int *r_revoked, PKT_public_key *ret_pk )
{
PKT_public_key *pk = xcalloc (1, sizeof *pk );
PKT_public_key *pk = xmalloc_clear( sizeof *pk );
int rc=0;
/* Sanity check that the md has a context for the hash that the
sig is expecting. This can happen if a onepass sig header does
not match the actual sig, and also if the clearsign "Hash:"
header is missing or does not match the actual sig. */
if ( (rc=openpgp_md_test_algo(sig->digest_algo)) )
; /* We don't have this digest. */
else if ((rc=openpgp_pk_test_algo(sig->pubkey_algo)))
; /* We don't have this pubkey algo. */
else if (!gcry_md_is_enabled (digest,sig->digest_algo))
{
/* Sanity check that the md has a context for the hash that the
sig is expecting. This can happen if a onepass sig header does
not match the actual sig, and also if the clearsign "Hash:"
header is missing or does not match the actual sig. */
if(!gcry_md_is_enabled (digest,sig->digest_algo)) {
log_info(_("WARNING: signature digest conflict in message\n"));
rc=GPG_ERR_GENERAL;
}
rc=G10ERR_GENERAL;
}
else if( get_pubkey( pk, sig->keyid ) )
rc = GPG_ERR_NO_PUBKEY;
rc = G10ERR_NO_PUBKEY;
else if(!pk->is_valid && !pk->is_primary)
rc=GPG_ERR_BAD_PUBKEY; /* you cannot have a good sig from an
rc=G10ERR_BAD_PUBKEY; /* you cannot have a good sig from an
invalid subkey */
else {
if (r_expiredate)
*r_expiredate = pk->expiredate;
else
{
if(r_expiredate)
*r_expiredate = pk->expiredate;
rc = do_check( pk, sig, digest, r_expired, r_revoked, ret_pk );
}
/* Check the backsig. This is a 0x19 signature from the
subkey on the primary key. The idea here is that it should
not be possible for someone to "steal" subkeys and claim
them as their own. The attacker couldn't actually use the
subkey, but they could try and claim ownership of any
signaures issued by it. */
if(rc==0 && !pk->is_primary && pk->backsig<2)
{
if(pk->backsig==0)
{
log_info(_("WARNING: signing subkey %s is not"
" cross-certified\n"),keystr_from_pk(pk));
log_info(_("please see %s for more information\n"),
"http://www.gnupg.org/faq/subkey-cross-certify.html");
/* --require-cross-certification makes this warning an
error. TODO: change the default to require this
after more keys have backsigs. */
if(opt.flags.require_cross_cert)
rc=G10ERR_GENERAL;
}
else if(pk->backsig==1)
{
log_info(_("WARNING: signing subkey %s has an invalid"
" cross-certification\n"),keystr_from_pk(pk));
rc=G10ERR_GENERAL;
}
}
}
free_public_key( pk );
@ -96,35 +134,38 @@ signature_check2( PKT_signature *sig, MD_HANDLE digest, u32 *r_expiredate,
* one second. Some remote batch processing applications might
* like this feature here */
gcry_md_hd_t md;
u32 a = sig->timestamp;
int i, nsig = pubkey_get_nsig( sig->pubkey_algo );
byte *p, *buffer;
gcry_md_open (&md, GCRY_MD_RMD160, 0);
if (gcry_md_open (&md, GCRY_MD_RMD160, 0))
BUG ();
/* FIXME: Why the hell are we updating DIGEST here??? */
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 );
gcry_md_putc( digest, (a >> 8) & 0xff );
gcry_md_putc( digest, a & 0xff );
for(i=0; i < nsig; i++ ) {
size_t n;
unsigned char *tmp;
if (gcry_mpi_aprint (GCRYMPI_FMT_USG, &tmp, &n, sig->data[i]))
BUG();
BUG();
gcry_md_write (md, tmp, n);
xfree (tmp);
}
gcry_md_final( md );
p = make_radix64_string( gcry_md_read( md, 0 ), 20 );
buffer = xmalloc ( strlen(p) + 60 );
gcry_md_final (md);
p = make_radix64_string ( gcry_md_read( md, 0 ), 20 );
buffer = xmalloc( strlen(p) + 60 );
sprintf( buffer, "%s %s %lu",
p, strtimestamp( sig->timestamp ), (ulong)sig->timestamp );
write_status_text( STATUS_SIG_ID, buffer );
xfree (buffer);
xfree (p);
xfree(buffer);
xfree(p);
gcry_md_close(md);
}
@ -134,58 +175,51 @@ signature_check2( PKT_signature *sig, MD_HANDLE digest, u32 *r_expiredate,
static int
do_check_messages( PKT_public_key *pk, PKT_signature *sig,
int *r_expired, int *r_revoked )
int *r_expired, int *r_revoked )
{
u32 cur_time;
if (r_expired)
if(r_expired)
*r_expired = 0;
if (r_revoked)
if(r_revoked)
*r_revoked = 0;
if( pk->version == 4 && pk->pubkey_algo == PUBKEY_ALGO_ELGAMAL_E ) {
log_info(_("key %08lX: this is a PGP generated "
"ElGamal key which is NOT secure for signatures!\n"),
(ulong)keyid_from_pk(pk,NULL));
return GPG_ERR_PUBKEY_ALGO;
}
if( pk->timestamp > sig->timestamp ) {
if( pk->timestamp > sig->timestamp )
{
ulong d = pk->timestamp - sig->timestamp;
log_info( d==1
? _("public key %08lX is %lu second newer than the signature\n")
: _("public key %08lX is %lu seconds newer than the signature\n"),
(ulong)keyid_from_pk(pk,NULL),d );
log_info(d==1
?_("public key %s is %lu second newer than the signature\n")
:_("public key %s is %lu seconds newer than the signature\n"),
keystr_from_pk(pk),d );
if( !opt.ignore_time_conflict )
return GPG_ERR_TIME_CONFLICT; /* pubkey newer than signature */
}
return G10ERR_TIME_CONFLICT; /* pubkey newer than signature */
}
cur_time = make_timestamp();
if( pk->timestamp > cur_time ) {
if( pk->timestamp > cur_time )
{
ulong d = pk->timestamp - cur_time;
log_info( d==1 ? _("key %08lX has been created %lu second "
"in future (time warp or clock problem)\n")
: _("key %08lX has been created %lu seconds "
"in future (time warp or clock problem)\n"),
(ulong)keyid_from_pk(pk,NULL),d );
log_info( d==1
? _("key %s was created %lu second"
" in the future (time warp or clock problem)\n")
: _("key %s was created %lu seconds"
" in the future (time warp or clock problem)\n"),
keystr_from_pk(pk),d );
if( !opt.ignore_time_conflict )
return GPG_ERR_TIME_CONFLICT;
}
return G10ERR_TIME_CONFLICT;
}
if( pk->expiredate && pk->expiredate < cur_time ) {
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 ) );
}
if (opt.verbose)
log_info(_("NOTE: signature key %s expired %s\n"),
keystr_from_pk(pk), asctimestamp( pk->expiredate ) );
/* SIGEXPIRED is deprecated. Use KEYEXPIRED. */
sprintf(buf,"%lu",(ulong)pk->expiredate);
write_status_text(STATUS_KEYEXPIRED,buf);
write_status(STATUS_SIGEXPIRED);
if (r_expired)
*r_expired = 1;
if(r_expired)
*r_expired = 1;
}
if(pk->is_revoked && r_revoked)
@ -196,25 +230,21 @@ do_check_messages( PKT_public_key *pk, PKT_signature *sig,
static int
do_check( PKT_public_key *pk, PKT_signature *sig, MD_HANDLE digest,
do_check( PKT_public_key *pk, PKT_signature *sig, gcry_md_hd_t digest,
int *r_expired, int *r_revoked, PKT_public_key *ret_pk )
{
gcry_mpi_t result = NULL;
int rc=0;
int rc = 0;
struct cmp_help_context_s ctx;
if( (rc=do_check_messages(pk,sig,r_expired,r_revoked)) )
return rc;
if( (rc=gcry_md_test_algo(sig->digest_algo)) )
return rc;
if( (rc=gcry_pk_test_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 );
/* Make sure the digest algo is enabled (in case of a detached
signature). */
gcry_md_enable (digest, sig->digest_algo);
/* complete the digest */
/* Complete the digest. */
if( sig->version >= 4 )
gcry_md_putc( digest, sig->version );
gcry_md_putc( digest, sig->sig_class );
@ -253,38 +283,22 @@ do_check( PKT_public_key *pk, PKT_signature *sig, MD_HANDLE digest,
buf[5] = n;
gcry_md_write( digest, buf, 6 );
}
gcry_md_final (digest);
gcry_md_final( digest );
result = encode_md_value( pk->pubkey_algo, digest, sig->digest_algo,
mpi_get_nbits(pk->pkey[0]), 0 );
result = encode_md_value( pk, NULL, digest, sig->digest_algo );
if (!result)
return GPG_ERR_GENERAL;
return G10ERR_GENERAL;
ctx.sig = sig;
ctx.md = digest;
rc = pk_verify ( pk->pubkey_algo, result, sig->data, pk->pkey);
gcry_mpi_release ( result );
if( (opt.emulate_bugs & EMUBUG_MDENCODE)
&& gpg_err_code (rc) == GPG_ERR_BAD_SIGNATURE
&& 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,
mpi_get_nbits(pk->pkey[0]), (sig->version < 5) );
if (!result)
rc = GPG_ERR_GENERAL;
else {
ctx.sig = sig;
ctx.md = digest;
rc = pk_verify (pk->pubkey_algo, result, sig->data, pk->pkey);
}
}
rc = pk_verify( pk->pubkey_algo, result, sig->data, pk->pkey );
gcry_mpi_release (result);
if( !rc && sig->flags.unknown_critical ) {
log_info(_("assuming bad signature from key %08lX "
"due to an unknown critical bit\n"),
(ulong)keyid_from_pk(pk,NULL));
rc = gpg_error (GPG_ERR_BAD_SIGNATURE);
}
if( !rc && sig->flags.unknown_critical )
{
log_info(_("assuming bad signature from key %s"
" due to an unknown critical bit\n"),keystr_from_pk(pk));
rc = G10ERR_BAD_SIGN;
}
if(!rc && ret_pk)
copy_public_key(ret_pk,pk);
@ -293,6 +307,7 @@ do_check( PKT_public_key *pk, PKT_signature *sig, MD_HANDLE digest,
}
static void
hash_uid_node( KBNODE unode, MD_HANDLE md, PKT_signature *sig )
{
@ -342,34 +357,36 @@ cache_sig_result ( PKT_signature *sig, int result )
}
}
/* Check the revocation keys to see if any of them have revoked our
pk. sig is the revocation sig. pk is the key it is on. This code
will need to be modified if gpg ever becomes multi-threaded. Note
that this guarantees that a designated revocation sig will never be
considered valid unless it is actually valid, as well as being
issued by a revocation key in a valid direct signature. Note that
this is written so that a revoked revoker can still issue
issued by a revocation key in a valid direct signature. Note also
that this is written so that a revoked revoker can still issue
revocations: i.e. If A revokes B, but A is revoked, B is still
revoked. I'm not completely convinced this is the proper behavior,
but it matches how PGP does it. -dms */
/* Returns 0 if sig is valid (i.e. pk is revoked), non-0 if not
revoked */
revoked. It is important that G10ERR_NO_PUBKEY is only returned
when a revocation signature is from a valid revocation key
designated in a revkey subpacket, but the revocation key itself
isn't present. */
int
check_revocation_keys(PKT_public_key *pk,PKT_signature *sig)
{
static int busy=0;
int i,rc=GPG_ERR_GENERAL;
int i,rc=G10ERR_GENERAL;
assert(IS_KEY_REV(sig));
assert((sig->keyid[0]!=pk->keyid[0]) || (sig->keyid[0]!=pk->keyid[1]));
if(busy)
{
/* return -1 (i.e. not revoked), but mark the pk as uncacheable
as we don't really know its revocation status until it is
checked directly. */
/* return an error (i.e. not revoked), but mark the pk as
uncacheable as we don't really know its revocation status
until it is checked directly. */
pk->dont_cache=1;
return rc;
@ -394,7 +411,8 @@ check_revocation_keys(PKT_public_key *pk,PKT_signature *sig)
{
gcry_md_hd_t md;
gcry_md_open (&md, sig->digest_algo,0);
if (gcry_md_open (&md, sig->digest_algo, 0))
BUG ();
hash_public_key(md,pk);
rc=signature_check(sig,md);
cache_sig_result(sig,rc);
@ -407,6 +425,39 @@ check_revocation_keys(PKT_public_key *pk,PKT_signature *sig)
return rc;
}
/* Backsigs (0x19) have the same format as binding sigs (0x18), but
this function is simpler than check_key_signature in a few ways.
For example, there is no support for expiring backsigs since it is
questionable what such a thing actually means. Note also that the
sig cache check here, unlike other sig caches in GnuPG, is not
persistent. */
int
check_backsig(PKT_public_key *main_pk,PKT_public_key *sub_pk,
PKT_signature *backsig)
{
gcry_md_hd_t md;
int rc;
if(!opt.no_sig_cache && backsig->flags.checked)
{
if((rc=openpgp_md_test_algo (backsig->digest_algo)))
return rc;
return backsig->flags.valid? 0 : gpg_error (GPG_ERR_BAD_SIGNATURE);
}
if (gcry_md_open (&md, backsig->digest_algo,0))
BUG ();
hash_public_key(md,main_pk);
hash_public_key(md,sub_pk);
rc=do_check(sub_pk,backsig,md,NULL,NULL,NULL);
cache_sig_result(backsig,rc);
gcry_md_close(md);
return rc;
}
/****************
* check the signature pointed to by NODE. This is a key signature.
* If the function detects a self-signature, it uses the PK from
@ -415,7 +466,7 @@ check_revocation_keys(PKT_public_key *pk,PKT_signature *sig)
int
check_key_signature( KBNODE root, KBNODE node, int *is_selfsig )
{
return check_key_signature2(root, node, NULL, NULL, is_selfsig, NULL, NULL);
return check_key_signature2(root, node, NULL, NULL, is_selfsig, NULL, NULL );
}
/* If check_pk is set, then use it to check the signature in node
@ -427,9 +478,9 @@ check_key_signature( KBNODE root, KBNODE node, int *is_selfsig )
int
check_key_signature2( KBNODE root, KBNODE node, PKT_public_key *check_pk,
PKT_public_key *ret_pk, int *is_selfsig,
u32 *r_expiredate, int *r_expired )
u32 *r_expiredate, int *r_expired )
{
MD_HANDLE md;
gcry_md_hd_t md;
PKT_public_key *pk;
PKT_signature *sig;
int algo;
@ -448,7 +499,10 @@ check_key_signature2( KBNODE root, KBNODE node, PKT_public_key *check_pk,
sig = node->pkt->pkt.signature;
algo = sig->digest_algo;
/* check whether we have cached the result of a previous signature check.*/
/* Check whether we have cached the result of a previous signature
check. Note that we may no longer have the pubkey or hash
needed to verify a sig, but can still use the cached value. A
cache refresh detects and clears these cases. */
if ( !opt.no_sig_cache ) {
if (sig->flags.checked) { /*cached status available*/
if( is_selfsig ) {
@ -458,7 +512,7 @@ check_key_signature2( KBNODE root, KBNODE node, PKT_public_key *check_pk,
if( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1] )
*is_selfsig = 1;
}
/* BUG: This is wrong for non-self-sigs. Needs to be the
/* BUG: This is wrong for non-self-sigs.. needs to be the
actual pk */
if((rc=do_check_messages(pk,sig,r_expired,NULL)))
return rc;
@ -466,8 +520,10 @@ check_key_signature2( KBNODE root, KBNODE node, PKT_public_key *check_pk,
}
}
if( (rc=gcry_md_test_algo(algo)) )
return rc;
if( (rc=openpgp_pk_test_algo(sig->pubkey_algo)) )
return rc;
if( (rc=openpgp_md_test_algo(algo)) )
return rc;
if( sig->sig_class == 0x20 ) { /* key revocation */
u32 keyid[2];
@ -478,7 +534,8 @@ check_key_signature2( KBNODE root, KBNODE node, PKT_public_key *check_pk,
rc=check_revocation_keys(pk,sig);
else
{
gcry_md_open (&md, algo, 0 );
if (gcry_md_open (&md, algo, 0 ))
BUG ();
hash_public_key( md, pk );
rc = do_check( pk, sig, md, r_expired, NULL, ret_pk );
cache_sig_result ( sig, rc );
@ -489,20 +546,21 @@ check_key_signature2( KBNODE root, KBNODE node, PKT_public_key *check_pk,
KBNODE snode = find_prev_kbnode( root, node, PKT_PUBLIC_SUBKEY );
if( snode ) {
gcry_md_open (&md, algo, 0 );
if (gcry_md_open (&md, algo, 0))
BUG ();
hash_public_key( md, pk );
hash_public_key( md, snode->pkt->pkt.public_key );
rc = do_check( pk, sig, md, r_expired, NULL, ret_pk );
cache_sig_result ( sig, rc );
gcry_md_close(md);
}
else {
else
{
if (opt.verbose)
log_info (_("key %08lX: no subkey for subkey "
"revocation signature\n"),
(ulong)keyid_from_pk (pk, NULL));
rc = GPG_ERR_SIG_CLASS;
}
log_info (_("key %s: no subkey for subkey"
" revocation signature\n"),keystr_from_pk(pk));
rc = G10ERR_SIG_CLASS;
}
}
else if( sig->sig_class == 0x18 ) { /* key binding */
KBNODE snode = find_prev_kbnode( root, node, PKT_PUBLIC_SUBKEY );
@ -515,23 +573,25 @@ check_key_signature2( KBNODE root, KBNODE node, PKT_public_key *check_pk,
if( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1] )
*is_selfsig = 1;
}
gcry_md_open (&md, algo, 0 );
if (gcry_md_open (&md, algo, 0))
BUG ();
hash_public_key( md, pk );
hash_public_key( md, snode->pkt->pkt.public_key );
rc = do_check( pk, sig, md, r_expired, NULL, ret_pk );
cache_sig_result ( sig, rc );
gcry_md_close(md);
}
else {
else
{
if (opt.verbose)
log_info(_("key %08lX: no subkey for subkey "
"binding signature\n"),
(ulong)keyid_from_pk (pk, NULL));
rc = GPG_ERR_SIG_CLASS;
}
log_info(_("key %s: no subkey for subkey"
" binding signature\n"),keystr_from_pk(pk));
rc = G10ERR_SIG_CLASS;
}
}
else if( sig->sig_class == 0x1f ) { /* direct key signature */
gcry_md_open (&md, algo, 0 );
if (gcry_md_open (&md, algo, 0 ))
BUG ();
hash_public_key( md, pk );
rc = do_check( pk, sig, md, r_expired, NULL, ret_pk );
cache_sig_result ( sig, rc );
@ -544,7 +604,8 @@ check_key_signature2( KBNODE root, KBNODE node, PKT_public_key *check_pk,
u32 keyid[2];
keyid_from_pk( pk, keyid );
gcry_md_open (&md, algo, 0 );
if (gcry_md_open (&md, algo, 0 ))
BUG ();
hash_public_key( md, pk );
hash_uid_node( unode, md, sig );
if( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1] )
@ -554,21 +615,20 @@ check_key_signature2( KBNODE root, KBNODE node, PKT_public_key *check_pk,
rc = do_check( pk, sig, md, r_expired, NULL, ret_pk );
}
else if (check_pk)
rc=do_check(check_pk,sig,md,r_expired, NULL, ret_pk);
rc=do_check(check_pk,sig,md,r_expired,NULL,ret_pk);
else
rc = signature_check2( sig, md, r_expiredate, r_expired,
NULL, ret_pk);
rc=signature_check2(sig,md,r_expiredate,r_expired,NULL,ret_pk);
cache_sig_result ( sig, rc );
gcry_md_close(md);
}
else {
else
{
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 = GPG_ERR_SIG_CLASS;
}
log_info ("key %s: no user ID for key signature packet"
" of class %02x\n",keystr_from_pk(pk),sig->sig_class);
rc = G10ERR_SIG_CLASS;
}
}
return rc;

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,6 @@
/* signal.c - signal handling
* Copyright (C) 1998, 1999, 2000, 2001, 2003 Free Software Foundation, Inc.
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004,
* 2005 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -15,7 +16,8 @@
*
* 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
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
#include <config.h>
@ -26,22 +28,28 @@
#include <string.h>
#include <errno.h>
#include <assert.h>
#ifdef HAVE_LIBREADLINE
#include <readline/readline.h>
#include <readline/history.h>
#endif
#include "gpg.h"
#include "options.h"
#include "errors.h"
#include "memory.h"
#include "util.h"
#include "main.h"
#include "ttyio.h"
#ifdef HAVE_DOSISH_SYSTEM
void init_signals(void) {}
void pause_on_sigusr(int which) {}
#else
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
#if defined(HAVE_SIGACTION) && defined(HAVE_STRUCT_SIGACTION)
struct sigaction oact, nact;
@ -65,20 +73,8 @@ init_one_signal (int sig, RETSIGTYPE (*handler)(int), int check_ign )
signal (sig, SIG_IGN);
}
#endif
#endif /*!HAVE_DOSISH_SYSTEM*/
}
static const char *
get_signal_name( int signum )
{
#if defined(SYS_SIGLIST_DECLARED) && defined(NSIG)
return (signum >= 0 && signum < NSIG) ? sys_siglist[signum] : "?";
#else
return "some signal";
#endif
}
static RETSIGTYPE
got_fatal_signal( int sig )
{
@ -89,14 +85,33 @@ got_fatal_signal( int sig )
caught_fatal_sig = 1;
gcry_control (GCRYCTL_TERM_SECMEM );
/* better don't transtale these messages */
#ifdef HAVE_LIBREADLINE
rl_free_line_state ();
rl_cleanup_after_signal ();
#endif
/* Better don't translate these messages. */
write(2, "\n", 1 );
s = "?" /* FIXME: log_get_name()*/; if( s ) write(2, s, strlen(s) );
s = log_get_name(); if( s ) write(2, s, strlen(s) );
write(2, ": ", 2 );
s = get_signal_name(sig); write(2, s, strlen(s) );
#if HAVE_DECL_SYS_SIGLIST && defined(NSIG)
s = (sig >= 0 && sig < NSIG) ? sys_siglist[sig] : "?";
write (2, s, strlen(s) );
#else
write (2, "signal ", 7 );
if (sig < 0 || sig >=100)
write (2, "?", 1);
else {
if (sig >= 10)
write (2, "0123456789"+(sig/10), 1 );
write (2, "0123456789"+(sig%10), 1 );
}
#endif
write(2, " caught ... exiting\n", 20 );
/* reset action to default action and raise signal again */
/* Reset action to default action and raise signal again. */
init_one_signal (sig, SIG_DFL, 0);
dotlock_remove_lockfiles ();
#ifdef __riscos__
@ -116,7 +131,6 @@ got_usr_signal( int sig )
void
init_signals()
{
#ifndef HAVE_DOSISH_SYSTEM
init_one_signal (SIGINT, got_fatal_signal, 1 );
init_one_signal (SIGHUP, got_fatal_signal, 1 );
init_one_signal (SIGTERM, got_fatal_signal, 1 );
@ -124,14 +138,12 @@ init_signals()
init_one_signal (SIGSEGV, got_fatal_signal, 1 );
init_one_signal (SIGUSR1, got_usr_signal, 0 );
init_one_signal (SIGPIPE, SIG_IGN, 0 );
#endif
}
void
pause_on_sigusr( int which )
{
#ifndef HAVE_DOSISH_SYSTEM
#if defined(HAVE_SIGPROCMASK) && defined(HAVE_SIGSET_T)
sigset_t mask, oldmask;
@ -150,16 +162,15 @@ pause_on_sigusr( int which )
while (!caught_sigusr1)
sigpause(SIGUSR1);
caught_sigusr1 = 0;
sigrelse(SIGUSR1);
#endif /*!HAVE_SIGPROCMASK && HAVE_SISET_T*/
#endif
sigrelse(SIGUSR1);
#endif /*! HAVE_SIGPROCMASK && HAVE_SIGSET_T */
}
/* Disabled - see comment in tdbio.c:tdbio_begin_transaction() */
#if 0
static void
do_block( int block )
{
#ifndef HAVE_DOSISH_SYSTEM
static int is_blocked;
#if defined(HAVE_SIGPROCMASK) && defined(HAVE_SIGSET_T)
static sigset_t oldmask;
@ -179,14 +190,14 @@ do_block( int block )
sigprocmask( SIG_SETMASK, &oldmask, NULL );
is_blocked = 0;
}
#else /*!HAVE_SIGPROCMASK*/
#else /*! HAVE_SIGPROCMASK && HAVE_SIGSET_T */
#if defined(NSIG)
# define SIGSMAX (NSIG)
#define SIGSMAX (NSIG)
#elif defined(MAXSIG)
# define SIGSMAX (MAXSIG+1)
#define SIGSMAX (MAXSIG+1)
#else
# error "define SIGSMAX to the number of signals on your platform plus one"
#error "define SIGSMAX to the number of signals on your platform plus one"
#endif
static void (*disposition[SIGSMAX])(int);
@ -208,11 +219,9 @@ do_block( int block )
}
is_blocked = 0;
}
#endif /*!HAVE_SIGPROCMASK*/
#endif /*HAVE_DOSISH_SYSTEM*/
#endif /*! HAVE_SIGPROCMASK && HAVE_SIGSET_T */
}
void
block_all_signals()
{
@ -224,3 +233,6 @@ unblock_all_signals()
{
do_block(0);
}
#endif
#endif /* !HAVE_DOSISH_SYSTEM */

View File

@ -1,5 +1,5 @@
/* skclist.c
* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
/* skclist.c - Build a list of secret keys
* Copyright (C) 1998, 1999, 2000, 2001, 2006 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -15,7 +15,8 @@
*
* 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
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
#include <config.h>
@ -25,11 +26,11 @@
#include <errno.h>
#include <assert.h>
#include "gpg.h"
#include "options.h"
#include "packet.h"
#include "errors.h"
#include "keydb.h"
#include "memory.h"
#include "util.h"
#include "i18n.h"
#include "cipher.h"
@ -43,11 +44,41 @@ 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 );
xfree ( sk_list );
xfree( 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)
@ -77,37 +108,41 @@ build_sk_list( STRLIST locusr, SK_LIST *ret_sk_list,
SK_LIST sk_list = NULL;
int rc;
if( !locusr ) { /* use the default one */
if( !locusr )
{ /* use the default one */
PKT_secret_key *sk;
sk = xcalloc (1, sizeof *sk );
sk = xmalloc_clear( sizeof *sk );
sk->req_usage = use;
if( (rc = get_seckey_byname( sk, NULL, unlock )) ) {
free_secret_key( sk ); sk = NULL;
log_error("no default secret key: %s\n", gpg_strerror (rc) );
free_secret_key( sk ); sk = NULL;
log_error("no default secret key: %s\n", g10_errstr(rc) );
}
else if( !(rc=openpgp_pk_test_algo (sk->pubkey_algo, use)) ) {
else if( !(rc=openpgp_pk_test_algo2 (sk->pubkey_algo, use)) )
{
SK_LIST r;
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");
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 = xmalloc ( sizeof *r );
}
else
{
r = xmalloc( sizeof *r );
r->sk = sk; sk = NULL;
r->next = sk_list;
r->mark = 0;
sk_list = r;
}
}
else {
}
}
else
{
free_secret_key( sk ); sk = NULL;
log_error("invalid default secret key: %s\n", gpg_strerror (rc) );
}
}
log_error("invalid default secret key: %s\n", g10_errstr(rc) );
}
}
else {
STRLIST locusr_orig = locusr;
for(; locusr; locusr = locusr->next ) {
@ -118,36 +153,47 @@ build_sk_list( STRLIST locusr, SK_LIST *ret_sk_list,
* 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 );
if ( is_duplicated_entry ( locusr_orig, locusr ) )
{
log_error(_("skipped \"%s\": duplicated\n"), locusr->d );
continue;
}
sk = xcalloc (1, sizeof *sk );
}
sk = xmalloc_clear( sizeof *sk );
sk->req_usage = use;
if( (rc = get_seckey_byname( sk, locusr->d, 0 )) ) {
if( (rc = get_seckey_byname( sk, locusr->d, 0 )) )
{
free_secret_key( sk ); sk = NULL;
log_error(_("skipped `%s': %s\n"), locusr->d, gpg_strerror (rc) );
}
log_error(_("skipped \"%s\": %s\n"),
locusr->d, g10_errstr(rc) );
}
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 )) ) {
else if ( unlock && (rc = check_secret_key( sk, 0 )) )
{
free_secret_key( sk ); sk = NULL;
log_error(_("skipped `%s': %s\n"), locusr->d, gpg_strerror (rc) );
}
log_error(_("skipped \"%s\": %s\n"),
locusr->d, g10_errstr(rc) );
}
else if( !(rc=openpgp_pk_test_algo (sk->pubkey_algo, use)) ) {
SK_LIST r;
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 );
&& sk->pubkey_algo == PUBKEY_ALGO_ELGAMAL_E )
{
log_info(_("skipped \"%s\": %s\n"),locusr->d,
_("this is a PGP generated Elgamal key which"
" is not secure for signatures!"));
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 = xmalloc ( sizeof *r );
r = xmalloc( sizeof *r );
r->sk = sk; sk = NULL;
r->next = sk_list;
r->mark = 0;
@ -156,7 +202,7 @@ build_sk_list( STRLIST locusr, SK_LIST *ret_sk_list,
}
else {
free_secret_key( sk ); sk = NULL;
log_error("skipped `%s': %s\n", locusr->d, gpg_strerror (rc) );
log_error("skipped \"%s\": %s\n", locusr->d, g10_errstr(rc) );
}
}
}
@ -164,7 +210,7 @@ build_sk_list( STRLIST locusr, SK_LIST *ret_sk_list,
if( !rc && !sk_list ) {
log_error("no valid signators\n");
rc = GPG_ERR_NO_USER_ID;
rc = G10ERR_NO_USER_ID;
}
if( rc )

View File

@ -1,6 +1,6 @@
/* status.c
* Copyright (C) 1998, 1999, 2000, 2001, 2002,
* 2003 Free Software Foundation, Inc.
/* status.c - Status message and command-fd interface
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003,
* 2004, 2005, 2006 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -16,7 +16,8 @@
*
* 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
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
#include <config.h>
@ -44,98 +45,145 @@ static FILE *statusfp;
static void
progress_cb (void *ctx, const char *what, int printchar, int current, int total)
progress_cb ( void *ctx, int c )
{
char buf[150];
if (printchar == '\n')
printchar = 'X';
sprintf (buf, "%.20s %c %d %d", what, printchar, current, total);
write_status_text (STATUS_PROGRESS, buf);
char buf[50];
if ( c == '\n' )
sprintf ( buf, "%.20s X 100 100", (char*)ctx );
else
sprintf ( buf, "%.20s %c 0 0", (char*)ctx, c );
write_status_text ( STATUS_PROGRESS, buf );
}
static const char *
get_status_string ( int no )
{
const char *s;
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_OK : s = "IMPORT_OK"; break;
case STATUS_IMPORT_CHECK : s = "IMPORT_CHECK"; 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_REVKEYSIG : s = "REVKEYSIG"; break;
case STATUS_ATTRIBUTE : s = "ATTRIBUTE"; break;
default: s = "?"; break;
switch( no )
{
case STATUS_ENTER : s = "ENTER"; break;
case STATUS_LEAVE : s = "LEAVE"; break;
case STATUS_ABORT : s = "ABORT"; break;
case STATUS_NEWSIG : s = "NEWSIG"; 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_NEED_PASSPHRASE_PIN: s = "NEED_PASSPHRASE_PIN"; 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_OK : s = "IMPORT_OK"; break;
case STATUS_IMPORT_CHECK : s = "IMPORT_CHECK"; 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_KEY_NOT_CREATED: s = "KEY_NOT_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_REVKEYSIG : s = "REVKEYSIG"; break;
case STATUS_ATTRIBUTE : s = "ATTRIBUTE"; break;
case STATUS_CARDCTRL : s = "CARDCTRL"; break;
case STATUS_PLAINTEXT : s = "PLAINTEXT"; break;
case STATUS_PLAINTEXT_LENGTH:s = "PLAINTEXT_LENGTH"; break;
case STATUS_SIG_SUBPACKET : s = "SIG_SUBPACKET"; break;
case STATUS_SC_OP_SUCCESS : s = "SC_OP_SUCCESS"; break;
case STATUS_SC_OP_FAILURE : s = "SC_OP_FAILURE"; break;
case STATUS_BACKUP_KEY_CREATED:s="BACKUP_KEY_CREATED"; break;
case STATUS_PKA_TRUST_BAD : s = "PKA_TRUST_BAD"; break;
case STATUS_PKA_TRUST_GOOD : s = "PKA_TRUST_GOOD"; break;
case STATUS_BEGIN_SIGNING : s = "BEGIN_SIGNING"; break;
default: s = "?"; break;
}
return s;
return s;
}
/* Return true if the status message NO may currently be issued. We
need this to avoid syncronisation problem while auto retrieving a
key. There it may happen that a status NODATA is issued for a non
available key and the user may falsely interpret this has a missing
signature. */
static int
status_currently_allowed (int no)
{
if (!glo_ctrl.in_auto_key_retrieve)
return 1; /* Yes. */
/* We allow some statis anyway, so that import statistics are
correct and to avoid problems if the retriebval subsystem will
prompt the user. */
switch (no)
{
case STATUS_GET_BOOL:
case STATUS_GET_LINE:
case STATUS_GET_HIDDEN:
case STATUS_GOT_IT:
case STATUS_IMPORTED:
case STATUS_IMPORT_OK:
case STATUS_IMPORT_CHECK:
case STATUS_IMPORT_RES:
return 1; /* Yes. */
default:
break;
}
return 0; /* No. */
}
void
set_status_fd ( int fd )
{
@ -161,7 +209,9 @@ set_status_fd ( int fd )
fd, strerror(errno));
}
last_fd = fd;
gcry_set_progress_handler (progress_cb, NULL);
register_primegen_progress ( progress_cb, "primegen" );
register_pk_dsa_progress ( progress_cb, "pk_dsa" );
register_pk_elg_progress ( progress_cb, "pk_elg" );
}
int
@ -179,8 +229,8 @@ write_status ( int no )
void
write_status_text ( int no, const char *text)
{
if( !statusfp )
return; /* not enabled */
if( !statusfp || !status_currently_allowed (no) )
return; /* Not enabled or allowed. */
fputs ( "[GNUPG:] ", statusfp );
fputs ( get_status_string (no), statusfp );
@ -196,7 +246,8 @@ write_status_text ( int no, const char *text)
}
}
putc ('\n',statusfp);
fflush (statusfp);
if ( fflush (statusfp) && opt.exit_on_status_write_error )
g10_exit (0);
}
@ -215,8 +266,8 @@ write_status_text_and_buffer ( int no, const char *string,
int lower_limit = ' ';
size_t n, count, dowrap;
if( !statusfp )
return; /* not enabled */
if( !statusfp || !status_currently_allowed (no) )
return; /* Not enabled or allowed. */
if (wrap == -1) {
lower_limit--;
@ -260,7 +311,8 @@ write_status_text_and_buffer ( int no, const char *string,
} while ( len );
putc ('\n',statusfp);
fflush (statusfp);
if ( fflush (statusfp) && opt.exit_on_status_write_error )
g10_exit (0);
}
void
@ -308,6 +360,9 @@ do_get_from_fd( const char *keyword, int hidden, int bool )
int i, len;
char *string;
if(statusfp!=stdout)
fflush(stdout);
write_status_text( bool? STATUS_GET_BOOL :
hidden? STATUS_GET_HIDDEN : STATUS_GET_LINE, keyword );
@ -348,6 +403,10 @@ cpr_enabled()
{
if( opt.command_fd != -1 )
return 1;
#ifdef USE_SHM_COPROCESSING
if( opt.shm_coprocess )
return 1;
#endif
return 0;
}
@ -358,6 +417,10 @@ cpr_get_no_help( const char *keyword, const char *prompt )
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;
@ -371,10 +434,14 @@ cpr_get( const char *keyword, const char *prompt )
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 );
if( *p=='?' && !p[1] && !(keyword && !*keyword)) {
xfree (p);
xfree(p);
display_online_help( keyword );
}
else
@ -390,7 +457,7 @@ cpr_get_utf8( const char *keyword, const char *prompt )
p = cpr_get( keyword, prompt );
if( p ) {
char *utf8 = native_to_utf8( p );
xfree ( p );
xfree( p );
p = utf8;
}
return p;
@ -403,10 +470,14 @@ cpr_get_hidden( const char *keyword, const char *prompt )
if( opt.command_fd != -1 )
return do_get_from_fd ( keyword, 1, 0 );
#ifdef USE_SHM_COPROCESSING
if( opt.shm_coprocess )
return do_shm_get( keyword, 1, 0 );
#endif
for(;;) {
p = tty_get_hidden( prompt );
if( *p == '?' && !p[1] ) {
xfree (p);
xfree(p);
display_online_help( keyword );
}
else
@ -419,6 +490,10 @@ cpr_kill_prompt(void)
{
if( opt.command_fd != -1 )
return;
#ifdef USE_SHM_COPROCESSING
if( opt.shm_coprocess )
return;
#endif
tty_kill_prompt();
return;
}
@ -431,17 +506,21 @@ cpr_get_answer_is_yes( const char *keyword, const char *prompt )
if( opt.command_fd != -1 )
return !!do_get_from_fd ( keyword, 0, 1 );
#ifdef USE_SHM_COPROCESSING
if( opt.shm_coprocess )
return !!do_shm_get( keyword, 0, 1 );
#endif
for(;;) {
p = tty_get( prompt );
trim_spaces(p); /* it is okay to do this here */
if( *p == '?' && !p[1] ) {
xfree (p);
xfree(p);
display_online_help( keyword );
}
else {
tty_kill_prompt();
yes = answer_is_yes(p);
xfree (p);
xfree(p);
return yes;
}
}
@ -455,18 +534,65 @@ cpr_get_answer_yes_no_quit( const char *keyword, const char *prompt )
if( opt.command_fd != -1 )
return !!do_get_from_fd ( keyword, 0, 1 );
#ifdef USE_SHM_COPROCESSING
if( opt.shm_coprocess )
return !!do_shm_get( keyword, 0, 1 );
#endif
for(;;) {
p = tty_get( prompt );
trim_spaces(p); /* it is okay to do this here */
if( *p == '?' && !p[1] ) {
xfree (p);
xfree(p);
display_online_help( keyword );
}
else {
tty_kill_prompt();
yes = answer_is_yes_no_quit(p);
xfree (p);
xfree(p);
return yes;
}
}
}
int
cpr_get_answer_okay_cancel (const char *keyword,
const char *prompt,
int def_answer)
{
int yes;
char *answer = NULL;
char *p;
if( opt.command_fd != -1 )
answer = do_get_from_fd ( keyword, 0, 0 );
#ifdef USE_SHM_COPROCESSING
else if( opt.shm_coprocess )
answer = do_shm_get( keyword, 0, 0 );
#endif
if (answer)
{
yes = answer_is_okay_cancel (answer, def_answer);
xfree (answer);
return yes;
}
for(;;)
{
p = tty_get( prompt );
trim_spaces(p); /* it is okay to do this here */
if (*p == '?' && !p[1])
{
xfree(p);
display_online_help (keyword);
}
else
{
tty_kill_prompt();
yes = answer_is_okay_cancel (p, def_answer);
xfree(p);
return yes;
}
}
}

View File

@ -1,5 +1,6 @@
/* status.h
* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003,
* 2004 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -15,12 +16,12 @@
*
* 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
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
#ifndef G10_STATUS_H
#define G10_STATUS_H
#define STATUS_ENTER 1
#define STATUS_LEAVE 2
#define STATUS_ABORT 3
@ -29,7 +30,6 @@
#define STATUS_BADSIG 5
#define STATUS_ERRSIG 6
#define STATUS_BADARMOR 7
#define STATUS_RSA_OR_IDEA 8
@ -100,6 +100,26 @@
#define STATUS_IMPORT_OK 68
#define STATUS_IMPORT_CHECK 69
#define STATUS_REVKEYSIG 70
#define STATUS_CARDCTRL 71
#define STATUS_NEWSIG 72
#define STATUS_PLAINTEXT 73
#define STATUS_PLAINTEXT_LENGTH 74
#define STATUS_KEY_NOT_CREATED 75
#define STATUS_NEED_PASSPHRASE_PIN 76
#define STATUS_SIG_SUBPACKET 77
/* Extra status codes for certain smartcard operations. Primary
useful to double check that change PIN worked as expected. */
#define STATUS_SC_OP_FAILURE 79
#define STATUS_SC_OP_SUCCESS 80
#define STATUS_BACKUP_KEY_CREATED 81
#define STATUS_PKA_TRUST_BAD 82
#define STATUS_PKA_TRUST_GOOD 83
#define STATUS_BEGIN_SIGNING 84
/*-- status.c --*/
void set_status_fd ( int fd );
@ -119,6 +139,8 @@ char *cpr_get_hidden( const char *keyword, const char *prompt );
void cpr_kill_prompt(void);
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 );
int cpr_get_answer_okay_cancel (const char *keyword,
const char *prompt,
int def_answer);
#endif /*G10_STATUS_H*/

View File

@ -1,5 +1,5 @@
/* tdbdump.c
* Copyright (C) 1998, 1999, 2000, 2001, 2003 Free Software Foundation, Inc.
* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -15,7 +15,8 @@
*
* 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
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
#include <config.h>
@ -34,7 +35,6 @@
#include "errors.h"
#include "iobuf.h"
#include "keydb.h"
#include "memory.h"
#include "util.h"
#include "trustdb.h"
#include "options.h"
@ -58,7 +58,7 @@ write_record( TRUSTREC *rec )
if( !rc )
return;
log_error(_("trust record %lu, type %d: write failed: %s\n"),
rec->recnum, rec->rectype, gpg_strerror (rc) );
rec->recnum, rec->rectype, g10_errstr(rc) );
tdbio_invalid();
}
@ -132,7 +132,7 @@ import_ownertrust( const char *fname )
int rc;
init_trustdb();
if( !fname || (*fname == '-' && !fname[1]) ) {
if( iobuf_is_pipe_filename (fname) ) {
fp = stdin;
fname = "[stdin]";
is_stdin = 1;
@ -142,6 +142,14 @@ import_ownertrust( const char *fname )
return;
}
if (is_secured_file (fileno (fp)))
{
fclose (fp);
errno = EPERM;
log_error (_("can't open `%s': %s\n"), fname, strerror(errno) );
return;
}
while( fgets( line, DIM(line)-1, fp ) ) {
TRUSTREC rec;
@ -149,24 +157,26 @@ import_ownertrust( const char *fname )
continue;
n = strlen(line);
if( line[n-1] != '\n' ) {
log_error (_("\b%s: line too long\n"), fname );
log_error (_("error in `%s': %s\n"), fname, _("line too long") );
/* ... or last line does not have a LF */
break; /* can't continue */
}
for(p = line; *p && *p != ':' ; p++ )
if( !hexdigitp (p) )
if( !hexdigitp(p) )
break;
if( *p != ':' ) {
log_error (_("\b%s: error: missing colon\n"), fname );
log_error (_("error in `%s': %s\n"), fname, _("colon missing") );
continue;
}
fprlen = p - line;
if( fprlen != 32 && fprlen != 40 ) {
log_error (_("\b%s: error: invalid fingerprint\n"), fname );
log_error (_("error in `%s': %s\n"),
fname, _("invalid fingerprint") );
continue;
}
if( sscanf(p, ":%u:", &otrust ) != 1 ) {
log_error (_("\b%s: error: no ownertrust value\n"), fname );
log_error (_("error in `%s': %s\n"),
fname, _("ownertrust value missing"));
continue;
}
if( !otrust )
@ -202,11 +212,11 @@ import_ownertrust( const char *fname )
any = 1;
}
else /* error */
log_error (_("\b%s: error finding trust record: %s\n"),
fname, gpg_strerror (rc));
log_error (_("error finding trust record in `%s': %s\n"),
fname, g10_errstr(rc));
}
if( ferror(fp) )
log_error (_("\b%s: read error: %s\n"), fname, strerror(errno) );
log_error ( _("read error in `%s': %s\n"), fname, strerror(errno) );
if( !is_stdin )
fclose(fp);
@ -215,7 +225,7 @@ import_ownertrust( const char *fname )
revalidation_mark ();
rc = tdbio_sync ();
if (rc)
log_error (_("trustdb: sync failed: %s\n"), gpg_strerror (rc) );
log_error (_("trustdb: sync failed: %s\n"), g10_errstr(rc) );
}
}

View File

@ -1,4 +1,4 @@
/* tdbio.c
/* tdbio.c - trust databse I/O operations
* Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
@ -15,7 +15,8 @@
*
* 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
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
#include <config.h>
@ -32,7 +33,6 @@
#include "gpg.h"
#include "errors.h"
#include "iobuf.h"
#include "memory.h"
#include "util.h"
#include "options.h"
#include "main.h"
@ -123,21 +123,21 @@ get_record_from_cache( ulong recno )
static int
write_cache_item( CACHE_CTRL r )
{
gpg_error_t err;
int n;
gpg_error_t rc;
if( lseek( db_fd, r->recno * TRUST_RECORD_LEN, SEEK_SET ) == -1 ) {
rc = gpg_error_from_errno (errno);
err = gpg_error_from_errno (errno);
log_error(_("trustdb rec %lu: lseek failed: %s\n"),
r->recno, strerror(errno) );
return rc;
return err;
}
n = write( db_fd, r->data, TRUST_RECORD_LEN);
if( n != TRUST_RECORD_LEN ) {
rc = gpg_error_from_errno (errno);
err = gpg_error_from_errno (errno);
log_error(_("trustdb rec %lu: write failed (n=%d): %s\n"),
r->recno, n, strerror(errno) );
return rc;
return err;
}
r->flags.dirty = 0;
return 0;
@ -191,7 +191,7 @@ put_record_into_cache( ulong recno, const char *data )
}
/* see whether we reached the limit */
if( cache_entries < MAX_CACHE_ENTRIES_SOFT ) { /* no */
r = xmalloc ( sizeof *r );
r = xmalloc( sizeof *r );
r->flags.used = 1;
r->recno = recno;
memcpy( r->data, data, TRUST_RECORD_LEN );
@ -234,7 +234,7 @@ put_record_into_cache( ulong recno, const char *data )
if( cache_entries < MAX_CACHE_ENTRIES_HARD ) { /* no */
if( opt.debug && !(cache_entries % 100) )
log_debug("increasing tdbio cache size\n");
r = xmalloc ( sizeof *r );
r = xmalloc( sizeof *r );
r->flags.used = 1;
r->recno = recno;
memcpy( r->data, data, TRUST_RECORD_LEN );
@ -246,7 +246,7 @@ put_record_into_cache( ulong recno, const char *data )
return 0;
}
log_info(_("trustdb transaction too large\n"));
return GPG_ERR_RESOURCE_LIMIT;
return G10ERR_RESOURCE_LIMIT;
}
if( dirty_count ) {
int n = dirty_count / 5; /* discard some dirty entries */
@ -336,7 +336,6 @@ tdbio_sync()
return 0;
}
#if 0
/* The transaction code is disabled in the 1.2.x branch, as it is not
yet used. It will be enabled in 1.3.x. */
@ -375,11 +374,10 @@ tdbio_end_transaction()
else
is_locked = 1;
}
#warning block_all_signals is not yet available in ../common/signals.c
/* block_all_signals(); */
block_all_signals();
in_transaction = 0;
rc = tdbio_sync();
/* unblock_all_signals(); */
unblock_all_signals();
if( !opt.lock_once ) {
if( !release_dotlock( lockhandle ) )
is_locked = 0;
@ -410,9 +408,7 @@ tdbio_cancel_transaction()
in_transaction = 0;
return 0;
}
#endif /* transaction code */
#endif
/********************************************************
@ -502,9 +498,9 @@ tdbio_set_dbname( const char *new_dbname, int create )
if( access( fname, R_OK ) ) {
if( errno != ENOENT ) {
log_error( _("%s: can't access: %s\n"), fname, strerror(errno) );
xfree (fname);
return GPG_ERR_TRUSTDB;
log_error( _("can't access `%s': %s\n"), fname, strerror(errno) );
xfree(fname);
return G10ERR_TRUSTDB;
}
if( create ) {
FILE *fp;
@ -521,37 +517,42 @@ tdbio_set_dbname( const char *new_dbname, int create )
}
*p = DIRSEP_C;
xfree (db_name);
xfree(db_name);
db_name = fname;
#ifdef __riscos__
if( !lockhandle )
lockhandle = create_dotlock( db_name );
if( !lockhandle )
log_fatal( _("%s: can't create lock\n"), db_name );
log_fatal( _("can't create lock for `%s'\n"), db_name );
if( make_dotlock( lockhandle, -1 ) )
log_fatal( _("%s: can't make lock\n"), db_name );
log_fatal( _("can't lock `%s'\n"), db_name );
#endif /* __riscos__ */
oldmask=umask(077);
fp =fopen( fname, "wb" );
if (is_secured_filename (fname)) {
fp = NULL;
errno = EPERM;
}
else
fp =fopen( fname, "wb" );
umask(oldmask);
if( !fp )
log_fatal( _("%s: can't create: %s\n"), fname, strerror(errno) );
log_fatal( _("can't create `%s': %s\n"), fname, strerror(errno) );
fclose(fp);
db_fd = open( db_name, O_RDWR | MY_O_BINARY );
if( db_fd == -1 )
log_fatal( _("%s: can't open: %s\n"), db_name, strerror(errno) );
log_fatal( _("can't open `%s': %s\n"), db_name, strerror(errno) );
#ifndef __riscos__
if( !lockhandle )
lockhandle = create_dotlock( db_name );
if( !lockhandle )
log_fatal( _("%s: can't create lock\n"), db_name );
log_fatal( _("can't create lock for `%s'\n"), db_name );
#endif /* !__riscos__ */
rc = create_version_record ();
if( rc )
log_fatal( _("%s: failed to create version record: %s"),
fname, gpg_strerror (rc));
fname, g10_errstr(rc));
/* and read again to check that we are okay */
if( tdbio_read_record( 0, &rec, RECTYPE_VER ) )
log_fatal( _("%s: invalid trustdb created\n"), db_name );
@ -562,7 +563,7 @@ tdbio_set_dbname( const char *new_dbname, int create )
return 0;
}
}
xfree (db_name);
xfree(db_name);
db_name = fname;
return 0;
}
@ -588,30 +589,26 @@ open_db()
if (!lockhandle )
lockhandle = create_dotlock( db_name );
if (!lockhandle )
log_fatal( _("%s: can't create lock\n"), db_name );
log_fatal( _("can't create lock for `%s'\n"), db_name );
#ifdef __riscos__
if (make_dotlock( lockhandle, -1 ) )
log_fatal( _("%s: can't make lock\n"), db_name );
log_fatal( _("can't lock `%s'\n"), db_name );
#endif /* __riscos__ */
db_fd = open (db_name, O_RDWR | MY_O_BINARY );
if (db_fd == -1 && errno == EACCES) {
if (db_fd == -1 && (errno == EACCES
#ifdef EROFS
|| errno == EROFS)
#endif
) {
db_fd = open (db_name, O_RDONLY | MY_O_BINARY );
if (db_fd != -1)
log_info (_("NOTE: trustdb not writable\n"));
}
if ( db_fd == -1 )
log_fatal( _("%s: can't open: %s\n"), db_name, strerror(errno) );
log_fatal( _("can't open `%s': %s\n"), db_name, strerror(errno) );
register_secured_file (db_name);
/* check whether we need to do a version migration */
do
n = read (db_fd, buf, 5);
while (n==-1 && errno == EINTR);
if (n == 5 && !memcmp (buf, "\x01gpg\x02", 5))
{
migrate_from_v2 ();
}
/* read the version record */
/* Read the version record. */
if (tdbio_read_record (0, &rec, RECTYPE_VER ) )
log_fatal( _("%s: invalid trustdb\n"), db_name );
}
@ -646,7 +643,7 @@ create_hashtable( TRUSTREC *vr, int type )
rc = tdbio_write_record( &rec );
if( rc )
log_fatal( _("%s: failed to create hashtable: %s\n"),
db_name, gpg_strerror (rc));
db_name, g10_errstr(rc));
}
/* update the version record */
rc = tdbio_write_record( vr );
@ -654,7 +651,7 @@ create_hashtable( TRUSTREC *vr, int type )
rc = tdbio_sync();
if( rc )
log_fatal( _("%s: error updating version record: %s\n"),
db_name, gpg_strerror (rc));
db_name, g10_errstr(rc));
}
@ -671,7 +668,7 @@ tdbio_db_matches_options()
rc = tdbio_read_record( 0, &vr, RECTYPE_VER );
if( rc )
log_fatal( _("%s: error reading version record: %s\n"),
db_name, gpg_strerror (rc) );
db_name, g10_errstr(rc) );
yes_no = vr.r.ver.marginals == opt.marginals_needed
&& vr.r.ver.completes == opt.completes_needed
@ -691,7 +688,7 @@ tdbio_read_model(void)
rc = tdbio_read_record( 0, &vr, RECTYPE_VER );
if( rc )
log_fatal( _("%s: error reading version record: %s\n"),
db_name, gpg_strerror (rc) );
db_name, g10_errstr(rc) );
return vr.r.ver.trust_model;
}
@ -707,7 +704,7 @@ tdbio_read_nextcheck ()
rc = tdbio_read_record( 0, &vr, RECTYPE_VER );
if( rc )
log_fatal( _("%s: error reading version record: %s\n"),
db_name, gpg_strerror (rc) );
db_name, g10_errstr(rc) );
return vr.r.ver.nextcheck;
}
@ -721,7 +718,7 @@ tdbio_write_nextcheck (ulong stamp)
rc = tdbio_read_record( 0, &vr, RECTYPE_VER );
if( rc )
log_fatal( _("%s: error reading version record: %s\n"),
db_name, gpg_strerror (rc) );
db_name, g10_errstr(rc) );
if (vr.r.ver.nextcheck == stamp)
return 0;
@ -730,7 +727,7 @@ tdbio_write_nextcheck (ulong stamp)
rc = tdbio_write_record( &vr );
if( rc )
log_fatal( _("%s: error writing version record: %s\n"),
db_name, gpg_strerror (rc) );
db_name, g10_errstr(rc) );
return 1;
}
@ -751,7 +748,7 @@ get_trusthashrec(void)
rc = tdbio_read_record( 0, &vr, RECTYPE_VER );
if( rc )
log_fatal( _("%s: error reading version record: %s\n"),
db_name, gpg_strerror (rc) );
db_name, g10_errstr(rc) );
if( !vr.r.ver.trusthashtbl )
create_hashtable( &vr, 0 );
@ -782,9 +779,8 @@ upd_hashtable( ulong table, byte *key, int keylen, ulong newrecnum )
hashrec += msb / ITEMS_PER_HTBL_RECORD;
rc = tdbio_read_record( hashrec, &rec, RECTYPE_HTBL );
if( rc ) {
log_error ("upd_hashtable in `%s': read failed: %s\n", db_name,
gpg_strerror (rc) );
return rc;
log_error("upd_hashtable: read failed: %s\n", g10_errstr(rc) );
return rc;
}
item = rec.r.htbl.item[msb % ITEMS_PER_HTBL_RECORD];
@ -792,8 +788,8 @@ upd_hashtable( ulong table, byte *key, int keylen, ulong newrecnum )
rec.r.htbl.item[msb % ITEMS_PER_HTBL_RECORD] = newrecnum;
rc = tdbio_write_record( &rec );
if( rc ) {
log_error ("upd_hashtable in `%s': write htbl failed: %s\n",
db_name, gpg_strerror (rc) );
log_error("upd_hashtable: write htbl failed: %s\n",
g10_errstr(rc) );
return rc;
}
}
@ -802,7 +798,7 @@ upd_hashtable( ulong table, byte *key, int keylen, ulong newrecnum )
rc = tdbio_read_record( item, &rec, 0 );
if( rc ) {
log_error( "upd_hashtable: read item failed: %s\n",
gpg_strerror (rc) );
g10_errstr(rc) );
return rc;
}
@ -811,7 +807,7 @@ upd_hashtable( ulong table, byte *key, int keylen, ulong newrecnum )
level++;
if( level >= keylen ) {
log_error( "hashtable has invalid indirections.\n");
return GPG_ERR_TRUSTDB;
return G10ERR_TRUSTDB;
}
goto next_level;
}
@ -828,7 +824,7 @@ upd_hashtable( ulong table, byte *key, int keylen, ulong newrecnum )
&rec, RECTYPE_HLST);
if( rc ) {
log_error( "upd_hashtable: read hlst failed: %s\n",
gpg_strerror (rc) );
g10_errstr(rc) );
return rc;
}
}
@ -843,7 +839,7 @@ upd_hashtable( ulong table, byte *key, int keylen, ulong newrecnum )
rc = tdbio_write_record( &rec );
if( rc )
log_error( "upd_hashtable: write hlst failed: %s\n",
gpg_strerror (rc) );
g10_errstr(rc) );
return rc; /* done */
}
}
@ -852,7 +848,7 @@ upd_hashtable( ulong table, byte *key, int keylen, ulong newrecnum )
&rec, RECTYPE_HLST );
if( rc ) {
log_error( "upd_hashtable: read hlst failed: %s\n",
gpg_strerror (rc) );
g10_errstr(rc) );
return rc;
}
}
@ -861,7 +857,7 @@ upd_hashtable( ulong table, byte *key, int keylen, ulong newrecnum )
rc = tdbio_write_record( &rec );
if( rc ) {
log_error( "upd_hashtable: write hlst failed: %s\n",
gpg_strerror (rc) );
g10_errstr(rc) );
return rc;
}
memset( &rec, 0, sizeof rec );
@ -871,7 +867,7 @@ upd_hashtable( ulong table, byte *key, int keylen, ulong newrecnum )
rc = tdbio_write_record( &rec );
if( rc )
log_error( "upd_hashtable: write ext hlst failed: %s\n",
gpg_strerror (rc) );
g10_errstr(rc) );
return rc; /* done */
}
} /* end loop over hlst slots */
@ -889,7 +885,7 @@ upd_hashtable( ulong table, byte *key, int keylen, ulong newrecnum )
rc = tdbio_write_record( &rec );
if( rc ) {
log_error( "upd_hashtable: write new hlst failed: %s\n",
gpg_strerror (rc) );
g10_errstr(rc) );
return rc;
}
/* update the hashtable record */
@ -897,14 +893,14 @@ upd_hashtable( ulong table, byte *key, int keylen, ulong newrecnum )
rc = tdbio_write_record( &lastrec );
if( rc )
log_error( "upd_hashtable: update htbl failed: %s\n",
gpg_strerror (rc) );
g10_errstr(rc) );
return rc; /* ready */
}
else {
log_error( "hashtbl %lu: %lu/%d points to an invalid record %lu\n",
table, hashrec, (msb % ITEMS_PER_HTBL_RECORD), item);
list_trustdb(NULL);
return GPG_ERR_TRUSTDB;
return G10ERR_TRUSTDB;
}
}
@ -931,8 +927,8 @@ drop_from_hashtable( ulong table, byte *key, int keylen, ulong recnum )
hashrec += msb / ITEMS_PER_HTBL_RECORD;
rc = tdbio_read_record( hashrec, &rec, RECTYPE_HTBL );
if( rc ) {
log_error ("drop_from_hashtable `%s': read failed: %s\n",
db_name, gpg_strerror (rc) );
log_error("drop_from_hashtable: read failed: %s\n",
g10_errstr(rc) );
return rc;
}
@ -944,15 +940,15 @@ drop_from_hashtable( ulong table, byte *key, int keylen, ulong recnum )
rec.r.htbl.item[msb % ITEMS_PER_HTBL_RECORD] = 0;
rc = tdbio_write_record( &rec );
if( rc )
log_error ("drop_from_hashtable `%s': write htbl failed: %s\n",
db_name, gpg_strerror (rc) );
log_error("drop_from_hashtable: write htbl failed: %s\n",
g10_errstr(rc) );
return rc;
}
rc = tdbio_read_record( item, &rec, 0 );
if( rc ) {
log_error( "drop_from_hashtable: read item failed: %s\n",
gpg_strerror (rc) );
g10_errstr(rc) );
return rc;
}
@ -961,7 +957,7 @@ drop_from_hashtable( ulong table, byte *key, int keylen, ulong recnum )
level++;
if( level >= keylen ) {
log_error( "hashtable has invalid indirections.\n");
return GPG_ERR_TRUSTDB;
return G10ERR_TRUSTDB;
}
goto next_level;
}
@ -973,9 +969,8 @@ drop_from_hashtable( ulong table, byte *key, int keylen, ulong recnum )
rec.r.hlst.rnum[i] = 0; /* drop */
rc = tdbio_write_record( &rec );
if( rc )
log_error ("drop_from_hashtable `%s': "
"write htbl failed: %s\n",
db_name, gpg_strerror (rc) );
log_error("drop_from_hashtable: write htbl failed: %s\n",
g10_errstr(rc) );
return rc;
}
}
@ -984,7 +979,7 @@ drop_from_hashtable( ulong table, byte *key, int keylen, ulong recnum )
&rec, RECTYPE_HLST);
if( rc ) {
log_error( "drop_from_hashtable: read hlst failed: %s\n",
gpg_strerror (rc) );
g10_errstr(rc) );
return rc;
}
}
@ -995,7 +990,7 @@ drop_from_hashtable( ulong table, byte *key, int keylen, ulong recnum )
log_error( "hashtbl %lu: %lu/%d points to wrong record %lu\n",
table, hashrec, (msb % ITEMS_PER_HTBL_RECORD), item);
return GPG_ERR_TRUSTDB;
return G10ERR_TRUSTDB;
}
@ -1021,8 +1016,7 @@ lookup_hashtable( ulong table, const byte *key, size_t keylen,
hashrec += msb / ITEMS_PER_HTBL_RECORD;
rc = tdbio_read_record( hashrec, rec, RECTYPE_HTBL );
if( rc ) {
log_error ("lookup_hashtable in `%s' failed: %s\n",
db_name, gpg_strerror (rc) );
log_error("lookup_hashtable failed: %s\n", g10_errstr(rc) );
return rc;
}
@ -1032,16 +1026,15 @@ lookup_hashtable( ulong table, const byte *key, size_t keylen,
rc = tdbio_read_record( item, rec, 0 );
if( rc ) {
log_error ("hashtable `%s' read failed: %s\n",
db_name, gpg_strerror (rc) );
log_error( "hashtable read failed: %s\n", g10_errstr(rc) );
return rc;
}
if( rec->rectype == RECTYPE_HTBL ) {
hashrec = item;
level++;
if( level >= keylen ) {
log_error ("hashtable `%s' has invalid indirections\n", db_name);
return GPG_ERR_TRUSTDB;
log_error("hashtable has invalid indirections\n");
return G10ERR_TRUSTDB;
}
goto next_level;
}
@ -1056,7 +1049,7 @@ lookup_hashtable( ulong table, const byte *key, size_t keylen,
rc = tdbio_read_record( rec->r.hlst.rnum[i], &tmp, 0 );
if( rc ) {
log_error( "lookup_hashtable: read item failed: %s\n",
gpg_strerror (rc) );
g10_errstr(rc) );
return rc;
}
if( (*cmpfnc)( cmpdata, &tmp ) ) {
@ -1069,7 +1062,7 @@ lookup_hashtable( ulong table, const byte *key, size_t keylen,
rc = tdbio_read_record( rec->r.hlst.next, rec, RECTYPE_HLST );
if( rc ) {
log_error( "lookup_hashtable: read hlst failed: %s\n",
gpg_strerror (rc) );
g10_errstr(rc) );
return rc;
}
}
@ -1164,7 +1157,7 @@ tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected )
{
byte readbuf[TRUST_RECORD_LEN];
const byte *buf, *p;
int rc = 0;
gpg_error_t err = 0;
int n, i;
if( db_fd == -1 )
@ -1172,19 +1165,19 @@ tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected )
buf = get_record_from_cache( recnum );
if( !buf ) {
if( lseek( db_fd, recnum * TRUST_RECORD_LEN, SEEK_SET ) == -1 ) {
rc = gpg_error_from_errno (errno);
err = gpg_error_from_errno (errno);
log_error(_("trustdb: lseek failed: %s\n"), strerror(errno) );
return rc;
return err;
}
n = read( db_fd, readbuf, TRUST_RECORD_LEN);
if( !n ) {
return -1; /* eof */
}
else if( n != TRUST_RECORD_LEN ) {
rc = gpg_error_from_errno (errno);
err = gpg_error_from_errno (errno);
log_error(_("trustdb: read failed (n=%d): %s\n"), n,
strerror(errno) );
return rc;
return err;
}
buf = readbuf;
}
@ -1195,7 +1188,7 @@ tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected )
if( expected && rec->rectype != expected ) {
log_error("%lu: read expected rec type %d, got %d\n",
recnum, expected, rec->rectype );
return GPG_ERR_TRUSTDB;
return gpg_error (GPG_ERR_TRUSTDB);
}
p++; /* skip reserved byte */
switch( rec->rectype ) {
@ -1204,7 +1197,7 @@ tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected )
case RECTYPE_VER: /* version record */
if( memcmp(buf+1, "gpg", 3 ) ) {
log_error( _("%s: not a trustdb file\n"), db_name );
rc = GPG_ERR_TRUSTDB;
err = gpg_error (GPG_ERR_TRUSTDB);
}
p += 2; /* skip "gpg" */
rec->r.ver.version = *p++;
@ -1223,12 +1216,12 @@ tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected )
if( recnum ) {
log_error( _("%s: version record with recnum %lu\n"), db_name,
(ulong)recnum );
rc = GPG_ERR_TRUSTDB;
err = gpg_error (GPG_ERR_TRUSTDB);
}
else if( rec->r.ver.version != 3 ) {
log_error( _("%s: invalid file version %d\n"), db_name,
rec->r.ver.version );
rc = GPG_ERR_TRUSTDB;
err = gpg_error (GPG_ERR_TRUSTDB);
}
break;
case RECTYPE_FREE:
@ -1263,11 +1256,11 @@ tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected )
default:
log_error( "%s: invalid record type %d at recnum %lu\n",
db_name, rec->rectype, (ulong)recnum );
rc = GPG_ERR_TRUSTDB;
err = gpg_error (GPG_ERR_TRUSTDB);
break;
}
return rc;
return err;
}
/****************
@ -1379,7 +1372,7 @@ tdbio_delete_record( ulong recnum )
rc = tdbio_read_record( 0, &vr, RECTYPE_VER );
if( rc )
log_fatal( _("%s: error reading version record: %s\n"),
db_name, gpg_strerror (rc) );
db_name, g10_errstr(rc) );
rec.recnum = recnum;
rec.rectype = RECTYPE_FREE;
@ -1406,13 +1399,13 @@ tdbio_new_recnum()
rc = tdbio_read_record( 0, &vr, RECTYPE_VER );
if( rc )
log_fatal( _("%s: error reading version record: %s\n"),
db_name, gpg_strerror (rc) );
db_name, g10_errstr(rc) );
if( vr.r.ver.firstfree ) {
recnum = vr.r.ver.firstfree;
rc = tdbio_read_record( recnum, &rec, RECTYPE_FREE );
if( rc ) {
log_error( _("%s: error reading free record: %s\n"),
db_name, gpg_strerror (rc) );
db_name, g10_errstr(rc) );
return rc;
}
/* update dir record */
@ -1420,7 +1413,7 @@ tdbio_new_recnum()
rc = tdbio_write_record( &vr );
if( rc ) {
log_error( _("%s: error writing dir record: %s\n"),
db_name, gpg_strerror (rc) );
db_name, g10_errstr(rc) );
return rc;
}
/*zero out the new record */
@ -1430,7 +1423,7 @@ tdbio_new_recnum()
rc = tdbio_write_record( &rec );
if( rc )
log_fatal(_("%s: failed to zero a record: %s\n"),
db_name, gpg_strerror (rc));
db_name, g10_errstr(rc));
}
else { /* not found, append a new record */
offset = lseek( db_fd, 0, SEEK_END );
@ -1460,7 +1453,7 @@ tdbio_new_recnum()
if( rc )
log_fatal(_("%s: failed to append a record: %s\n"),
db_name, gpg_strerror (rc));
db_name, g10_errstr(rc));
}
return recnum ;
}
@ -1508,129 +1501,3 @@ tdbio_invalid(void)
g10_exit(2);
}
/*
* Migrate the trustdb as just up to gpg 1.0.6 (trustdb version 2)
* to the 2.1 version as used with 1.0.6b - This is pretty trivial as needs
* only to scan the tdb and insert new the new trust records. The old ones are
* obsolte from now on
*/
static void
migrate_from_v2 ()
{
TRUSTREC rec;
int i, n;
struct {
ulong keyrecno;
byte ot;
byte okay;
byte fpr[20];
} *ottable;
int ottable_size, ottable_used;
byte oldbuf[40];
ulong recno;
int rc, count;
ottable_size = 5;
ottable = xmalloc (ottable_size * sizeof *ottable);
ottable_used = 0;
/* We have some restrictions here. We can't use the version record
* and we can't use any of the old hashtables because we dropped the
* code. So we first collect all ownertrusts and then use a second
* pass fo find the associated keys. We have to do this all without using
* the regular record read functions.
*/
/* get all the ownertrusts */
if (lseek (db_fd, 0, SEEK_SET ) == -1 )
log_fatal ("migrate_from_v2: lseek failed: %s\n", strerror (errno));
for (recno=0;;recno++)
{
do
n = read (db_fd, oldbuf, 40);
while (n==-1 && errno == EINTR);
if (!n)
break; /* eof */
if (n != 40)
log_fatal ("migrate_vfrom_v2: read error or short read\n");
if (*oldbuf != 2)
continue;
/* v2 dir record */
if (ottable_used == ottable_size)
{
ottable_size += 1000;
ottable = xrealloc (ottable, ottable_size * sizeof *ottable);
}
ottable[ottable_used].keyrecno = buftoulong (oldbuf+6);
ottable[ottable_used].ot = oldbuf[18];
ottable[ottable_used].okay = 0;
memset (ottable[ottable_used].fpr,0, 20);
if (ottable[ottable_used].keyrecno && ottable[ottable_used].ot)
ottable_used++;
}
log_info ("found %d ownertrust records\n", ottable_used);
/* Read again and find the fingerprints */
if (lseek (db_fd, 0, SEEK_SET ) == -1 )
log_fatal ("migrate_from_v2: lseek failed: %s\n", strerror (errno));
for (recno=0;;recno++)
{
do
n = read (db_fd, oldbuf, 40);
while (n==-1 && errno == EINTR);
if (!n)
break; /* eof */
if (n != 40)
log_fatal ("migrate_from_v2: read error or short read\n");
if (*oldbuf != 3)
continue;
/* v2 key record */
for (i=0; i < ottable_used; i++)
{
if (ottable[i].keyrecno == recno)
{
memcpy (ottable[i].fpr, oldbuf+20, 20);
ottable[i].okay = 1;
break;
}
}
}
/* got everything - create the v3 trustdb */
if (ftruncate (db_fd, 0))
log_fatal ("can't truncate `%s': %s\n", db_name, strerror (errno) );
if (create_version_record ())
log_fatal ("failed to recreate version record of `%s'\n", db_name);
/* access the hash table, so it is store just after the version record,
* this is not needed put a dump is more pretty */
get_trusthashrec ();
/* And insert the old ownertrust values */
count = 0;
for (i=0; i < ottable_used; i++)
{
if (!ottable[i].okay)
continue;
memset (&rec, 0, sizeof rec);
rec.recnum = tdbio_new_recnum ();
rec.rectype = RECTYPE_TRUST;
memcpy(rec.r.trust.fingerprint, ottable[i].fpr, 20);
rec.r.trust.ownertrust = ottable[i].ot;
if (tdbio_write_record (&rec))
log_fatal ("failed to write trust record of `%s'\n", db_name);
count++;
}
revalidation_mark ();
rc = tdbio_sync ();
if (rc)
log_fatal ("failed to sync `%s'\n", db_name);
log_info ("migrated %d version 2 ownertrusts\n", count);
xfree (ottable);
}

View File

@ -15,7 +15,8 @@
*
* 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
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
#ifndef G10_TDBIO_H

View File

@ -1,5 +1,5 @@
/* textfilter.c
* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
* Copyright (C) 1998, 1999, 2000, 2001, 2004 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -15,7 +15,8 @@
*
* 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
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
#include <config.h>
@ -28,11 +29,11 @@
#include "gpg.h"
#include "errors.h"
#include "iobuf.h"
#include "memory.h"
#include "util.h"
#include "filter.h"
#include "i18n.h"
#include "options.h"
#include "status.h"
#ifdef HAVE_DOSISH_SYSTEM
#define LF "\r\n"
@ -62,17 +63,9 @@ len_without_trailing_chars( byte *line, unsigned len, const char *trimchars )
return mark? (mark - line) : len;
}
unsigned
len_without_trailing_ws( byte *line, unsigned len )
{
return len_without_trailing_chars( line, len, " \t\r\n" );
}
static int
standard( text_filter_context_t *tfx, iobuf_t a,
standard( text_filter_context_t *tfx, IOBUF a,
byte *buf, size_t size, size_t *ret_len)
{
int rc=0;
@ -102,7 +95,30 @@ standard( text_filter_context_t *tfx, iobuf_t a,
break;
}
lf_seen = tfx->buffer[tfx->buffer_len-1] == '\n';
tfx->buffer_len = trim_trailing_ws( tfx->buffer, tfx->buffer_len );
/* The story behind this is that 2440 says that textmode
hashes should canonicalize line endings to CRLF and remove
spaces and tabs. 2440bis-12 says to just canonicalize to
CRLF. 1.4.0 was released using the bis-12 behavior, but it
was discovered that many mail clients do not canonicalize
PGP/MIME signature text appropriately (and were relying on
GnuPG to handle trailing spaces). So, we default to the
2440 behavior, but use the 2440bis-12 behavior if the user
specifies --no-rfc2440-text. The default will be changed
at some point in the future when the mail clients have been
upgraded. Aside from PGP/MIME and broken mail clients,
this makes no difference to any signatures in the real
world except for a textmode detached signature. PGP always
used the 2440bis-12 behavior (ignoring 2440 itself), so
this actually makes us compatible with PGP textmode
detached signatures for the first time. */
if(opt.rfc2440_text)
tfx->buffer_len=trim_trailing_chars(tfx->buffer,tfx->buffer_len,
" \t\r\n");
else
tfx->buffer_len=trim_trailing_chars(tfx->buffer,tfx->buffer_len,
"\r\n");
if( lf_seen ) {
tfx->buffer[tfx->buffer_len++] = '\r';
tfx->buffer[tfx->buffer_len++] = '\n';
@ -113,15 +129,13 @@ standard( text_filter_context_t *tfx, iobuf_t a,
}
/****************
* The filter is used to make canonical text: Lines are terminated by
* CR, LF, trailing white spaces are removed.
*/
int
text_filter( void *opaque, int control,
iobuf_t a, byte *buf, size_t *ret_len)
IOBUF a, byte *buf, size_t *ret_len)
{
size_t size = *ret_len;
text_filter_context_t *tfx = opaque;
@ -134,7 +148,7 @@ text_filter( void *opaque, int control,
if( tfx->truncated )
log_error(_("can't handle text lines longer than %d characters\n"),
MAX_LINELEN );
xfree ( tfx->buffer );
xfree( tfx->buffer );
tfx->buffer = NULL;
}
else if( control == IOBUFCTRL_DESC )
@ -148,13 +162,13 @@ text_filter( void *opaque, int control,
* md is updated as required by rfc2440
*/
int
copy_clearsig_text( iobuf_t out, iobuf_t inp, MD_HANDLE md,
copy_clearsig_text( IOBUF out, IOBUF inp, gcry_md_hd_t md,
int escape_dash, int escape_from, int pgp2mode )
{
unsigned maxlen;
unsigned int maxlen;
byte *buffer = NULL; /* malloced buffer */
unsigned bufsize; /* and size of this buffer */
unsigned n;
unsigned int bufsize; /* and size of this buffer */
unsigned int n;
int truncated = 0;
int pending_lf = 0;
@ -164,6 +178,8 @@ copy_clearsig_text( iobuf_t out, iobuf_t inp, MD_HANDLE md,
if( !escape_dash )
escape_from = 0;
write_status (STATUS_BEGIN_SIGNING);
for(;;) {
maxlen = MAX_LINELEN;
n = iobuf_read_line( inp, &buffer, &bufsize, &maxlen );
@ -176,15 +192,16 @@ copy_clearsig_text( iobuf_t out, iobuf_t inp, MD_HANDLE md,
/* update the message digest */
if( escape_dash ) {
if( pending_lf ) {
gcry_md_putc( md, '\r' );
gcry_md_putc( md, '\n' );
gcry_md_putc ( md, '\r' );
gcry_md_putc ( md, '\n' );
}
gcry_md_write( md, buffer,
len_without_trailing_chars( buffer, n,
pgp2mode? " \r\n":" \t\r\n"));
gcry_md_write ( md, buffer,
len_without_trailing_chars (buffer, n,
pgp2mode?
" \r\n":" \t\r\n"));
}
else
gcry_md_write( md, buffer, n );
gcry_md_write ( md, buffer, n );
pending_lf = buffer[n-1] == '\n';
/* write the output */

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
/* trustdb.h - Trust database
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003
* Free Software Foundation, Inc.
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004,
* 2005 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -16,13 +16,13 @@
*
* 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
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
#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/assigned */
@ -38,19 +38,26 @@
#define TRUST_FLAG_DISABLED 128 /* d: key/uid disabled */
#define TRUST_FLAG_PENDING_CHECK 256 /* a check-trustdb is pending */
#define NAMEHASH_HASH DIGEST_ALGO_RMD160
#define NAMEHASH_LEN 20
/*-- trustdb.c --*/
void register_trusted_keyid(u32 *keyid);
void register_trusted_key( const char *string );
void check_trustdb (void);
void update_trustdb (void);
int setup_trustdb( int level, const char *dbname );
void init_trustdb( void );
void check_trustdb_stale(void);
void sync_trustdb( void );
const char *uid_trust_string_fixed(PKT_public_key *key,PKT_user_id *uid);
const char *trust_value_to_string (unsigned int value);
int string_to_trust_value (const char *str);
void revalidation_mark (void);
int trustdb_pending_check(void);
void trustdb_check_or_update(void);
int cache_disabled_value(PKT_public_key *pk);
@ -75,6 +82,11 @@ const char *get_ownertrust_string (PKT_public_key *pk);
void update_ownertrust (PKT_public_key *pk, unsigned int new_trust );
int clear_ownertrusts (PKT_public_key *pk);
void clean_one_uid(KBNODE keyblock,KBNODE uidnode,int noisy,int self_only,
int *uids_cleaned,int *sigs_cleaned);
void clean_key(KBNODE keyblock,int noisy,int self_only,
int *uids_cleaned,int *sigs_cleaned);
/*-- tdbdump.c --*/
void list_trustdb(const char *username);
void export_ownertrust(void);

View File

@ -1,5 +1,5 @@
/* verify.c - verify signed data
* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
/* verify.c - Verify signed data
* Copyright (C) 1998, 1999, 2000, 2001, 2004 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -15,7 +15,8 @@
*
* 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
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
#include <config.h>
@ -24,14 +25,13 @@
#include <string.h>
#include <errno.h>
#include <assert.h>
#include <unistd.h> /* for isatty() */
#include "gpg.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"
@ -54,7 +54,7 @@
int
verify_signatures( int nfiles, char **files )
{
iobuf_t fp;
IOBUF fp;
armor_filter_context_t afx;
progress_filter_context_t pfx;
const char *sigfile;
@ -91,11 +91,17 @@ verify_signatures( int nfiles, char **files )
/* open the signature file */
fp = iobuf_open(sigfile);
if (fp && is_secured_file (iobuf_get_fd (fp)))
{
iobuf_close (fp);
fp = NULL;
errno = EPERM;
}
if( !fp ) {
rc = gpg_error_from_errno (errno);
log_error(_("can't open `%s': %s\n"),
print_fname_stdin(sigfile), strerror (errno));
return rc;
return rc;
}
handle_progress (&pfx, fp, sigfile);
@ -103,12 +109,12 @@ verify_signatures( int nfiles, char **files )
iobuf_push_filter( fp, armor_filter, &afx );
sl = NULL;
for(i=1 ; i < nfiles; i++ )
for(i=nfiles-1 ; i > 0 ; i-- )
add_to_strlist( &sl, files[i] );
rc = proc_signature_packets( NULL, fp, sl, sigfile );
free_strlist(sl);
iobuf_close(fp);
if( afx.no_openpgp_data && rc == -1 ) {
if( (afx.no_openpgp_data && rc == -1) || rc == G10ERR_NO_DATA ) {
log_error(_("the signature could not be verified.\n"
"Please remember that the signature file (.sig or .asc)\n"
"should be the first file given on the command line.\n") );
@ -122,23 +128,31 @@ verify_signatures( int nfiles, char **files )
void
print_file_status( int status, const char *name, int what )
{
char *p = xmalloc (strlen(name)+10);
char *p = xmalloc(strlen(name)+10);
sprintf(p, "%d %s", what, name );
write_status_text( status, p );
xfree (p);
xfree(p);
}
static int
verify_one_file( const char *name )
{
iobuf_t fp;
IOBUF fp;
armor_filter_context_t afx;
progress_filter_context_t pfx;
int rc;
print_file_status( STATUS_FILE_START, name, 1 );
fp = iobuf_open(name);
if (fp)
iobuf_ioctl (fp,3,1,NULL); /* disable fd caching */
if (fp && is_secured_file (iobuf_get_fd (fp)))
{
iobuf_close (fp);
fp = NULL;
errno = EPERM;
}
if( !fp ) {
rc = gpg_error_from_errno (errno);
log_error(_("can't open `%s': %s\n"),
@ -179,7 +193,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 GPG_ERR_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

View File

@ -1,3 +1,7 @@
2006-04-18 Werner Koch <wk@g10code.com>
* keyserver.h, i18n.h, http.h, cipher.h: Updated to gpg 1.4.3.
2003-09-04 David Shaw <dshaw@jabberwocky.com>
* cipher.h: Drop TIGER/192 support.

View File

@ -1,97 +1,101 @@
/* cipher.h
* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
/* cipher.h - Definitions for OpenPGP
* Copyright (C) 1998, 1999, 2000, 2001, 2006 Free Software Foundation, Inc.
*
* This file is part of GNUPG.
* This file is part of GnuPG.
*
* GNUPG is free software; you can redistribute it and/or modify
* 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,
* 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
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
#ifndef G10_CIPHER_H
#define G10_CIPHER_H
#include <gcrypt.h>
#define CIPHER_ALGO_NONE GCRY_CIPHER_NONE
#define CIPHER_ALGO_IDEA GCRY_CIPHER_IDEA
#define CIPHER_ALGO_3DES GCRY_CIPHER_3DES
#define CIPHER_ALGO_CAST5 GCRY_CIPHER_CAST5
#define CIPHER_ALGO_BLOWFISH GCRY_CIPHER_BLOWFISH /* 128 bit */
#define CIPHER_ALGO_SAFER_SK128 GCRY_CIPHER_SK128
#define CIPHER_ALGO_DES_SK GCRY_CIPHER_DES_SK
#define CIPHER_ALGO_AES GCRY_CIPHER_AES
#define CIPHER_ALGO_AES192 GCRY_CIPHER_AES192
#define CIPHER_ALGO_AES256 GCRY_CIPHER_AES256
/* Macros for compatibility with older libgcrypt versions. */
#ifndef GCRY_PK_USAGE_CERT
# define GCRY_PK_USAGE_CERT 4
# define GCRY_PK_USAGE_AUTH 8
# define GCRY_PK_USAGE_UNKN 128
#endif
/* Constants for OpenPGP. */
#define CIPHER_ALGO_NONE /* 0 */ GCRY_CIPHER_NONE
#define CIPHER_ALGO_IDEA /* 1 */ GCRY_CIPHER_IDEA
#define CIPHER_ALGO_3DES /* 2 */ GCRY_CIPHER_3DES
#define CIPHER_ALGO_CAST5 /* 3 */ GCRY_CIPHER_CAST5
#define CIPHER_ALGO_BLOWFISH /* 4 */ GCRY_CIPHER_BLOWFISH /* 128 bit */
/* 5 & 6 are reserved */
#define CIPHER_ALGO_AES /* 7 */ GCRY_CIPHER_AES
#define CIPHER_ALGO_AES192 /* 8 */ GCRY_CIPHER_AES192
#define CIPHER_ALGO_AES256 /* 9 */ GCRY_CIPHER_AES256
#define CIPHER_ALGO_RIJNDAEL CIPHER_ALGO_AES
#define CIPHER_ALGO_RIJNDAEL192 CIPHER_ALGO_AES192
#define CIPHER_ALGO_RIJNDAEL256 CIPHER_ALGO_AES256
#define CIPHER_ALGO_TWOFISH GCRY_CIPHER_TWOFISH /* 256 bit */
#define CIPHER_ALGO_DUMMY 110 /* no encryption at all */
#define CIPHER_ALGO_TWOFISH /* 10 */ GCRY_CIPHER_TWOFISH /* 256 bit */
#define CIPHER_ALGO_DUMMY 110 /* No encryption at all. */
#define PUBKEY_ALGO_RSA GCRY_PK_RSA
#define PUBKEY_ALGO_RSA_E GCRY_PK_RSA_E
#define PUBKEY_ALGO_RSA_S GCRY_PK_RSA_S
#define PUBKEY_ALGO_ELGAMAL_E GCRY_PK_ELG_E
#define PUBKEY_ALGO_DSA GCRY_PK_DSA
#define PUBKEY_ALGO_ELGAMAL GCRY_PK_ELG
#define PUBKEY_ALGO_RSA /* 1 */ GCRY_PK_RSA
#define PUBKEY_ALGO_RSA_E /* 2 */ GCRY_PK_RSA_E /* RSA encrypt only. */
#define PUBKEY_ALGO_RSA_S /* 3 */ GCRY_PK_RSA_S /* RSA sign only. */
#define PUBKEY_ALGO_ELGAMAL_E /* 16 */ GCRY_PK_ELG_E /* Elgamal encr only */
#define PUBKEY_ALGO_DSA /* 17 */ GCRY_PK_DSA
#define PUBKEY_ALGO_ELGAMAL /* 20 */ GCRY_PK_ELG /* Elgamal encr+sign */
#define PUBKEY_USAGE_SIG GCRY_PK_USAGE_SIGN
#define PUBKEY_USAGE_ENC GCRY_PK_USAGE_ENCR
#define PUBKEY_USAGE_CERT 4 /* key is also good to certify other keys*/
#define PUBKEY_USAGE_AUTH 8
#define PUBKEY_USAGE_SIG GCRY_PK_USAGE_SIGN /* Good for signatures. */
#define PUBKEY_USAGE_ENC GCRY_PK_USAGE_ENCR /* Good for encryption. */
#define PUBKEY_USAGE_CERT GCRY_PK_USAGE_CERT /* Also good to certify keys. */
#define PUBKEY_USAGE_AUTH GCRY_PK_USAGE_AUTH /* Good for authentication. */
#define PUBKEY_USAGE_UNKNOWN GCRY_PK_USAGE_UNKN /* Unknown usage flag. */
#define DIGEST_ALGO_MD5 GCRY_MD_MD5
#define DIGEST_ALGO_SHA1 GCRY_MD_SHA1
#define DIGEST_ALGO_RMD160 GCRY_MD_RMD160
#define DIGEST_ALGO_SHA256 GCRY_MD_SHA256
#define DIGEST_ALGO_SHA384 GCRY_MD_SHA384
#define DIGEST_ALGO_SHA512 GCRY_MD_SHA512
#define DIGEST_ALGO_MD5 /* 1 */ GCRY_MD_MD5
#define DIGEST_ALGO_SHA1 /* 2 */ GCRY_MD_SHA1
#define DIGEST_ALGO_RMD160 /* 3 */ GCRY_MD_RMD160
/* 4, 5, 6, and 7 are reserved */
#define DIGEST_ALGO_SHA256 /* 8 */ GCRY_MD_SHA256
#define DIGEST_ALGO_SHA384 /* 9 */ GCRY_MD_SHA384
#define DIGEST_ALGO_SHA512 /* 10 */ GCRY_MD_SHA512
#define COMPRESS_ALGO_NONE 0
#define COMPRESS_ALGO_ZIP 1
#define COMPRESS_ALGO_ZLIB 2
#define COMPRESS_ALGO_BZIP2 3
#define is_RSA(a) ((a)==PUBKEY_ALGO_RSA || (a)==PUBKEY_ALGO_RSA_E \
|| (a)==PUBKEY_ALGO_RSA_S )
#define is_ELGAMAL(a) ((a)==PUBKEY_ALGO_ELGAMAL || (a)==PUBKEY_ALGO_ELGAMAL_E)
#define is_ELGAMAL(a) ((a)==PUBKEY_ALGO_ELGAMAL_E)
#define is_DSA(a) ((a)==PUBKEY_ALGO_DSA)
typedef struct {
int algo;
int keylen;
int algo_info_printed;
int use_mdc;
byte key[32]; /* this is the largest used keylen (256 bit) */
/* The data encryption key object. */
typedef struct
{
int algo;
int keylen;
int algo_info_printed;
int use_mdc;
int symmetric;
byte key[32]; /* This is the largest used keylen (256 bit). */
} DEK;
#ifndef EXTERN_UNLESS_MAIN_MODULE
#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 int g10_opt_verbose;
EXTERN_UNLESS_MAIN_MODULE const char *g10_opt_homedir;
/* Constants to allocate static MPI arrays. */
#define PUBKEY_MAX_NPKEY 4
#define PUBKEY_MAX_NSKEY 6
#define PUBKEY_MAX_NSIG 2
#define PUBKEY_MAX_NENC 2
#define MD_HANDLE gcry_md_hd_t
#define CIPHER_HANDLE gcry_cipher_hd_t
#endif /*G10_CIPHER_H*/

View File

@ -1,21 +1,22 @@
/* host2net.h - Some macros
* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
*
* This file is part of GNUPG.
* This file is part of GnuPG.
*
* GNUPG is free software; you can redistribute it and/or modify
* 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,
* 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
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
#ifndef G10_HOST2NET_H

View File

@ -1,5 +1,6 @@
/* http.h - HTTP protocol handler
* Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
* Copyright (C) 1999, 2000, 2001, 2003, 2004,
* 2005 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -15,12 +16,14 @@
*
* 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
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
#ifndef G10_HTTP_H
#define G10_HTTP_H 1
#include "iobuf.h"
#include "../common/iobuf.h"
struct uri_tuple {
struct uri_tuple *next;
@ -34,6 +37,7 @@ typedef struct uri_tuple *URI_TUPLE;
struct parsed_uri {
/* all these pointers point into buffer; most stuff is not escaped */
char *scheme; /* pointer to the scheme string (lowercase) */
char *auth; /* username/password for basic auth */
char *host; /* host (converted to lowercase) */
ushort port; /* port (always set if the host is set) */
char *path; /* the path */
@ -49,19 +53,20 @@ typedef enum {
HTTP_REQ_POST = 3
} HTTP_REQ_TYPE;
enum { /* put flag values into an enum, so that gdb can display them */
HTTP_FLAG_TRY_PROXY = 1,
HTTP_FLAG_NO_SHUTDOWN = 2,
HTTP_FLAG_TRY_SRV = 3
};
/* put flag values into an enum, so that gdb can display them */
enum
{
HTTP_FLAG_NO_SHUTDOWN = 1,
HTTP_FLAG_TRY_SRV = 2
};
struct http_context {
int initialized;
unsigned int status_code;
int sock;
int in_data;
IOBUF fp_read;
IOBUF fp_write;
iobuf_t fp_read;
iobuf_t fp_write;
int is_http_0_9;
PARSED_URI uri;
HTTP_REQ_TYPE req_type;
@ -72,11 +77,11 @@ struct http_context {
typedef struct http_context *HTTP_HD;
int http_open( HTTP_HD hd, HTTP_REQ_TYPE reqtype, const char *url,
unsigned int flags );
char *auth, unsigned int flags, const char *proxy );
void http_start_data( HTTP_HD hd );
int http_wait_response( HTTP_HD hd, unsigned int *ret_status );
void http_close( HTTP_HD hd );
int http_open_document( HTTP_HD hd, const char *document, unsigned int flags );
int http_open_document( HTTP_HD hd, const char *document, char *auth,
unsigned int flags, const char *proxy );
#endif /*G10_HTTP_H*/

View File

@ -15,14 +15,15 @@
*
* 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
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
#ifndef G10_I18N_H
#define G10_I18N_H
#ifdef USE_SIMPLE_GETTEXT
int set_gettext_file( const char *filename );
int set_gettext_file( const char *filename, const char *regkey );
const char *gettext( const char *msgid );
#define _(a) gettext (a)

View File

@ -1,21 +1,22 @@
/* keyserver.h
* Copyright (C) 2001, 2002 Free Software Foundation, Inc.
*
* This file is part of GNUPG.
* This file is part of GnuPG.
*
* GNUPG is free software; you can redistribute it and/or modify
* 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,
* 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
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
#ifndef _KEYSERVER_H_
@ -35,6 +36,7 @@
#define KEYSERVER_KEY_EXISTS 7 /* key already exists */
#define KEYSERVER_KEY_INCOMPLETE 8 /* key incomplete (EOF) */
#define KEYSERVER_UNREACHABLE 9 /* unable to contact keyserver */
#define KEYSERVER_TIMEOUT 10 /* timeout while accessing keyserver */
/* Must be 127 due to shell internal magic. */
#define KEYSERVER_SCHEME_NOT_FOUND 127

View File

@ -21,6 +21,8 @@
#ifndef G10_MEMORY_H
#define G10_MEMORY_H
#error this file should not be used anymore
#ifdef M_DEBUG
#ifndef STR
#define STR(v) #v

View File

@ -30,6 +30,8 @@
#ifndef G10_MPI_H
#define G10_MPI_H
#error this file should not be used anymore
#include <gcrypt.h>
#if 0

View File

@ -1,21 +1,22 @@
/* types.h - some common typedefs
* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
*
* This file is part of GNUPG.
* This file is part of GnuPG.
*
* GNUPG is free software; you can redistribute it and/or modify
* 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,
* 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
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
#ifndef G10_TYPES_H

View File

@ -20,7 +20,7 @@
#ifndef G10_UTIL_H
#define G10_UTIL_H
#warning oops, using old util.h
#error this file should not be used anymore
#if 0 /* Dont use it anymore */
#if defined (__MINGW32__) || defined (__CYGWIN32__)

View File

@ -15,7 +15,8 @@
*
* 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
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
#ifndef G10_ZLIB_RISCOS_H
#define G10_ZLIB_RISCOS_H

View File

@ -1,3 +1,8 @@
2006-04-18 Werner Koch <wk@g10code.com>
* libjnlib-config.h (JNLIB_NEED_UTF8CONF): Defined.
* strlist.c (add_to_strlist2) [JNLIB_NEED_UTF8CONV]: Enabled.
2005-06-15 Werner Koch <wk@g10code.com>
* stringhelp.c (sanitize_buffer): Make P a void*.

View File

@ -1,5 +1,5 @@
/* libjnlib-config.h - local configuration of the jnlib functions
* Copyright (C) 2000, 2001 Free Software Foundation, Inc.
* Copyright (C) 2000, 2001, 2006 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -29,6 +29,9 @@
#include <gcrypt.h> /* gcry_malloc & Cie. */
#include "logging.h"
/* We require support for utf-8 conversion. */
#define JNLIB_NEED_UTF8CONF 1
#ifdef USE_SIMPLE_GETTEXT
int set_gettext_file( const char *filename );
const char *gettext( const char *msgid );

View File

@ -1,5 +1,5 @@
/* strlist.c - string helpers
* Copyright (C) 1998, 2000, 2001 Free Software Foundation, Inc.
* Copyright (C) 1998, 2000, 2001, 2006 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -26,7 +26,9 @@
#include "libjnlib-config.h"
#include "strlist.h"
#ifdef JNLIB_NEED_UTF8CONV
#include "utf8conv.h"
#endif
void
free_strlist( strlist_t sl )
@ -53,26 +55,26 @@ add_to_strlist( strlist_t *list, const char *string )
return sl;
}
#if 0
/****************
* same as add_to_strlist() but if is_utf8 is *not* set a conversion
* to UTF8 is done
*/
/* Same as add_to_strlist() but if is_utf8 is *not* set, a conversion
to UTF-8 is done. */
#ifdef JNLIB_NEED_UTF8CONV
strlist_t
add_to_strlist2( strlist_t *list, const char *string, int is_utf8 )
{
strlist_t sl;
if( is_utf8 )
sl = add_to_strlist( list, string );
else {
char *p = native_to_utf8( string );
sl = add_to_strlist( list, p );
m_free( p );
strlist_t sl;
if (is_utf8)
sl = add_to_strlist( list, string );
else
{
char *p = native_to_utf8( string );
sl = add_to_strlist( list, p );
jnlib_free ( p );
}
return sl;
return sl;
}
#endif
#endif /* JNLIB_NEED_UTF8CONV*/
strlist_t
append_to_strlist( strlist_t *list, const char *string )

View File

@ -32,8 +32,7 @@ typedef struct string_list *strlist_t;
void free_strlist (strlist_t sl);
strlist_t add_to_strlist (strlist_t *list, const char *string);
/*strlist_t add_to_strlist2( strlist_t *list,
const char *string, int is_utf8);*/
strlist_t add_to_strlist2( strlist_t *list, const char *string, int is_utf8);
strlist_t append_to_strlist (strlist_t *list, const char *string);