diff options
author | Werner Koch <wk@gnupg.org> | 1998-01-02 21:40:10 +0100 |
---|---|---|
committer | Werner Koch <wk@gnupg.org> | 1998-01-02 21:40:10 +0100 |
commit | b7bdef0834f9d04f96f69a5323e0ac3e5e1b7bc2 (patch) | |
tree | cb6bae66627f4ea4d0a6b29631223ed2fe78ee8e /g10 | |
parent | Sylvester Version (diff) | |
download | gnupg2-b7bdef0834f9d04f96f69a5323e0ac3e5e1b7bc2.tar.xz gnupg2-b7bdef0834f9d04f96f69a5323e0ac3e5e1b7bc2.zip |
added more stuff
Diffstat (limited to 'g10')
-rw-r--r-- | g10/Makefile.am | 1 | ||||
-rw-r--r-- | g10/Makefile.in | 8 | ||||
-rw-r--r-- | g10/encode.c | 88 | ||||
-rw-r--r-- | g10/filter.h | 4 | ||||
-rw-r--r-- | g10/g10.c | 69 | ||||
-rw-r--r-- | g10/kbnode.c | 55 | ||||
-rw-r--r-- | g10/keydb.h | 5 | ||||
-rw-r--r-- | g10/keyid.c | 6 | ||||
-rw-r--r-- | g10/main.h | 12 | ||||
-rw-r--r-- | g10/mainproc.c | 93 | ||||
-rw-r--r-- | g10/options.h | 2 | ||||
-rw-r--r-- | g10/packet.h | 1 | ||||
-rw-r--r-- | g10/passphrase.c | 59 | ||||
-rw-r--r-- | g10/seckey-cert.c | 6 | ||||
-rw-r--r-- | g10/sign.c | 173 | ||||
-rw-r--r-- | g10/trustdb.c | 35 |
16 files changed, 466 insertions, 151 deletions
diff --git a/g10/Makefile.am b/g10/Makefile.am index 02639904a..901370ffb 100644 --- a/g10/Makefile.am +++ b/g10/Makefile.am @@ -30,6 +30,7 @@ g10_SOURCES = g10.c \ options.h \ openfile.c \ keyid.c \ + trustdb.c \ packet.h \ parse-packet.c \ passphrase.c \ diff --git a/g10/Makefile.in b/g10/Makefile.in index 40cf3aeed..531b1b8e9 100644 --- a/g10/Makefile.in +++ b/g10/Makefile.in @@ -68,6 +68,7 @@ g10_SOURCES = g10.c \ options.h \ openfile.c \ keyid.c \ + trustdb.c \ packet.h \ parse-packet.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 \ 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 \ -openfile.o keyid.o parse-packet.o passphrase.o plaintext.o pubkey-enc.o \ -seckey-cert.o seskey.o sign.o comment.o sig-check.o +openfile.o keyid.o trustdb.o parse-packet.o passphrase.o plaintext.o \ +pubkey-enc.o seckey-cert.o seskey.o sign.o comment.o sig-check.o EXTRA_g10_SOURCES = g10_LDADD = $(LDADD) 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/seckey-cert.P $(srcdir)/.deps/seskey.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) OBJECTS = $(g10_OBJECTS) diff --git a/g10/encode.c b/g10/encode.c index b73ee28d7..b0b148dd1 100644 --- a/g10/encode.c +++ b/g10/encode.c @@ -37,6 +37,7 @@ 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; armor_filter_context_t afx; compress_filter_context_t zfx; - PKC_LIST pkc_list, pkc_rover; + PKC_LIST pkc_list; memset( &cfx, 0, sizeof cfx); memset( &afx, 0, sizeof afx); @@ -203,31 +204,9 @@ encode_crypt( const char *filename, STRLIST remusr ) if( DBG_CIPHER ) log_hexdump("DEK is: ", cfx.dek->key, cfx.dek->keylen ); - /* loop over all public key certificates */ - for( pkc_rover=pkc_list; pkc_rover; pkc_rover = pkc_rover->next ) { - PKT_public_cert *pkc; - 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; - } - } + rc = write_pubkey_enc_from_list( pkc_list, cfx.dek, out ); + if( rc ) + goto leave; /* setup the inner packet */ if( filename ) { @@ -276,7 +255,6 @@ encode_crypt( const char *filename, STRLIST remusr ) /**************** * Filter to do a complete public key encryption. */ - #if 0 int encrypt_filter( void *opaque, int control, IOBUF a, byte *buf, size_t *ret_len) @@ -289,6 +267,24 @@ encrypt_filter( void *opaque, int control, log_bug(NULL); /* not used */ } 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 ) { } @@ -297,5 +293,41 @@ encrypt_filter( void *opaque, int control, } 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; +} diff --git a/g10/filter.h b/g10/filter.h index 11c05e4a4..83ed3d153 100644 --- a/g10/filter.h +++ b/g10/filter.h @@ -65,6 +65,7 @@ typedef struct { } cipher_filter_context_t; + typedef struct { size_t linesize; byte *line; @@ -73,6 +74,9 @@ typedef struct { int eof; } text_filter_context_t; + +/* encrypt_filter_context_t defined in main.h */ + /*-- mdfilter.c --*/ int md_filter( void *opaque, int control, IOBUF a, byte *buf, size_t *ret_len); void free_md_filter_context( md_filter_context_t *mfx ); @@ -121,7 +121,7 @@ main( int argc, char **argv ) { 'e', "encrypt", 0, "encrypt data" }, { 'd', "decrypt", 0, "decrypt data (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" }, { 510, "debug" ,4|16, "set debugging flags" }, { 511, "debug-all" ,0, "enable full debugging"}, @@ -135,13 +135,17 @@ main( int argc, char **argv ) { 518, "options" , 2, "read options from file" }, { 519, "no-armor", 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} }; ARGPARSE_ARGS pargs; IOBUF a; int rc; enum { aNull, aSym, aStore, aEncr, aPrimegen, aKeygen, aSign, aSignEncr, - aTest, aPrintMDs, aSignKey, aClearsig + aTest, aPrintMDs, aSignKey, aClearsig, aListPackets, aEditSig, } action = aNull; int orig_argc; char **orig_argv; @@ -158,9 +162,10 @@ main( int argc, char **argv ) int default_config =1; int errors=0; 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 */ orig_argc = argc; @@ -221,7 +226,7 @@ main( int argc, char **argv ) /* fall trough */ case 's': action = action == aEncr? aSignEncr : aSign; 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)); strcpy(sl->d, pargs.r.ret_str); sl->next = locusr; @@ -233,7 +238,7 @@ main( int argc, char **argv ) sl->next = remusr; remusr = sl; break; - case 500: opt.batch = 1; break; + case 500: opt.batch = 1; greeting = 0; break; case 501: opt.answer_yes = 1; break; case 502: opt.answer_no = 1; break; case 503: action = aKeygen; break; @@ -259,6 +264,10 @@ main( int argc, char **argv ) break; case 519: opt.no_armor=1; opt.armor=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; } } @@ -275,11 +284,11 @@ main( int argc, char **argv ) set_debug(); if( opt.verbose > 1 ) set_packet_list_mode(1); - if( opt.verbose && isatty(fileno(stdin)) ) { + if( greeting ) { if( *(s=strusage(10)) ) - fputs(s, stderr); + tty_printf("%s", s); if( *(s=strusage(30)) ) - fputs(s, stderr); + tty_printf("%s", s); } 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) ); 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: if( argc == 1 ) { @@ -388,6 +405,8 @@ main( int argc, char **argv ) case aTest: do_test( argc? atoi(*argv): 0 ); break; + case aListPackets: + opt.list_packets=1; default: if( argc > 1 ) usage(1); @@ -398,6 +417,10 @@ main( int argc, char **argv ) memset( &afx, 0, sizeof afx); iobuf_push_filter( a, armor_filter, &afx ); } + if( action == aListPackets ) { + set_packet_list_mode(1); + opt.list_packets=1; + } proc_packets( a ); iobuf_close(a); break; @@ -406,7 +429,7 @@ main( int argc, char **argv ) /* cleanup */ FREE_STRLIST(remusr); FREE_STRLIST(locusr); - return 0; + return log_get_errorcount(0)? 2:0; } @@ -509,33 +532,5 @@ do_test(int times) m_check(NULL); #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 } - diff --git a/g10/kbnode.c b/g10/kbnode.c index 844bafe6c..19e0870df 100644 --- a/g10/kbnode.c +++ b/g10/kbnode.c @@ -38,6 +38,7 @@ new_kbnode( PACKET *pkt ) n->pkt = pkt; n->child = NULL; n->flag = 0; + n->private_flag=0; /* kludge to delete a node */ return n; } @@ -58,6 +59,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! */ void @@ -116,26 +127,35 @@ find_kbparent( KBNODE root, KBNODE node ) KBNODE walk_kbtree( KBNODE root, KBNODE *context ) { + return walk_kbtree2( root, context, 0 ); +} + +KBNODE +walk_kbtree2( KBNODE root, KBNODE *context, int all ) +{ KBNODE n; - if( !*context ) { - *context = root; - return root; - } + do { + if( !*context ) { + *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; } @@ -147,3 +167,4 @@ clear_kbnode_flags( KBNODE n ) n->flag = 0; } } + diff --git a/g10/keydb.h b/g10/keydb.h index f0d8b517b..cbca04cb9 100644 --- a/g10/keydb.h +++ b/g10/keydb.h @@ -41,6 +41,7 @@ struct kbnode_struct { KBNODE next; /* used to form a link list */ KBNODE child; 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 ); /*-- passphrase.h --*/ +void set_passphrase_fd( int fd ); +int get_passphrase_fd(void); DEK *get_passphrase_hash( u32 *keyid, char *text ); 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 new_kbnode( PACKET *pkt ); void release_kbnode( KBNODE n ); +void delete_kbnode( KBNODE root, KBNODE node ); void add_kbnode( KBNODE root, KBNODE node ); void add_kbnode_as_child( KBNODE root, KBNODE node ); KBNODE find_kbparent( KBNODE root, KBNODE node ); KBNODE walk_kbtree( KBNODE root, KBNODE *context ); +KBNODE walk_kbtree2( KBNODE root, KBNODE *context, int all ); void clear_kbnode_flags( KBNODE n ); /*-- ringedit.c --*/ diff --git a/g10/keyid.c b/g10/keyid.c index 307e28c61..5848459c8 100644 --- a/g10/keyid.c +++ b/g10/keyid.c @@ -155,7 +155,7 @@ datestr_from_pkc( PKT_public_cert *pkc ) time_t atime = pkc->timestamp; 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; } @@ -167,7 +167,7 @@ datestr_from_skc( PKT_secret_cert *skc ) time_t atime = skc->timestamp; 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; } @@ -179,7 +179,7 @@ datestr_from_sig( PKT_signature *sig ) time_t atime = sig->timestamp; 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; } diff --git a/g10/main.h b/g10/main.h index 0d00dd19a..15caaab9a 100644 --- a/g10/main.h +++ b/g10/main.h @@ -28,15 +28,27 @@ #define DEFAULT_PUBKEY_ALGO PUBKEY_ALGO_ELGAMAL #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 --*/ int encode_symmetric( const char *filename ); int encode_store( const char *filename ); 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 --*/ int sign_file( const char *filename, int detached, STRLIST locusr, int encrypt, STRLIST remusr ); int sign_key( const char *username, STRLIST locusr ); +int edit_keysigs( const char *username ); /*-- sig-check.c --*/ int check_key_signature( KBNODE root, KBNODE node ); diff --git a/g10/mainproc.c b/g10/mainproc.c index 338ce3d2d..b46cb1344 100644 --- a/g10/mainproc.c +++ b/g10/mainproc.c @@ -46,7 +46,6 @@ typedef struct { md_filter_context_t mfx; DEK *dek; int last_was_pubkey_enc; - int opt_list; KBNODE cert; /* the current certificate */ int have_data; 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; 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 || enc->pubkey_algo == PUBKEY_ALGO_RSA ) { m_free(c->dek ); /* paranoid: delete a pending DEK */ @@ -213,11 +212,12 @@ proc_pubkey_enc( CTX c, PACKET *pkt ) if( result == -1 ) ; - else if( !result ) - fputs( " DEK is good", stdout ); + else if( !result ) { + if( opt.verbose > 1 ) + log_info( "pubkey_enc packet: Good DEK\n" ); + } else - printf( " %s", g10_errstr(result)); - putchar('\n'); + log_error( "pubkey_enc packet: %s\n", g10_errstr(result)); free_packet(pkt); } @@ -228,7 +228,7 @@ proc_encrypted( CTX c, PACKET *pkt ) { 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 ) { /* assume this is conventional encrypted data */ 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; if( result == -1 ) ; - else if( !result ) - fputs( " encryption okay",stdout); - else - printf( " %s", g10_errstr(result)); - putchar('\n'); + else if( !result ) { + if( opt.verbose > 1 ) + log_info("encryption okay\n"); + } + else { + log_error("encryption failed: %s\n", g10_errstr(result)); + } free_packet(pkt); c->last_was_pubkey_enc = 0; } @@ -256,9 +258,10 @@ static void proc_plaintext( CTX c, PACKET *pkt ) { 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 ); /* fixme: take the digest algo(s) to use from the * onepass_sig packet (if we have these) @@ -266,12 +269,9 @@ proc_plaintext( CTX c, PACKET *pkt ) * textmode filter (sigclass 0x01) */ c->mfx.md = md_open(DIGEST_ALGO_RMD160, 0); - result = handle_plaintext( pt, &c->mfx ); - if( !result ) - fputs( " okay", stdout); - else - printf( " %s", g10_errstr(result)); - putchar('\n'); + rc = handle_plaintext( pt, &c->mfx ); + if( rc ) + log_error( "handle plaintext failed: %s\n", g10_errstr(rc)); free_packet(pkt); c->last_was_pubkey_enc = 0; } @@ -281,15 +281,12 @@ static void proc_compressed( CTX c, PACKET *pkt ) { PKT_compressed *zd = pkt->pkt.compressed; - int result; + int rc; - printf("zip: compressed data packet\n"); - result = handle_compressed( zd ); - if( !result ) - fputs( " okay", stdout); - else - printf( " %s", g10_errstr(result)); - putchar('\n'); + /*printf("zip: compressed data packet\n");*/ + rc = handle_compressed( zd ); + if( rc ) + log_error("uncompressing failed: %s\n", g10_errstr(rc)); free_packet(pkt); c->last_was_pubkey_enc = 0; } @@ -505,7 +502,6 @@ proc_packets( IOBUF a ) u32 keyid[2]; int newpkt; - c->opt_list = 1; c->iobuf = a; init_packet(pkt); while( (rc=parse_packet(a, pkt)) != -1 ) { @@ -522,17 +518,27 @@ proc_packets( IOBUF a ) continue; } newpkt = -1; - switch( pkt->pkttype ) { - 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( opt.list_packets ) { + switch( pkt->pkttype ) { + case PKT_PUBKEY_ENC: proc_pubkey_enc( c, pkt ); break; + case PKT_ENCRYPTED: proc_encrypted( c, pkt ); break; + case PKT_COMPRESSED: proc_compressed( c, pkt ); break; + default: newpkt = 0; break; + } + } + else { + switch( pkt->pkttype ) { + 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 ) c->have_data = pkt->pkttype == PKT_PLAINTEXT; @@ -575,13 +581,16 @@ proc_tree( CTX c, KBNODE node ) KBNODE n1; int rc; + if( opt.list_packets ) + return; + if( node->pkt->pkttype == PKT_PUBLIC_CERT ) list_node( c, node ); else if( node->pkt->pkttype == PKT_SECRET_CERT ) list_node( c, node ); else if( node->pkt->pkttype == PKT_ONEPASS_SIG ) { 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 ) log_error("proc_tree: onepass_sig not followed by signature\n"); else { /* check all signatures */ @@ -611,6 +620,8 @@ proc_tree( CTX c, KBNODE node ) log_error("BAD signature from "); print_keyid( stderr, sig->keyid ); putc('\n', stderr); + if( opt.batch ) + exit(1); } else log_error("Can't check signature made by %08lX: %s\n", diff --git a/g10/options.h b/g10/options.h index c1aea3f95..31aa95522 100644 --- a/g10/options.h +++ b/g10/options.h @@ -35,7 +35,7 @@ struct { int fingerprint; /* list fingerprints */ int list_sigs; /* list signatures */ int no_armor; - int reserved5; + int list_packets; /* list-packets mode */ int reserved6; int reserved7; int reserved8; diff --git a/g10/packet.h b/g10/packet.h index f7dbf9734..4a5a5a3cc 100644 --- a/g10/packet.h +++ b/g10/packet.h @@ -210,6 +210,7 @@ struct packet_struct { /*-- mainproc.c --*/ int proc_packets( IOBUF a ); +int list_packets( IOBUF a ); /*-- parse-packet.c --*/ int set_packet_list_mode( int mode ); diff --git a/g10/passphrase.c b/g10/passphrase.c index a974ca9f5..df8ac7176 100644 --- a/g10/passphrase.c +++ b/g10/passphrase.c @@ -25,13 +25,27 @@ #include <assert.h> #include "util.h" #include "memory.h" +#include "options.h" #include "ttyio.h" #include "cipher.h" #include "keydb.h" +static int pwfd = -1; 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 @@ -41,35 +55,51 @@ static int hash_passphrase( DEK *dek, char *pw ); DEK * get_passphrase_hash( u32 *keyid, char *text ) { - char *p=NULL, *pw; + char *pw; DEK *dek; - if( keyid ) { + if( keyid && !opt.batch ) { char *ustr; - tty_printf("\nNeed a pass phrase to unlock the secret key!\n"); - tty_printf("KeyID: " ); + tty_printf("Need a pass phrase to unlock the secret key for:\n"); + tty_printf(" \"" ); ustr = get_user_id_string( keyid ); tty_print_string( ustr, strlen(ustr) ); m_free(ustr); - tty_printf("\n\n"); + tty_printf("\"\n\n"); } - if( keyid && (p=getenv("G10PASSPHRASE")) ) { - pw = m_alloc_secure(strlen(p)+1); - strcpy(pw,p); - tty_printf("Taking it from $G10PASSPHRASE !\n", keyid[1] ); + if( pwfd != -1 ) { /* read the passphrase from the given descriptor */ + int i, len; + + 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: " ); + tty_kill_prompt(); + } dek = m_alloc_secure( sizeof *dek ); dek->algo = CIPHER_ALGO_BLOWFISH; if( hash_passphrase( dek, pw ) ) log_bug("get_passphrase_hash\n"); m_free(pw); /* is allocated in secure memory, so it will be burned */ - if( !p ) { - tty_kill_prompt(); - tty_printf("\n"); - } return dek; } @@ -89,6 +119,7 @@ make_dek_from_passphrase( DEK *dek, int mode ) tty_kill_prompt(); if( mode == 2 ) { pw2 = tty_get_hidden("Repeat pass phrase: " ); + tty_kill_prompt(); if( strcmp(pw, pw2) ) { m_free(pw2); m_free(pw); diff --git a/g10/seckey-cert.c b/g10/seckey-cert.c index 85d93b4f9..c1ea596ac 100644 --- a/g10/seckey-cert.c +++ b/g10/seckey-cert.c @@ -65,6 +65,7 @@ check_elg( PKT_secret_cert *cert ) unsigned nbytes; u32 keyid[2]; ELG_secret_key skey; + char save_iv[8]; if( cert->d.elg.is_protected ) { /* remove the protection */ DEK *dek = NULL; @@ -80,6 +81,7 @@ check_elg( PKT_secret_cert *cert ) blowfish_setkey( blowfish_ctx, dek->key, dek->keylen ); m_free(dek); /* pw is in secure memory, so m_free() burns it */ blowfish_setiv( blowfish_ctx, NULL ); + memcpy(save_iv, cert->d.elg.protect.blowfish.iv, 8 ); blowfish_decode_cfb( blowfish_ctx, cert->d.elg.protect.blowfish.iv, 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 */ if( csum != cert->d.elg.csum ) { mpi_free(test_x); + memcpy( cert->d.elg.protect.blowfish.iv, save_iv, 8 ); return G10ERR_BAD_PASS; } @@ -105,6 +108,7 @@ check_elg( PKT_secret_cert *cert ) memset( &skey, 0, sizeof skey ); if( !res ) { mpi_free(test_x); + memcpy( cert->d.elg.protect.blowfish.iv, save_iv, 8 ); return G10ERR_BAD_PASS; } mpi_set(cert->d.elg.x, test_x); @@ -274,6 +278,8 @@ check_secret_key( PKT_secret_cert *cert ) #endif else rc = G10ERR_PUBKEY_ALGO; + if( get_passphrase_fd() != -1 ) + break; } return rc; } diff --git a/g10/sign.c b/g10/sign.c index 67e229f29..a8541391d 100644 --- a/g10/sign.c +++ b/g10/sign.c @@ -79,6 +79,7 @@ sign_file( const char *filename, int detached, STRLIST locusr, compress_filter_context_t zfx; md_filter_context_t mfx; text_filter_context_t tfx; + encrypt_filter_context_t efx; IOBUF inp = NULL, out = NULL; PACKET pkt; PKT_plaintext *pt = NULL; @@ -92,6 +93,7 @@ sign_file( const char *filename, int detached, STRLIST locusr, memset( &zfx, 0, sizeof zfx); memset( &mfx, 0, sizeof mfx); memset( &tfx, 0, sizeof tfx); + memset( &efx, 0, sizeof efx); init_packet( &pkt ); 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 ); if( encrypt ) { - /* prepare for encryption */ - /* FIXME!!!!!!! */ + efx.pkc_list = pkc_list; + /* fixme: set efx.cfx.datalen if known */ + iobuf_push_filter( out, encrypt_filter, &efx ); } /* 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 ) { KBNODE kbctx; @@ -384,6 +395,7 @@ check_all_keysigs( KBNODE keyblock ) m_free(p); } tty_printf("\n"); + /* FIXME: update the trustdb */ } } if( inv_sigs ) @@ -392,6 +404,76 @@ check_all_keysigs( KBNODE keyblock ) tty_printf("No public key for %d signatures\n", no_key ); if( 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; int any; u32 pkc_keyid[2]; + char *answer; memset( &mfx, 0, sizeof mfx); @@ -464,9 +547,16 @@ sign_key( const char *username, STRLIST locusr ) } clear_kbnode_flags( keyblock ); - check_all_keysigs( keyblock ); - /* look wether we should ask to remove invalid keys */ - /*+ FIXME: */ + if( check_all_keysigs( keyblock ) ) { + if( !opt.batch ) { + /* 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 */ 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 ); if( rc ) { - log_error("insert_keyblock failed: %s\n", g10_errstr(rc) ); + log_error("update_keyblock failed: %s\n", g10_errstr(rc) ); 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 * and the user id and return it in ret_sig. User signature class SIGCLASS diff --git a/g10/trustdb.c b/g10/trustdb.c new file mode 100644 index 000000000..00774f572 --- /dev/null +++ b/g10/trustdb.c @@ -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" + + + |