1
0
mirror of git://git.gnupg.org/gnupg.git synced 2024-11-10 21:38:50 +01:00

added more stuff

This commit is contained in:
Werner Koch 1998-01-02 20:40:10 +00:00
parent 4d2636eafe
commit b7bdef0834
23 changed files with 639 additions and 224 deletions

84
README
View File

@ -51,7 +51,6 @@
Key Generation Key Generation
-------------- --------------
Create a key pair with this command:
g10 --gen-key g10 --gen-key
@ -59,7 +58,7 @@
good random numbers for prime number generation, it uses a /dev/random good random numbers for prime number generation, it uses a /dev/random
which will emit only bytes if the kernel can gather enough entropy. which will emit only bytes if the kernel can gather enough entropy.
If you see no progress, you should start some other activities such If you see no progress, you should start some other activities such
as a mouse moves or a "find /". Because we have no hardware device as mouse moves or a "find /". Because we have no hardware device
to generate random we have to use this method. to generate random we have to use this method.
Key generation shows progress by printing different characters to Key generation shows progress by printing different characters to
@ -89,9 +88,25 @@
9) Find a generator for that prime. 9) Find a generator for that prime.
Signatures You can sign a key with this command:
----------
To create a signature, use this: g10 --sign-key Donald
To sign the key of of "Donald" with your default userid
g10 --sign-key -u Karl -u Joe Donald
To sign the key of of "Donald" with the userids of "Karl" and "Joe".
All existing signatures are checked, if some are invalid, a menu is
offered to delete some of them, and the you are asked for every user
wether you want to sign this key.
You may remove a signature at any time by usiing the option "--edit-sig",
which also asks for the sigs to remove.
Sign
----
g10 -s file g10 -s file
@ -106,9 +121,9 @@
Creates a signature of file, but writes the output to the file "out". Creates a signature of file, but writes the output to the file "out".
Encryption
---------- Encrypt
To encrypt data use this: -------
g10 -e -r heine file g10 -e -r heine file
@ -120,6 +135,51 @@
Ditto, but encrypts "hallo\n" and mails it as ascii armored message. Ditto, but encrypts "hallo\n" and mails it as ascii armored message.
Sign and Encrypt
----------------
g10 -se -r heine file
This encrypts files with the public key of "heine" and writes it
to "file.g10" after signing it with the default user id.
g10 -se -r heine -u Suttner file
Ditto, but sign the file with the user id "Suttner"
Examine a data or key file
--------------------------
g10 --list-packets datafile
Use this to list the contents of a data file. If the file is encrypted
you are asked for the passphrase, so that G10 is able to look at the
inner structure of a encrypted packet.
Batch mode
----------
If you use the option "--batch", G10 runs in non-interactive mode and
never prompts for input data. This even does not allow to enter
passphrase; until we have a better solution (something like ssh-agent),
you can use the option "--passhrase-fd n", which works like PGPs
PGPPASSFD.
Batch mode also causes PGP to terminate as soon as a BAD signature is
detected.
Exit status
-----------
G10 returns with an exit status of 1 if in batch mode and a bad signature
has been detected or 2 or higher for all other errors. You should parse
stderr to get detailed informations about the errors.
Debug Flags Debug Flags
----------- -----------
Use the option "--debug n" to output debug informations. This option Use the option "--debug n" to output debug informations. This option
@ -146,18 +206,10 @@
I will run "indent" over the source when making a real distribution, I will run "indent" over the source when making a real distribution,
but for now I stick to my own formatting rules. but for now I stick to my own formatting rules.
Compression does not work always; this is the reason that "-z 0"
is the default.
This will be cleaned up of course.
The primary FTP site is "ftp://ftp.guug.de/pub/gcrypt/" The primary FTP site is "ftp://ftp.guug.de/pub/gcrypt/"
The primary WWW page is "http://www.d.shuttle.de/isil/g10.html" The primary WWW page is "http://www.d.shuttle.de/isil/g10.html"
Please direct bug reports to <g10-bugs@isil.d.shuttle.de> or better Please direct bug reports to <g10-bugs@isil.d.shuttle.de> or better
post them to the mailing list <g10@net.lut.ac.uk>. post them to the mailing list <g10@net.lut.ac.uk>.
Have fun
Werner

3
TODO
View File

@ -22,7 +22,6 @@
before we can check wether we have the pubkey or not. The one-pass before we can check wether we have the pubkey or not. The one-pass
signature packets should be implemented to avoid this. signature packets should be implemented to avoid this.
* compress does not work always!
* complete cipher/cast.c * complete cipher/cast.c
* complete cipher/dsa.c * complete cipher/dsa.c
@ -34,3 +33,5 @@
of the userid. of the userid.
[can be handles in get_pubkey_by_name()] [can be handles in get_pubkey_by_name()]
* armor has now some problems.

View File

@ -21,9 +21,12 @@
#include <config.h> #include <config.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <assert.h>
#include <errno.h> #include <errno.h>
#include <sys/time.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h> #include <fcntl.h>
#include "util.h" #include "util.h"
#include "cipher.h" #include "cipher.h"
@ -98,6 +101,7 @@ fill_buffer( byte *buffer, size_t length, int level )
static int fd_random = -1; static int fd_random = -1;
int fd; int fd;
int n; int n;
int warn=0;
if( level == 2 ) { if( level == 2 ) {
if( fd_random == -1 ) if( fd_random == -1 )
@ -112,11 +116,34 @@ fill_buffer( byte *buffer, size_t length, int level )
do { do {
fd_set rfds;
struct timeval tv;
int rc;
FD_ZERO(&rfds);
FD_SET(fd, &rfds);
tv.tv_sec = 3;
tv.tv_usec = 0;
if( !(rc=select(fd+1, &rfds, NULL, NULL, &tv)) ) {
if( !warn )
tty_printf(
"\nNot enough random bytes available. Please do some other work to give
the OS a chance to collect more entropy! (Need %d more bytes)\n", length );
warn = 1;
continue;
}
else if( rc == -1 ) {
tty_printf("select() error: %s\n", strerror(errno));
continue;
}
assert( length < 200 );
do { do {
n = read(fd, buffer, length ); n = read(fd, buffer, length );
} while( n == -1 && errno == EINTR ); } while( n == -1 && errno == EINTR );
if( n == -1 ) if( n == -1 )
log_fatal("read error on random device: %s\n", strerror(errno) ); log_fatal("read error on random device: %s\n", strerror(errno) );
assert( n <= length );
buffer += n; buffer += n;
length -= n; length -= n;
} while( length ); } while( length );

View File

@ -30,6 +30,7 @@ g10_SOURCES = g10.c \
options.h \ options.h \
openfile.c \ openfile.c \
keyid.c \ keyid.c \
trustdb.c \
packet.h \ packet.h \
parse-packet.c \ parse-packet.c \
passphrase.c \ passphrase.c \

View File

@ -68,6 +68,7 @@ g10_SOURCES = g10.c \
options.h \ options.h \
openfile.c \ openfile.c \
keyid.c \ keyid.c \
trustdb.c \
packet.h \ packet.h \
parse-packet.c \ parse-packet.c \
passphrase.c \ passphrase.c \
@ -100,8 +101,8 @@ LINK = $(CC) $(LDFLAGS) -o $@
g10_OBJECTS = g10.o build-packet.o compress.o encode.o encr-data.o \ g10_OBJECTS = g10.o build-packet.o compress.o encode.o encr-data.o \
free-packet.o getkey.o pkclist.o skclist.o ringedit.o kbnode.o keygen.o \ free-packet.o getkey.o pkclist.o skclist.o ringedit.o kbnode.o keygen.o \
mainproc.o armor.o mdfilter.o textfilter.o cipher.o elg.o rsa.o \ mainproc.o armor.o mdfilter.o textfilter.o cipher.o elg.o rsa.o \
openfile.o keyid.o parse-packet.o passphrase.o plaintext.o pubkey-enc.o \ openfile.o keyid.o trustdb.o parse-packet.o passphrase.o plaintext.o \
seckey-cert.o seskey.o sign.o comment.o sig-check.o pubkey-enc.o seckey-cert.o seskey.o sign.o comment.o sig-check.o
EXTRA_g10_SOURCES = EXTRA_g10_SOURCES =
g10_LDADD = $(LDADD) g10_LDADD = $(LDADD)
DIST_COMMON = Makefile.am Makefile.in DIST_COMMON = Makefile.am Makefile.in
@ -130,7 +131,8 @@ $(srcdir)/.deps/plaintext.P $(srcdir)/.deps/pubkey-enc.P \
$(srcdir)/.deps/ringedit.P $(srcdir)/.deps/rsa.P \ $(srcdir)/.deps/ringedit.P $(srcdir)/.deps/rsa.P \
$(srcdir)/.deps/seckey-cert.P $(srcdir)/.deps/seskey.P \ $(srcdir)/.deps/seckey-cert.P $(srcdir)/.deps/seskey.P \
$(srcdir)/.deps/sig-check.P $(srcdir)/.deps/sign.P \ $(srcdir)/.deps/sig-check.P $(srcdir)/.deps/sign.P \
$(srcdir)/.deps/skclist.P $(srcdir)/.deps/textfilter.P $(srcdir)/.deps/skclist.P $(srcdir)/.deps/textfilter.P \
$(srcdir)/.deps/trustdb.P
SOURCES = $(g10_SOURCES) SOURCES = $(g10_SOURCES)
OBJECTS = $(g10_OBJECTS) OBJECTS = $(g10_OBJECTS)

View File

@ -37,6 +37,7 @@
static int encode_simple( const char *filename, int mode ); static int encode_simple( const char *filename, int mode );
static int write_pubkey_enc_from_list( PKC_LIST pkc_list, DEK *dek, IOBUF out );
@ -164,7 +165,7 @@ encode_crypt( const char *filename, STRLIST remusr )
cipher_filter_context_t cfx; cipher_filter_context_t cfx;
armor_filter_context_t afx; armor_filter_context_t afx;
compress_filter_context_t zfx; compress_filter_context_t zfx;
PKC_LIST pkc_list, pkc_rover; PKC_LIST pkc_list;
memset( &cfx, 0, sizeof cfx); memset( &cfx, 0, sizeof cfx);
memset( &afx, 0, sizeof afx); memset( &afx, 0, sizeof afx);
@ -203,31 +204,9 @@ encode_crypt( const char *filename, STRLIST remusr )
if( DBG_CIPHER ) if( DBG_CIPHER )
log_hexdump("DEK is: ", cfx.dek->key, cfx.dek->keylen ); log_hexdump("DEK is: ", cfx.dek->key, cfx.dek->keylen );
/* loop over all public key certificates */ rc = write_pubkey_enc_from_list( pkc_list, cfx.dek, out );
for( pkc_rover=pkc_list; pkc_rover; pkc_rover = pkc_rover->next ) { if( rc )
PKT_public_cert *pkc; goto leave;
PKT_pubkey_enc *enc;
pkc = pkc_rover->pkc;
enc = m_alloc_clear( sizeof *enc );
enc->pubkey_algo = pkc->pubkey_algo;
if( enc->pubkey_algo == PUBKEY_ALGO_ELGAMAL )
g10_elg_encrypt( pkc, enc, cfx.dek );
else if( enc->pubkey_algo == PUBKEY_ALGO_RSA )
g10_rsa_encrypt( pkc, enc, cfx.dek );
else
log_bug(NULL);
/* and write it */
init_packet(&pkt);
pkt.pkttype = PKT_PUBKEY_ENC;
pkt.pkt.pubkey_enc = enc;
rc = build_packet( out, &pkt );
free_pubkey_enc(enc);
if( rc ) {
log_error("build pubkey_enc packet failed: %s\n", g10_errstr(rc) );
goto leave;
}
}
/* setup the inner packet */ /* setup the inner packet */
if( filename ) { if( filename ) {
@ -276,7 +255,6 @@ encode_crypt( const char *filename, STRLIST remusr )
/**************** /****************
* Filter to do a complete public key encryption. * Filter to do a complete public key encryption.
*/ */
#if 0
int int
encrypt_filter( void *opaque, int control, encrypt_filter( void *opaque, int control,
IOBUF a, byte *buf, size_t *ret_len) IOBUF a, byte *buf, size_t *ret_len)
@ -289,6 +267,24 @@ encrypt_filter( void *opaque, int control,
log_bug(NULL); /* not used */ log_bug(NULL); /* not used */
} }
else if( control == IOBUFCTRL_FLUSH ) { /* encrypt */ else if( control == IOBUFCTRL_FLUSH ) { /* encrypt */
if( !efx->header_okay ) {
efx->cfx.dek = m_alloc_secure( sizeof *efx->cfx.dek );
efx->cfx.dek->algo = DEFAULT_CIPHER_ALGO;
make_session_key( efx->cfx.dek );
if( DBG_CIPHER )
log_hexdump("DEK is: ",
efx->cfx.dek->key, efx->cfx.dek->keylen );
rc = write_pubkey_enc_from_list( efx->pkc_list, efx->cfx.dek, a );
if( rc )
return rc;
iobuf_push_filter( a, cipher_filter, &efx->cfx );
efx->header_okay = 1;
}
rc = iobuf_write( a, buf, size );
} }
else if( control == IOBUFCTRL_FREE ) { else if( control == IOBUFCTRL_FREE ) {
} }
@ -297,5 +293,41 @@ encrypt_filter( void *opaque, int control,
} }
return rc; return rc;
} }
#endif
/****************
* Write pubkey-enc packets from the list of PKCs to OUT.
*/
static int
write_pubkey_enc_from_list( PKC_LIST pkc_list, DEK *dek, IOBUF out )
{
PACKET pkt;
PKT_public_cert *pkc;
PKT_pubkey_enc *enc;
int rc;
for( ; pkc_list; pkc_list = pkc_list->next ) {
pkc = pkc_list->pkc;
enc = m_alloc_clear( sizeof *enc );
enc->pubkey_algo = pkc->pubkey_algo;
if( enc->pubkey_algo == PUBKEY_ALGO_ELGAMAL )
g10_elg_encrypt( pkc, enc, dek );
else if( enc->pubkey_algo == PUBKEY_ALGO_RSA )
g10_rsa_encrypt( pkc, enc, dek );
else
log_bug(NULL);
/* and write it */
init_packet(&pkt);
pkt.pkttype = PKT_PUBKEY_ENC;
pkt.pkt.pubkey_enc = enc;
rc = build_packet( out, &pkt );
free_pubkey_enc(enc);
if( rc ) {
log_error("build pubkey_enc packet failed: %s\n", g10_errstr(rc) );
return rc;
}
}
return 0;
}

View File

@ -65,6 +65,7 @@ typedef struct {
} cipher_filter_context_t; } cipher_filter_context_t;
typedef struct { typedef struct {
size_t linesize; size_t linesize;
byte *line; byte *line;
@ -73,6 +74,9 @@ typedef struct {
int eof; int eof;
} text_filter_context_t; } text_filter_context_t;
/* encrypt_filter_context_t defined in main.h */
/*-- mdfilter.c --*/ /*-- mdfilter.c --*/
int md_filter( void *opaque, int control, IOBUF 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 ); void free_md_filter_context( md_filter_context_t *mfx );

View File

@ -121,7 +121,7 @@ main( int argc, char **argv )
{ 'e', "encrypt", 0, "encrypt data" }, { 'e', "encrypt", 0, "encrypt data" },
{ 'd', "decrypt", 0, "decrypt data (default)" }, { 'd', "decrypt", 0, "decrypt data (default)" },
/*{ 'c', "check", 0, "check a signature (default)" }, */ /*{ 'c', "check", 0, "check a signature (default)" }, */
{ 'l', "local-user",2, "use this user-id to sign or decrypt" }, { 'u', "local-user",2, "use this user-id to sign or decrypt" },
{ 'r', "remote-user", 2, "use this user-id for encryption" }, { 'r', "remote-user", 2, "use this user-id for encryption" },
{ 510, "debug" ,4|16, "set debugging flags" }, { 510, "debug" ,4|16, "set debugging flags" },
{ 511, "debug-all" ,0, "enable full debugging"}, { 511, "debug-all" ,0, "enable full debugging"},
@ -135,13 +135,17 @@ main( int argc, char **argv )
{ 518, "options" , 2, "read options from file" }, { 518, "options" , 2, "read options from file" },
{ 519, "no-armor", 0, "\r"}, { 519, "no-armor", 0, "\r"},
{ 520, "no-default-keyring", 0, "\r" }, { 520, "no-default-keyring", 0, "\r" },
{ 521, "list-packets",0,"list only the sequence of packets"},
{ 522, "no-greeting", 0, "\r" },
{ 523, "passphrase-fd",1, "\r" },
{ 524, "edit-sig" ,0, "edit a key signature" },
{0} }; {0} };
ARGPARSE_ARGS pargs; ARGPARSE_ARGS pargs;
IOBUF a; IOBUF a;
int rc; int rc;
enum { aNull, aSym, aStore, aEncr, aPrimegen, aKeygen, aSign, aSignEncr, enum { aNull, aSym, aStore, aEncr, aPrimegen, aKeygen, aSign, aSignEncr,
aTest, aPrintMDs, aSignKey, aClearsig aTest, aPrintMDs, aSignKey, aClearsig, aListPackets, aEditSig,
} action = aNull; } action = aNull;
int orig_argc; int orig_argc;
char **orig_argv; char **orig_argv;
@ -158,9 +162,10 @@ main( int argc, char **argv )
int default_config =1; int default_config =1;
int errors=0; int errors=0;
int default_keyring = 1; int default_keyring = 1;
int greeting = 1;
opt.compress = 0; /* defaults to no compression level */ opt.compress = -1; /* defaults to standard compress level */
/* check wether we have a config file on the commandline */ /* check wether we have a config file on the commandline */
orig_argc = argc; orig_argc = argc;
@ -221,7 +226,7 @@ main( int argc, char **argv )
/* fall trough */ /* fall trough */
case 's': action = action == aEncr? aSignEncr : aSign; break; case 's': action = action == aEncr? aSignEncr : aSign; break;
case 't': action = aClearsig; break; case 't': action = aClearsig; break;
case 'l': /* store the local users */ case 'u': /* store the local users */
sl = m_alloc( sizeof *sl + strlen(pargs.r.ret_str)); sl = m_alloc( sizeof *sl + strlen(pargs.r.ret_str));
strcpy(sl->d, pargs.r.ret_str); strcpy(sl->d, pargs.r.ret_str);
sl->next = locusr; sl->next = locusr;
@ -233,7 +238,7 @@ main( int argc, char **argv )
sl->next = remusr; sl->next = remusr;
remusr = sl; remusr = sl;
break; break;
case 500: opt.batch = 1; break; case 500: opt.batch = 1; greeting = 0; break;
case 501: opt.answer_yes = 1; break; case 501: opt.answer_yes = 1; break;
case 502: opt.answer_no = 1; break; case 502: opt.answer_no = 1; break;
case 503: action = aKeygen; break; case 503: action = aKeygen; break;
@ -259,6 +264,10 @@ main( int argc, char **argv )
break; break;
case 519: opt.no_armor=1; opt.armor=0; break; case 519: opt.no_armor=1; opt.armor=0; break;
case 520: default_keyring = 0; break; case 520: default_keyring = 0; break;
case 521: action = aListPackets; break;
case 522: greeting = 0; break;
case 523: set_passphrase_fd( pargs.r.ret_int ); break;
case 524: action = aEditSig; break;
default : errors++; pargs.err = configfp? 1:2; break; default : errors++; pargs.err = configfp? 1:2; break;
} }
} }
@ -275,11 +284,11 @@ main( int argc, char **argv )
set_debug(); set_debug();
if( opt.verbose > 1 ) if( opt.verbose > 1 )
set_packet_list_mode(1); set_packet_list_mode(1);
if( opt.verbose && isatty(fileno(stdin)) ) { if( greeting ) {
if( *(s=strusage(10)) ) if( *(s=strusage(10)) )
fputs(s, stderr); tty_printf("%s", s);
if( *(s=strusage(30)) ) if( *(s=strusage(30)) )
fputs(s, stderr); tty_printf("%s", s);
} }
if( !sec_nrings || default_keyring ) { /* add default secret rings */ if( !sec_nrings || default_keyring ) { /* add default secret rings */
@ -347,6 +356,14 @@ main( int argc, char **argv )
log_error("sign_key('%s'): %s\n", fname_print, g10_errstr(rc) ); log_error("sign_key('%s'): %s\n", fname_print, g10_errstr(rc) );
break; break;
case aEditSig: /* Edit a key signature */
if( argc != 1 )
usage(1);
/* note: fname is the user id! */
if( (rc = edit_keysigs(fname)) )
log_error("edit_keysig('%s'): %s\n", fname_print, g10_errstr(rc) );
break;
case aPrimegen: case aPrimegen:
if( argc == 1 ) { if( argc == 1 ) {
@ -388,6 +405,8 @@ main( int argc, char **argv )
case aTest: do_test( argc? atoi(*argv): 0 ); break; case aTest: do_test( argc? atoi(*argv): 0 ); break;
case aListPackets:
opt.list_packets=1;
default: default:
if( argc > 1 ) if( argc > 1 )
usage(1); usage(1);
@ -398,6 +417,10 @@ main( int argc, char **argv )
memset( &afx, 0, sizeof afx); memset( &afx, 0, sizeof afx);
iobuf_push_filter( a, armor_filter, &afx ); iobuf_push_filter( a, armor_filter, &afx );
} }
if( action == aListPackets ) {
set_packet_list_mode(1);
opt.list_packets=1;
}
proc_packets( a ); proc_packets( a );
iobuf_close(a); iobuf_close(a);
break; break;
@ -406,7 +429,7 @@ main( int argc, char **argv )
/* cleanup */ /* cleanup */
FREE_STRLIST(remusr); FREE_STRLIST(remusr);
FREE_STRLIST(locusr); FREE_STRLIST(locusr);
return 0; return log_get_errorcount(0)? 2:0;
} }
@ -509,33 +532,5 @@ do_test(int times)
m_check(NULL); m_check(NULL);
#endif #endif
#if 0
char *array;
int i, j;
int n = 6;
int m = times;
if( m > n )
abort();
array = m_alloc_clear( n );
memset( array, 1, m );
for(i=0;; i++) {
printf("i=%3d: ", i );
for(j=0; j < n ; j++ )
if( array[j] )
putchar( 'X' );
else
putchar( '-' );
putchar('\n');
m_out_of_n( array, m, n );
for(j=0; j < n; j++ )
if( !array[j] )
break;
if( j == m )
break;
}
#endif
} }

View File

@ -38,6 +38,7 @@ new_kbnode( PACKET *pkt )
n->pkt = pkt; n->pkt = pkt;
n->child = NULL; n->child = NULL;
n->flag = 0; n->flag = 0;
n->private_flag=0; /* kludge to delete a node */
return n; return n;
} }
@ -57,6 +58,16 @@ release_kbnode( KBNODE n )
} }
/****************
* Delete NODE from ROOT, ROOT must exist!
* Note does only work with walk_kbtree!!
*/
void
delete_kbnode( KBNODE root, KBNODE node )
{
node->private_flag |= 1;
}
/**************** /****************
* Append NODE to ROOT, ROOT must exist! * Append NODE to ROOT, ROOT must exist!
*/ */
@ -115,27 +126,36 @@ find_kbparent( KBNODE root, KBNODE node )
*/ */
KBNODE KBNODE
walk_kbtree( KBNODE root, KBNODE *context ) walk_kbtree( KBNODE root, KBNODE *context )
{
return walk_kbtree2( root, context, 0 );
}
KBNODE
walk_kbtree2( KBNODE root, KBNODE *context, int all )
{ {
KBNODE n; KBNODE n;
if( !*context ) { do {
*context = root; if( !*context ) {
return root; *context = root;
} return root;
}
n = *context;
if( n->child ) {
n = n->child;
*context = n;
}
else if( n->next ) {
n = n->next;
*context = n;
}
else if( (n = find_kbparent( root, n )) ) {
n = n->next;
*context = n;
}
} while( !all && n && (n->private_flag & 1) );
n = *context;
if( n->child ) {
n = n->child;
*context = n;
}
else if( n->next ) {
n = n->next;
*context = n;
}
else if( (n = find_kbparent( root, n )) ) {
n = n->next;
*context = n;
}
return n; return n;
} }
@ -147,3 +167,4 @@ clear_kbnode_flags( KBNODE n )
n->flag = 0; n->flag = 0;
} }
} }

View File

@ -41,6 +41,7 @@ struct kbnode_struct {
KBNODE next; /* used to form a link list */ KBNODE next; /* used to form a link list */
KBNODE child; KBNODE child;
int flag; int flag;
int private_flag;
}; };
/**************** /****************
@ -81,6 +82,8 @@ void release_skc_list( SKC_LIST skc_list );
int build_skc_list( STRLIST locusr, SKC_LIST *ret_skc_list, int unlock ); int build_skc_list( STRLIST locusr, SKC_LIST *ret_skc_list, int unlock );
/*-- passphrase.h --*/ /*-- passphrase.h --*/
void set_passphrase_fd( int fd );
int get_passphrase_fd(void);
DEK *get_passphrase_hash( u32 *keyid, char *text ); DEK *get_passphrase_hash( u32 *keyid, char *text );
int make_dek_from_passphrase( DEK *dek, int mode ); int make_dek_from_passphrase( DEK *dek, int mode );
@ -112,10 +115,12 @@ byte *fingerprint_from_pkc( PKT_public_cert *pkc, size_t *ret_len );
/*-- kbnode.c --*/ /*-- kbnode.c --*/
KBNODE new_kbnode( PACKET *pkt ); KBNODE new_kbnode( PACKET *pkt );
void release_kbnode( KBNODE n ); void release_kbnode( KBNODE n );
void delete_kbnode( KBNODE root, KBNODE node );
void add_kbnode( KBNODE root, KBNODE node ); void add_kbnode( KBNODE root, KBNODE node );
void add_kbnode_as_child( KBNODE root, KBNODE node ); void add_kbnode_as_child( KBNODE root, KBNODE node );
KBNODE find_kbparent( KBNODE root, KBNODE node ); KBNODE find_kbparent( KBNODE root, KBNODE node );
KBNODE walk_kbtree( KBNODE root, KBNODE *context ); KBNODE walk_kbtree( KBNODE root, KBNODE *context );
KBNODE walk_kbtree2( KBNODE root, KBNODE *context, int all );
void clear_kbnode_flags( KBNODE n ); void clear_kbnode_flags( KBNODE n );
/*-- ringedit.c --*/ /*-- ringedit.c --*/

View File

@ -155,7 +155,7 @@ datestr_from_pkc( PKT_public_cert *pkc )
time_t atime = pkc->timestamp; time_t atime = pkc->timestamp;
tp = gmtime( &atime ); tp = gmtime( &atime );
sprintf(buffer,"%04d-%02d-%02d", 1900+tp->tm_year, tp->tm_mon, tp->tm_mday ); sprintf(buffer,"%04d-%02d-%02d", 1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday );
return buffer; return buffer;
} }
@ -167,7 +167,7 @@ datestr_from_skc( PKT_secret_cert *skc )
time_t atime = skc->timestamp; time_t atime = skc->timestamp;
tp = gmtime( &atime ); tp = gmtime( &atime );
sprintf(buffer,"%04d-%02d-%02d", 1900+tp->tm_year, tp->tm_mon, tp->tm_mday ); sprintf(buffer,"%04d-%02d-%02d", 1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday );
return buffer; return buffer;
} }
@ -179,7 +179,7 @@ datestr_from_sig( PKT_signature *sig )
time_t atime = sig->timestamp; time_t atime = sig->timestamp;
tp = gmtime( &atime ); tp = gmtime( &atime );
sprintf(buffer,"%04d-%02d-%02d", 1900+tp->tm_year, tp->tm_mon, tp->tm_mday ); sprintf(buffer,"%04d-%02d-%02d", 1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday );
return buffer; return buffer;
} }

View File

@ -28,15 +28,27 @@
#define DEFAULT_PUBKEY_ALGO PUBKEY_ALGO_ELGAMAL #define DEFAULT_PUBKEY_ALGO PUBKEY_ALGO_ELGAMAL
#define DEFAULT_DIGEST_ALGO DIGEST_ALGO_RMD160 #define DEFAULT_DIGEST_ALGO DIGEST_ALGO_RMD160
typedef struct {
int header_okay;
PKC_LIST pkc_list;
cipher_filter_context_t cfx;
} encrypt_filter_context_t;
/*-- encode.c --*/ /*-- encode.c --*/
int encode_symmetric( const char *filename ); int encode_symmetric( const char *filename );
int encode_store( 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 encrypt_filter( void *opaque, int control,
IOBUF a, byte *buf, size_t *ret_len);
/*-- sign.c --*/ /*-- sign.c --*/
int sign_file( const char *filename, int detached, STRLIST locusr, int sign_file( const char *filename, int detached, STRLIST locusr,
int encrypt, STRLIST remusr ); int encrypt, STRLIST remusr );
int sign_key( const char *username, STRLIST locusr ); int sign_key( const char *username, STRLIST locusr );
int edit_keysigs( const char *username );
/*-- sig-check.c --*/ /*-- sig-check.c --*/
int check_key_signature( KBNODE root, KBNODE node ); int check_key_signature( KBNODE root, KBNODE node );

View File

@ -46,7 +46,6 @@ typedef struct {
md_filter_context_t mfx; md_filter_context_t mfx;
DEK *dek; DEK *dek;
int last_was_pubkey_enc; int last_was_pubkey_enc;
int opt_list;
KBNODE cert; /* the current certificate */ KBNODE cert; /* the current certificate */
int have_data; int have_data;
IOBUF iobuf; /* used to get the filename etc. */ IOBUF iobuf; /* used to get the filename etc. */
@ -198,7 +197,7 @@ proc_pubkey_enc( CTX c, PACKET *pkt )
c->last_was_pubkey_enc = 1; c->last_was_pubkey_enc = 1;
enc = pkt->pkt.pubkey_enc; enc = pkt->pkt.pubkey_enc;
printf("enc: encrypted by a pubkey with keyid %08lX\n", enc->keyid[1] ); /*printf("enc: encrypted by a pubkey with keyid %08lX\n", enc->keyid[1] );*/
if( enc->pubkey_algo == PUBKEY_ALGO_ELGAMAL if( enc->pubkey_algo == PUBKEY_ALGO_ELGAMAL
|| enc->pubkey_algo == PUBKEY_ALGO_RSA ) { || enc->pubkey_algo == PUBKEY_ALGO_RSA ) {
m_free(c->dek ); /* paranoid: delete a pending DEK */ m_free(c->dek ); /* paranoid: delete a pending DEK */
@ -213,11 +212,12 @@ proc_pubkey_enc( CTX c, PACKET *pkt )
if( result == -1 ) if( result == -1 )
; ;
else if( !result ) else if( !result ) {
fputs( " DEK is good", stdout ); if( opt.verbose > 1 )
log_info( "pubkey_enc packet: Good DEK\n" );
}
else else
printf( " %s", g10_errstr(result)); log_error( "pubkey_enc packet: %s\n", g10_errstr(result));
putchar('\n');
free_packet(pkt); free_packet(pkt);
} }
@ -228,7 +228,7 @@ proc_encrypted( CTX c, PACKET *pkt )
{ {
int result = 0; int result = 0;
printf("dat: %sencrypted data\n", c->dek?"":"conventional "); /*printf("dat: %sencrypted data\n", c->dek?"":"conventional ");*/
if( !c->dek && !c->last_was_pubkey_enc ) { if( !c->dek && !c->last_was_pubkey_enc ) {
/* assume this is conventional encrypted data */ /* assume this is conventional encrypted data */
c->dek = m_alloc_secure( sizeof *c->dek ); c->dek = m_alloc_secure( sizeof *c->dek );
@ -242,11 +242,13 @@ proc_encrypted( CTX c, PACKET *pkt )
m_free(c->dek); c->dek = NULL; m_free(c->dek); c->dek = NULL;
if( result == -1 ) if( result == -1 )
; ;
else if( !result ) else if( !result ) {
fputs( " encryption okay",stdout); if( opt.verbose > 1 )
else log_info("encryption okay\n");
printf( " %s", g10_errstr(result)); }
putchar('\n'); else {
log_error("encryption failed: %s\n", g10_errstr(result));
}
free_packet(pkt); free_packet(pkt);
c->last_was_pubkey_enc = 0; c->last_was_pubkey_enc = 0;
} }
@ -256,9 +258,10 @@ static void
proc_plaintext( CTX c, PACKET *pkt ) proc_plaintext( CTX c, PACKET *pkt )
{ {
PKT_plaintext *pt = pkt->pkt.plaintext; PKT_plaintext *pt = pkt->pkt.plaintext;
int result; int rc;
printf("txt: plain text data name='%.*s'\n", pt->namelen, pt->name); if( opt.verbose )
log_info("original file name='%.*s'\n", pt->namelen, pt->name);
free_md_filter_context( &c->mfx ); free_md_filter_context( &c->mfx );
/* fixme: take the digest algo(s) to use from the /* fixme: take the digest algo(s) to use from the
* onepass_sig packet (if we have these) * onepass_sig packet (if we have these)
@ -266,12 +269,9 @@ proc_plaintext( CTX c, PACKET *pkt )
* textmode filter (sigclass 0x01) * textmode filter (sigclass 0x01)
*/ */
c->mfx.md = md_open(DIGEST_ALGO_RMD160, 0); c->mfx.md = md_open(DIGEST_ALGO_RMD160, 0);
result = handle_plaintext( pt, &c->mfx ); rc = handle_plaintext( pt, &c->mfx );
if( !result ) if( rc )
fputs( " okay", stdout); log_error( "handle plaintext failed: %s\n", g10_errstr(rc));
else
printf( " %s", g10_errstr(result));
putchar('\n');
free_packet(pkt); free_packet(pkt);
c->last_was_pubkey_enc = 0; c->last_was_pubkey_enc = 0;
} }
@ -281,15 +281,12 @@ static void
proc_compressed( CTX c, PACKET *pkt ) proc_compressed( CTX c, PACKET *pkt )
{ {
PKT_compressed *zd = pkt->pkt.compressed; PKT_compressed *zd = pkt->pkt.compressed;
int result; int rc;
printf("zip: compressed data packet\n"); /*printf("zip: compressed data packet\n");*/
result = handle_compressed( zd ); rc = handle_compressed( zd );
if( !result ) if( rc )
fputs( " okay", stdout); log_error("uncompressing failed: %s\n", g10_errstr(rc));
else
printf( " %s", g10_errstr(result));
putchar('\n');
free_packet(pkt); free_packet(pkt);
c->last_was_pubkey_enc = 0; c->last_was_pubkey_enc = 0;
} }
@ -505,7 +502,6 @@ proc_packets( IOBUF a )
u32 keyid[2]; u32 keyid[2];
int newpkt; int newpkt;
c->opt_list = 1;
c->iobuf = a; c->iobuf = a;
init_packet(pkt); init_packet(pkt);
while( (rc=parse_packet(a, pkt)) != -1 ) { while( (rc=parse_packet(a, pkt)) != -1 ) {
@ -522,17 +518,27 @@ proc_packets( IOBUF a )
continue; continue;
} }
newpkt = -1; newpkt = -1;
switch( pkt->pkttype ) { if( opt.list_packets ) {
case PKT_PUBLIC_CERT: newpkt = add_public_cert( c, pkt ); break; switch( pkt->pkttype ) {
case PKT_SECRET_CERT: newpkt = add_secret_cert( c, pkt ); break; case PKT_PUBKEY_ENC: proc_pubkey_enc( c, pkt ); break;
case PKT_USER_ID: newpkt = add_user_id( c, pkt ); break; case PKT_ENCRYPTED: proc_encrypted( c, pkt ); break;
case PKT_SIGNATURE: newpkt = add_signature( c, pkt ); break; case PKT_COMPRESSED: proc_compressed( c, pkt ); break;
case PKT_PUBKEY_ENC: proc_pubkey_enc( c, pkt ); break; default: newpkt = 0; break;
case PKT_ENCRYPTED: proc_encrypted( c, pkt ); break; }
case PKT_PLAINTEXT: proc_plaintext( c, pkt ); break; }
case PKT_COMPRESSED: proc_compressed( c, pkt ); break; else {
case PKT_ONEPASS_SIG: newpkt = add_onepass_sig( c, pkt ); break; switch( pkt->pkttype ) {
default: newpkt = 0; break; case PKT_PUBLIC_CERT: newpkt = add_public_cert( c, pkt ); break;
case PKT_SECRET_CERT: newpkt = add_secret_cert( c, pkt ); break;
case PKT_USER_ID: newpkt = add_user_id( c, pkt ); break;
case PKT_SIGNATURE: newpkt = add_signature( c, pkt ); break;
case PKT_PUBKEY_ENC: proc_pubkey_enc( c, pkt ); break;
case PKT_ENCRYPTED: proc_encrypted( c, pkt ); break;
case PKT_PLAINTEXT: proc_plaintext( c, pkt ); break;
case PKT_COMPRESSED: proc_compressed( c, pkt ); break;
case PKT_ONEPASS_SIG: newpkt = add_onepass_sig( c, pkt ); break;
default: newpkt = 0; break;
}
} }
if( pkt->pkttype != PKT_SIGNATURE ) if( pkt->pkttype != PKT_SIGNATURE )
c->have_data = pkt->pkttype == PKT_PLAINTEXT; c->have_data = pkt->pkttype == PKT_PLAINTEXT;
@ -575,13 +581,16 @@ proc_tree( CTX c, KBNODE node )
KBNODE n1; KBNODE n1;
int rc; int rc;
if( opt.list_packets )
return;
if( node->pkt->pkttype == PKT_PUBLIC_CERT ) if( node->pkt->pkttype == PKT_PUBLIC_CERT )
list_node( c, node ); list_node( c, node );
else if( node->pkt->pkttype == PKT_SECRET_CERT ) else if( node->pkt->pkttype == PKT_SECRET_CERT )
list_node( c, node ); list_node( c, node );
else if( node->pkt->pkttype == PKT_ONEPASS_SIG ) { else if( node->pkt->pkttype == PKT_ONEPASS_SIG ) {
if( !node->child ) if( !node->child )
log_error("proc_tree: onepass_sig without followin data\n"); log_error("proc_tree: onepass_sig without data\n");
else if( node->child->pkt->pkttype != PKT_SIGNATURE ) else if( node->child->pkt->pkttype != PKT_SIGNATURE )
log_error("proc_tree: onepass_sig not followed by signature\n"); log_error("proc_tree: onepass_sig not followed by signature\n");
else { /* check all signatures */ else { /* check all signatures */
@ -611,6 +620,8 @@ proc_tree( CTX c, KBNODE node )
log_error("BAD signature from "); log_error("BAD signature from ");
print_keyid( stderr, sig->keyid ); print_keyid( stderr, sig->keyid );
putc('\n', stderr); putc('\n', stderr);
if( opt.batch )
exit(1);
} }
else else
log_error("Can't check signature made by %08lX: %s\n", log_error("Can't check signature made by %08lX: %s\n",

View File

@ -35,7 +35,7 @@ struct {
int fingerprint; /* list fingerprints */ int fingerprint; /* list fingerprints */
int list_sigs; /* list signatures */ int list_sigs; /* list signatures */
int no_armor; int no_armor;
int reserved5; int list_packets; /* list-packets mode */
int reserved6; int reserved6;
int reserved7; int reserved7;
int reserved8; int reserved8;

View File

@ -210,6 +210,7 @@ struct packet_struct {
/*-- mainproc.c --*/ /*-- mainproc.c --*/
int proc_packets( IOBUF a ); int proc_packets( IOBUF a );
int list_packets( IOBUF a );
/*-- parse-packet.c --*/ /*-- parse-packet.c --*/
int set_packet_list_mode( int mode ); int set_packet_list_mode( int mode );

View File

@ -25,13 +25,27 @@
#include <assert.h> #include <assert.h>
#include "util.h" #include "util.h"
#include "memory.h" #include "memory.h"
#include "options.h"
#include "ttyio.h" #include "ttyio.h"
#include "cipher.h" #include "cipher.h"
#include "keydb.h" #include "keydb.h"
static int pwfd = -1;
static int hash_passphrase( DEK *dek, char *pw ); static int hash_passphrase( DEK *dek, char *pw );
void
set_passphrase_fd( int fd )
{
pwfd = fd;
}
int
get_passphrase_fd()
{
return pwfd;
}
/**************** /****************
* Get a passphrase for the secret key with KEYID, display TEXT * Get a passphrase for the secret key with KEYID, display TEXT
@ -41,35 +55,51 @@ static int hash_passphrase( DEK *dek, char *pw );
DEK * DEK *
get_passphrase_hash( u32 *keyid, char *text ) get_passphrase_hash( u32 *keyid, char *text )
{ {
char *p=NULL, *pw; char *pw;
DEK *dek; DEK *dek;
if( keyid ) { if( keyid && !opt.batch ) {
char *ustr; char *ustr;
tty_printf("\nNeed a pass phrase to unlock the secret key!\n"); tty_printf("Need a pass phrase to unlock the secret key for:\n");
tty_printf("KeyID: " ); tty_printf(" \"" );
ustr = get_user_id_string( keyid ); ustr = get_user_id_string( keyid );
tty_print_string( ustr, strlen(ustr) ); tty_print_string( ustr, strlen(ustr) );
m_free(ustr); m_free(ustr);
tty_printf("\n\n"); tty_printf("\"\n\n");
} }
if( keyid && (p=getenv("G10PASSPHRASE")) ) { if( pwfd != -1 ) { /* read the passphrase from the given descriptor */
pw = m_alloc_secure(strlen(p)+1); int i, len;
strcpy(pw,p);
tty_printf("Taking it from $G10PASSPHRASE !\n", keyid[1] ); if( !opt.batch )
tty_printf("Reading from file descriptor %d ...", pwfd );
for( pw = NULL, i = len = 100; ; i++ ) {
if( i >= len-1 ) {
char *pw2 = pw;
len += 100;
pw = m_alloc_secure( len );
if( pw2 )
memcpy(pw, pw2, i );
i=0;
}
if( read( pwfd, pw+i, 1) != 1 || pw[i] == '\n' )
break;
}
pw[i] = 0;
if( !opt.batch )
tty_printf("\b\b\b \n" );
} }
else else if( opt.batch )
log_fatal("Can't query password in batchmode\n");
else {
pw = tty_get_hidden("Enter pass phrase: " ); pw = tty_get_hidden("Enter pass phrase: " );
tty_kill_prompt();
}
dek = m_alloc_secure( sizeof *dek ); dek = m_alloc_secure( sizeof *dek );
dek->algo = CIPHER_ALGO_BLOWFISH; dek->algo = CIPHER_ALGO_BLOWFISH;
if( hash_passphrase( dek, pw ) ) if( hash_passphrase( dek, pw ) )
log_bug("get_passphrase_hash\n"); log_bug("get_passphrase_hash\n");
m_free(pw); /* is allocated in secure memory, so it will be burned */ m_free(pw); /* is allocated in secure memory, so it will be burned */
if( !p ) {
tty_kill_prompt();
tty_printf("\n");
}
return dek; return dek;
} }
@ -89,6 +119,7 @@ make_dek_from_passphrase( DEK *dek, int mode )
tty_kill_prompt(); tty_kill_prompt();
if( mode == 2 ) { if( mode == 2 ) {
pw2 = tty_get_hidden("Repeat pass phrase: " ); pw2 = tty_get_hidden("Repeat pass phrase: " );
tty_kill_prompt();
if( strcmp(pw, pw2) ) { if( strcmp(pw, pw2) ) {
m_free(pw2); m_free(pw2);
m_free(pw); m_free(pw);

View File

@ -65,6 +65,7 @@ check_elg( PKT_secret_cert *cert )
unsigned nbytes; unsigned nbytes;
u32 keyid[2]; u32 keyid[2];
ELG_secret_key skey; ELG_secret_key skey;
char save_iv[8];
if( cert->d.elg.is_protected ) { /* remove the protection */ if( cert->d.elg.is_protected ) { /* remove the protection */
DEK *dek = NULL; DEK *dek = NULL;
@ -80,6 +81,7 @@ check_elg( PKT_secret_cert *cert )
blowfish_setkey( blowfish_ctx, dek->key, dek->keylen ); blowfish_setkey( blowfish_ctx, dek->key, dek->keylen );
m_free(dek); /* pw is in secure memory, so m_free() burns it */ m_free(dek); /* pw is in secure memory, so m_free() burns it */
blowfish_setiv( blowfish_ctx, NULL ); blowfish_setiv( blowfish_ctx, NULL );
memcpy(save_iv, cert->d.elg.protect.blowfish.iv, 8 );
blowfish_decode_cfb( blowfish_ctx, blowfish_decode_cfb( blowfish_ctx,
cert->d.elg.protect.blowfish.iv, cert->d.elg.protect.blowfish.iv,
cert->d.elg.protect.blowfish.iv, 8 ); cert->d.elg.protect.blowfish.iv, 8 );
@ -94,6 +96,7 @@ check_elg( PKT_secret_cert *cert )
/* now let's see wether we have used the right passphrase */ /* now let's see wether we have used the right passphrase */
if( csum != cert->d.elg.csum ) { if( csum != cert->d.elg.csum ) {
mpi_free(test_x); mpi_free(test_x);
memcpy( cert->d.elg.protect.blowfish.iv, save_iv, 8 );
return G10ERR_BAD_PASS; return G10ERR_BAD_PASS;
} }
@ -105,6 +108,7 @@ check_elg( PKT_secret_cert *cert )
memset( &skey, 0, sizeof skey ); memset( &skey, 0, sizeof skey );
if( !res ) { if( !res ) {
mpi_free(test_x); mpi_free(test_x);
memcpy( cert->d.elg.protect.blowfish.iv, save_iv, 8 );
return G10ERR_BAD_PASS; return G10ERR_BAD_PASS;
} }
mpi_set(cert->d.elg.x, test_x); mpi_set(cert->d.elg.x, test_x);
@ -274,6 +278,8 @@ check_secret_key( PKT_secret_cert *cert )
#endif #endif
else else
rc = G10ERR_PUBKEY_ALGO; rc = G10ERR_PUBKEY_ALGO;
if( get_passphrase_fd() != -1 )
break;
} }
return rc; return rc;
} }

View File

@ -79,6 +79,7 @@ sign_file( const char *filename, int detached, STRLIST locusr,
compress_filter_context_t zfx; compress_filter_context_t zfx;
md_filter_context_t mfx; md_filter_context_t mfx;
text_filter_context_t tfx; text_filter_context_t tfx;
encrypt_filter_context_t efx;
IOBUF inp = NULL, out = NULL; IOBUF inp = NULL, out = NULL;
PACKET pkt; PACKET pkt;
PKT_plaintext *pt = NULL; PKT_plaintext *pt = NULL;
@ -92,6 +93,7 @@ sign_file( const char *filename, int detached, STRLIST locusr,
memset( &zfx, 0, sizeof zfx); memset( &zfx, 0, sizeof zfx);
memset( &mfx, 0, sizeof mfx); memset( &mfx, 0, sizeof mfx);
memset( &tfx, 0, sizeof tfx); memset( &tfx, 0, sizeof tfx);
memset( &efx, 0, sizeof efx);
init_packet( &pkt ); init_packet( &pkt );
if( (rc=build_skc_list( locusr, &skc_list, 1 )) ) if( (rc=build_skc_list( locusr, &skc_list, 1 )) )
@ -127,8 +129,9 @@ sign_file( const char *filename, int detached, STRLIST locusr,
iobuf_push_filter( out, compress_filter, &zfx ); iobuf_push_filter( out, compress_filter, &zfx );
if( encrypt ) { if( encrypt ) {
/* prepare for encryption */ efx.pkc_list = pkc_list;
/* FIXME!!!!!!! */ /* fixme: set efx.cfx.datalen if known */
iobuf_push_filter( out, encrypt_filter, &efx );
} }
/* loop over the secret certificates and build headers */ /* loop over the secret certificates and build headers */
@ -348,7 +351,15 @@ sign_it_p( PKT_public_cert *pkc, PKT_user_id *uid )
} }
static void /****************
* Check the keysigs and set the flags to indicate errors.
* Usage of nodes flag bits:
* Bit 0 = bad signature
* 1 = no public key
* 2 = other error
* Returns true if error found.
*/
static int
check_all_keysigs( KBNODE keyblock ) check_all_keysigs( KBNODE keyblock )
{ {
KBNODE kbctx; KBNODE kbctx;
@ -384,6 +395,7 @@ check_all_keysigs( KBNODE keyblock )
m_free(p); m_free(p);
} }
tty_printf("\n"); tty_printf("\n");
/* FIXME: update the trustdb */
} }
} }
if( inv_sigs ) if( inv_sigs )
@ -392,6 +404,76 @@ check_all_keysigs( KBNODE keyblock )
tty_printf("No public key for %d signatures\n", no_key ); tty_printf("No public key for %d signatures\n", no_key );
if( oth_err ) if( oth_err )
tty_printf("%d signatures not checked due to errors\n", oth_err ); tty_printf("%d signatures not checked due to errors\n", oth_err );
return inv_sigs || no_key || oth_err;
}
/****************
* Ask and remove invalid signatures are to be removed.
*/
static int
remove_keysigs( KBNODE keyblock, int all )
{
KBNODE kbctx;
KBNODE node;
char *answer;
int yes;
int count;
count = 0;
for( kbctx=NULL; (node=walk_kbtree( keyblock, &kbctx)) ; ) {
if( ((node->flag & 7) || all )
&& node->pkt->pkttype == PKT_SIGNATURE
&& (node->pkt->pkt.signature->sig_class&~3) == 0x10 ) {
PKT_signature *sig = node->pkt->pkt.signature;
int sigrc;
if( all ) {
/* fixme: skip self-sig */
}
tty_printf("\n \"%08lX %s ",
sig->keyid[1], datestr_from_sig(sig));
if( node->flag & 6 )
tty_printf("[User name not available] ");
else {
size_t n;
char *p = get_user_id( sig->keyid, &n );
tty_print_string( p, n );
m_free(p);
}
tty_printf("\"\n");
if( node->flag & 1 )
tty_printf("This is a BAD signature!\n");
else if( node->flag & 2 )
tty_printf("Public key not available.\n");
else if( node->flag & 4 )
tty_printf("The signature could not be checked!\n");
answer = tty_get("\nRemove this signature? ");
tty_kill_prompt();
if( answer_is_yes(answer) ) {
node->flag |= 128; /* use bit 7 to mark this node */
count++;
}
m_free(answer);
}
}
if( !count )
return 0; /* nothing to remove */
answer = tty_get("Do you really want to remove the selected signatures? ");
tty_kill_prompt();
yes = answer_is_yes(answer);
m_free(answer);
if( !yes )
return 0;
for( kbctx=NULL; (node=walk_kbtree2( keyblock, &kbctx, 1)) ; ) {
if( node->flag & 128)
delete_kbnode( keyblock, node );
}
return 1;
} }
@ -414,6 +496,7 @@ sign_key( const char *username, STRLIST locusr )
PKT_public_cert *pkc; PKT_public_cert *pkc;
int any; int any;
u32 pkc_keyid[2]; u32 pkc_keyid[2];
char *answer;
memset( &mfx, 0, sizeof mfx); memset( &mfx, 0, sizeof mfx);
@ -464,9 +547,16 @@ sign_key( const char *username, STRLIST locusr )
} }
clear_kbnode_flags( keyblock ); clear_kbnode_flags( keyblock );
check_all_keysigs( keyblock ); if( check_all_keysigs( keyblock ) ) {
/* look wether we should ask to remove invalid keys */ if( !opt.batch ) {
/*+ FIXME: */ /* ask wether we really should do anything */
answer = tty_get("To you want to remove some of the invalid sigs? ");
tty_kill_prompt();
if( answer_is_yes(answer) )
remove_keysigs( keyblock, 0 );
m_free(answer);
}
}
/* check wether we have already signed it */ /* check wether we have already signed it */
for( skc_rover = skc_list; skc_rover; skc_rover = skc_rover->next ) { for( skc_rover = skc_list; skc_rover; skc_rover = skc_rover->next ) {
@ -524,7 +614,7 @@ sign_key( const char *username, STRLIST locusr )
rc = update_keyblock( &kbpos, keyblock ); rc = update_keyblock( &kbpos, keyblock );
if( rc ) { if( rc ) {
log_error("insert_keyblock failed: %s\n", g10_errstr(rc) ); log_error("update_keyblock failed: %s\n", g10_errstr(rc) );
goto leave; goto leave;
} }
@ -537,6 +627,75 @@ sign_key( const char *username, STRLIST locusr )
int
edit_keysigs( const char *username )
{
int rc = 0;
KBNODE keyblock = NULL;
KBNODE kbctx, node;
KBPOS kbpos;
PKT_public_cert *pkc;
int any;
u32 pkc_keyid[2];
char *answer;
/* search the userid */
rc = search_keyblock_byname( &kbpos, username );
if( rc ) {
log_error("user '%s' not found\n", username );
goto leave;
}
/* read the keyblock */
rc = read_keyblock( &kbpos, &keyblock );
if( rc ) {
log_error("error reading the certificate: %s\n", g10_errstr(rc) );
goto leave;
}
/* get the keyid from the keyblock */
for( kbctx=NULL; (node=walk_kbtree( keyblock, &kbctx)) ; ) {
if( node->pkt->pkttype == PKT_PUBLIC_CERT )
break;
}
if( !node ) {
log_error("Oops; public key not found anymore!\n");
rc = G10ERR_GENERAL;
goto leave;
}
pkc = node->pkt->pkt.public_cert;
keyid_from_pkc( pkc, pkc_keyid );
log_info("Checking signatures of this public key certificate:\n");
tty_printf("pub %4u%c/%08lX %s ",
nbits_from_pkc( pkc ),
pubkey_letter( pkc->pubkey_algo ),
pkc_keyid[1], datestr_from_pkc(pkc) );
{
size_t n;
char *p = get_user_id( pkc_keyid, &n );
tty_print_string( p, n > 40? 40 : n );
m_free(p);
tty_printf("\n");
}
clear_kbnode_flags( keyblock );
check_all_keysigs( keyblock );
if( remove_keysigs( keyblock, 1 ) ) {
rc = update_keyblock( &kbpos, keyblock );
if( rc ) {
log_error("update_keyblock failed: %s\n", g10_errstr(rc) );
goto leave;
}
}
leave:
release_kbnode( keyblock );
return rc;
}
/**************** /****************
* Create a signature packet for the given public key certificate * Create a signature packet for the given public key certificate
* and the user id and return it in ret_sig. User signature class SIGCLASS * and the user id and return it in ret_sig. User signature class SIGCLASS

35
g10/trustdb.c Normal file
View File

@ -0,0 +1,35 @@
/* trustdb.c
* Copyright (c) 1997 by Werner Koch (dd9jn)
*
* This file is part of G10.
*
* G10 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.
*
* G10 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 "errors.h"
#include "iobuf.h"
#include "keydb.h"
#include "memory.h"
#include "util.h"

View File

@ -56,7 +56,8 @@ typedef struct {
} ARGPARSE_OPTS; } ARGPARSE_OPTS;
/*-- logger.c --*/ /*-- logger.c --*/
void set_log_pid( int pid ); void log_set_pid( int pid );
int log_get_errorcount( int clear );
void printstr( int level, const char *fmt, ... ); void printstr( int level, const char *fmt, ... );
void log_bug( const char *fmt, ... ); void log_bug( const char *fmt, ... );
void log_fatal( const char *fmt, ... ); void log_fatal( const char *fmt, ... );

View File

@ -450,6 +450,7 @@ iobuf_push_filter( IOBUF a,
/* remove the filter stuff from the new stream */ /* remove the filter stuff from the new stream */
a->filter = NULL; a->filter = NULL;
a->filter_ov = NULL; a->filter_ov = NULL;
a->filter_eof = 0;
if( a->usage == 2 ) { /* allocate a fresh buffer for the original stream */ if( a->usage == 2 ) { /* allocate a fresh buffer for the original stream */
b->d.buf = m_alloc( a->d.size ); b->d.buf = m_alloc( a->d.size );
b->d.len = 0; b->d.len = 0;
@ -539,7 +540,7 @@ iobuf_pop_filter( IOBUF a, int (*f)(void *opaque, int control,
m_free(b); m_free(b);
} }
else if( !b->chain ) { /* remove the last iobuf from the chain */ else if( !b->chain ) { /* remove the last iobuf from the chain */
log_bug("Ohh jeee, trying to a head filter\n"); log_bug("Ohh jeee, trying to remove a head filter\n");
} }
else { /* remove an intermediate iobuf from the chain */ else { /* remove an intermediate iobuf from the chain */
log_bug("Ohh jeee, trying to remove an intermediate filter\n"); log_bug("Ohh jeee, trying to remove an intermediate filter\n");
@ -833,13 +834,13 @@ iobuf_set_block_mode( IOBUF a, size_t n )
/**************** /****************
* checks wether the stream is in block mode * Checks wether the stream is in block mode
* Note: This does not work if other filters are pushed on the stream.
*/ */
int int
iobuf_in_block_mode( IOBUF a ) iobuf_in_block_mode( IOBUF a )
{ {
for(; a; a = a->chain ) if( a && a->filter == block_filter )
if( a->filter == block_filter )
return 1; /* yes */ return 1; /* yes */
return 0; /* no */ return 0; /* no */
} }

View File

@ -26,10 +26,10 @@
#include "util.h" #include "util.h"
static char pidstring[15]; static char pidstring[15];
static int errorcount;
void void
set_log_pid( int pid ) log_set_pid( int pid )
{ {
if( pid ) if( pid )
sprintf(pidstring,"[%u]", (unsigned)pid ); sprintf(pidstring,"[%u]", (unsigned)pid );
@ -37,6 +37,15 @@ set_log_pid( int pid )
*pidstring = 0; *pidstring = 0;
} }
int
log_get_errorcount( int clear)
{
int n = errorcount;
if( clear )
errorcount = 0;
return n;
}
/**************** /****************
* General interface for printing a line * General interface for printing a line
@ -90,6 +99,7 @@ log_error( const char *fmt, ... )
va_start( arg_ptr, fmt ) ; va_start( arg_ptr, fmt ) ;
vfprintf(stderr,fmt,arg_ptr) ; vfprintf(stderr,fmt,arg_ptr) ;
va_end(arg_ptr); va_end(arg_ptr);
errorcount++;
} }
void void

View File

@ -30,41 +30,19 @@
#include "memory.h" #include "memory.h"
#include "ttyio.h" #include "ttyio.h"
static FILE *ttyfp = NULL;
static int last_prompt_len; static int last_prompt_len;
static FILE *
open_tty(struct termios *termsave )
{
struct termios term;
FILE *tty = fopen("/dev/tty", "r");
if( !tty )
log_fatal("cannot open /dev/tty: %s\n", strerror(errno) );
if( termsave ) { /* hide input */
if( tcgetattr(fileno(tty), termsave) )
log_fatal("tcgetattr() failed: %s\n", strerror(errno) );
term = *termsave;
term.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
if( tcsetattr( fileno(tty), TCSAFLUSH, &term ) )
log_fatal("tcsetattr() failed: %s\n", strerror(errno) );
}
return tty;
}
static void static void
close_tty( FILE *tty, struct termios *termsave ) init_ttyfp()
{ {
if( termsave ) { if( ttyfp )
if( tcsetattr(fileno(tty), TCSAFLUSH, termsave) ) return;
log_error("tcsetattr() failed: %s\n", strerror(errno) );
putc('\n', stderr);
}
fclose(tty);
}
ttyfp = fopen("/dev/tty", "r+");
if( !ttyfp )
log_fatal("cannot open /dev/tty: %s\n", strerror(errno) );
}
void void
@ -72,10 +50,13 @@ tty_printf( const char *fmt, ... )
{ {
va_list arg_ptr; va_list arg_ptr;
if( !ttyfp )
init_ttyfp();
va_start( arg_ptr, fmt ) ; va_start( arg_ptr, fmt ) ;
last_prompt_len += vfprintf(stderr,fmt,arg_ptr) ; last_prompt_len += vfprintf(ttyfp,fmt,arg_ptr) ;
va_end(arg_ptr); va_end(arg_ptr);
fflush(stderr); fflush(ttyfp);
} }
@ -85,18 +66,21 @@ tty_printf( const char *fmt, ... )
void void
tty_print_string( byte *p, size_t n ) tty_print_string( byte *p, size_t n )
{ {
if( !ttyfp )
init_ttyfp();
for( ; n; n--, p++ ) for( ; n; n--, p++ )
if( iscntrl( *p ) ) { if( iscntrl( *p ) ) {
putc('\\', stderr); putc('\\', ttyfp);
if( *p == '\n' ) if( *p == '\n' )
putc('n', stderr); putc('n', ttyfp);
else if( !*p ) else if( !*p )
putc('0', stderr); putc('0', ttyfp);
else else
fprintf(stderr, "x%02x", *p ); fprintf(ttyfp, "x%02x", *p );
} }
else else
putc(*p, stderr); putc(*p, ttyfp);
} }
@ -107,17 +91,36 @@ static char *
do_get( const char *prompt, int hidden ) do_get( const char *prompt, int hidden )
{ {
char *buf; char *buf;
byte cbuf[1];
int c, n, i; int c, n, i;
FILE *fp; FILE *fp;
struct termios termsave; struct termios termsave;
if( !ttyfp )
init_ttyfp();
last_prompt_len = 0; last_prompt_len = 0;
tty_printf( prompt ); tty_printf( prompt );
buf = m_alloc(n=50); buf = m_alloc(n=50);
i = 0; i = 0;
fp = open_tty(hidden? &termsave: NULL);
while( (c=getc(fp)) != EOF && c != '\n' ) { if( hidden ) {
last_prompt_len++; struct termios term;
if( tcgetattr(fileno(ttyfp), &termsave) )
log_fatal("tcgetattr() failed: %s\n", strerror(errno) );
term = termsave;
term.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
if( tcsetattr( fileno(ttyfp), TCSAFLUSH, &term ) )
log_fatal("tcsetattr() failed: %s\n", strerror(errno) );
}
/* fixme: How can we avoid that the \n is echoed w/o disabling
* canonical mode - w/o this kill_prompt can't work */
while( read(fileno(ttyfp), cbuf, 1) == 1 && *cbuf != '\n' ) {
if( !hidden )
last_prompt_len++;
c = *cbuf;
if( c == '\t' ) if( c == '\t' )
c = ' '; c = ' ';
else if( iscntrl(c) ) else if( iscntrl(c) )
@ -128,7 +131,11 @@ do_get( const char *prompt, int hidden )
} }
buf[i++] = c; buf[i++] = c;
} }
close_tty(fp, hidden? &termsave: NULL);
if( hidden ) {
if( tcsetattr(fileno(ttyfp), TCSAFLUSH, &termsave) )
log_error("tcsetattr() failed: %s\n", strerror(errno) );
}
buf[i] = 0; buf[i] = 0;
return buf; return buf;
} }
@ -151,15 +158,16 @@ void
tty_kill_prompt() tty_kill_prompt()
{ {
int i; int i;
#if 0
if( !ttyfp )
init_ttyfp();
if( !last_prompt_len )
return;
fputc('\r', ttyfp);
for(i=0; i < last_prompt_len; i ++ ) for(i=0; i < last_prompt_len; i ++ )
fputc('\b', stderr); fputc(' ', ttyfp);
for(i=0; i < last_prompt_len; i ++ ) fputc('\r', ttyfp);
fputc(' ', stderr);
for(i=0; i < last_prompt_len; i ++ )
fputc('\b', stderr);
#endif
last_prompt_len = 0; last_prompt_len = 0;
fflush(stderr); fflush(ttyfp);
} }