aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>1997-12-02 19:36:53 +0000
committerWerner Koch <[email protected]>1997-12-02 19:36:53 +0000
commitcccf1efa4bcb97e2951a25ebd6250950d73d5169 (patch)
treeddf7e191b2782961c1494f0ab1e0c9ece0f0b6ca
parentList and check sigs works (diff)
downloadgnupg-cccf1efa4bcb97e2951a25ebd6250950d73d5169.tar.gz
gnupg-cccf1efa4bcb97e2951a25ebd6250950d73d5169.zip
Sicherung
Diffstat (limited to '')
-rw-r--r--TODO9
-rw-r--r--g10/build-packet.c29
-rw-r--r--g10/g10.c2
-rw-r--r--g10/mainproc.c97
-rw-r--r--g10/packet.h16
-rw-r--r--g10/parse-packet.c42
-rw-r--r--util/iobuf.c2
7 files changed, 186 insertions, 11 deletions
diff --git a/TODO b/TODO
index 2076d25f5..03f4faa4b 100644
--- a/TODO
+++ b/TODO
@@ -6,7 +6,6 @@
function of iobuf.
* filter all output read from the input when displaying it to the user.
* keyring editing
- * remove some debugging stuff (e.g. the listing mode in mainproc)
* add trust stuff
* make ttyio.c work (hide passwords etc..)
* add detached signatures
@@ -24,3 +23,11 @@
* add signal handling
* enable a SIGSEGV handler while using zlib functions
+ * PGP writes the signature and then the file, this is not
+ a good idea, we can't write such files if we take input rom stdin.
+ So the solution will: accept such packet, but write
+ signature the corret way: first the data and then the signature[s]
+ this is much easier to check, also we must read the entire data
+ before we can check wether we have the pubkey or not. The one-pass
+ signature packets should be implemented to avoid this.
+
diff --git a/g10/build-packet.c b/g10/build-packet.c
index 910929658..6d9957f17 100644
--- a/g10/build-packet.c
+++ b/g10/build-packet.c
@@ -44,6 +44,7 @@ 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_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 );
static int write_16(IOBUF inp, u16 a);
@@ -95,6 +96,9 @@ build_packet( IOBUF out, PACKET *pkt )
case PKT_SIGNATURE:
rc = do_signature( out, ctb, pkt->pkt.signature );
break;
+ case PKT_ONEPASS_SIG:
+ rc = do_onepass_sig( out, ctb, pkt->pkt.onepass_sig );
+ break;
case PKT_RING_TRUST:
default:
log_bug("invalid packet type in build_packet()");
@@ -124,6 +128,7 @@ calc_packet_length( PACKET *pkt )
case PKT_PUBKEY_ENC:
case PKT_ENCRYPTED:
case PKT_SIGNATURE:
+ case PKT_ONEPASS_SIG:
case PKT_RING_TRUST:
case PKT_COMPRESSED:
default:
@@ -399,6 +404,30 @@ do_signature( IOBUF out, int ctb, PKT_signature *sig )
static int
+do_onepass_sig( IOBUF out, int ctb, PKT_onepass_sig *ops )
+{
+ int rc = 0;
+ IOBUF a = iobuf_temp();
+
+ write_version( a, ctb );
+ iobuf_put(a, ops->sig_class );
+ iobuf_put(a, ops->digest_algo );
+ iobuf_put(a, ops->pubkey_algo );
+ write_32(a, ops->keyid[0] );
+ write_32(a, ops->keyid[1] );
+ iobuf_put(a, ops->last );
+
+ write_header(out, ctb, iobuf_get_temp_length(a) );
+ if( iobuf_write_temp( out, a ) )
+ rc = G10ERR_WRITE_FILE;
+
+ leave:
+ iobuf_close(a);
+ return rc;
+}
+
+
+static int
write_16(IOBUF out, u16 a)
{
iobuf_put(out, a>>8);
diff --git a/g10/g10.c b/g10/g10.c
index a27bd19b6..345ccd5ae 100644
--- a/g10/g10.c
+++ b/g10/g10.c
@@ -230,7 +230,7 @@ main( int argc, char **argv )
case aSign: /* sign the given file */
if( argc > 1 )
usage(1);
- if( (rc = sign_file(fname, 0, locusr)) )
+ if( (rc = sign_file(fname, opt.detached_sig, locusr)) )
log_error("sign_file('%s'): %s\n", fname_print, g10_errstr(rc) );
break;
diff --git a/g10/mainproc.c b/g10/mainproc.c
index fd814cc80..8004c3803 100644
--- a/g10/mainproc.c
+++ b/g10/mainproc.c
@@ -75,6 +75,7 @@ typedef struct {
static void list_node( CTX c, NODE node );
+static void proc_tree( CTX c, NODE node );
static int
pubkey_letter( int algo )
@@ -142,12 +143,31 @@ release_cert( CTX c )
{
if( !c->cert )
return;
- list_node(c, c->cert );
+ proc_tree(c, c->cert );
release_node( c->cert );
c->cert = NULL;
}
+static int
+add_onepass_sig( CTX c, PACKET *pkt )
+{
+ if( c->cert ) { /* add another packet */
+ NODE node;
+
+ if( c->cert->pkt->pkttype != PKT_ONEPASS_SIG ) {
+ log_error("add_onepass_sig: another packet is in the way\n");
+ release_cert( c );
+ }
+ node = new_node( pkt );
+ node->next = c->cert;
+ c->cert = node;
+ }
+ else /* insert the first one */
+ c->cert = new_node( pkt );
+ return 1;
+}
+
static int
add_public_cert( CTX c, PACKET *pkt )
@@ -205,10 +225,24 @@ add_signature( CTX c, PACKET *pkt )
NODE node, n1, n2;
if( !c->cert ) {
- log_error("orphaned signature (no certificate)\n" );
+ /* orphaned signature (no certificate)
+ * this is the first signature for a following datafile
+ */
return 0;
}
assert( c->cert->pkt );
+ if( c->cert->pkt->pkttype == PKT_ONEPASS_SIG ) {
+ /* The root is a onepass signature, so we are signing data
+ * The childs direct under the root are the signatures
+ * (there is no need to keep the correct sequence of packets)
+ */
+ node = new_node( pkt );
+ node->next = c->cert->child;
+ c->cert->child = node;
+ return 1;
+ }
+
+
if( !c->cert->child ) {
log_error("orphaned signature (no userid)\n" );
return 0;
@@ -531,6 +565,7 @@ proc_packets( IOBUF a )
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( newpkt == -1 )
@@ -553,3 +588,61 @@ proc_packets( IOBUF a )
}
+static void
+print_keyid( FILE *fp, u32 *keyid )
+{
+ size_t n;
+ char *p = get_user_id( keyid, &n );
+ print_string( fp, p, n );
+ m_free(p);
+}
+
+/****************
+ * Preocess the tree which starts at node
+ */
+static void
+proc_tree( CTX c, NODE node )
+{
+ NODE n1;
+ int rc;
+
+ 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");
+ else if( node->child->pkt->pkttype != PKT_SIGNATURE )
+ log_error("proc_tree: onepass_sig not followed by signature\n");
+ else { /* check all signature */
+ for(n1=node->child; n1; n1 = n1->next ) {
+ PKT_signature *sig = n1->pkt->pkt.signature;
+
+ rc = do_check_sig(c, n1 );
+ if( !rc ) {
+ log_info("Good signature from ");
+ print_keyid( stderr, sig->keyid );
+ putc('\n', stderr);
+ }
+ else if( rc == G10ERR_BAD_SIGN ) {
+ log_error("BAD signature from ");
+ print_keyid( stderr, sig->keyid );
+ putc('\n', stderr);
+ }
+ else
+ log_error("Can't check signature made by %08lX: %s\n",
+ sig->keyid[1], g10_errstr(rc) );
+ }
+ }
+ }
+ else if( node->pkt->pkttype == PKT_SIGNATURE ) {
+ log_info("proc_tree: old style signature\n");
+ }
+ else
+ log_error("proc_tree: invalid root packet\n");
+
+}
+
+
+
diff --git a/g10/packet.h b/g10/packet.h
index bef97a41f..63626307e 100644
--- a/g10/packet.h
+++ b/g10/packet.h
@@ -65,6 +65,15 @@ typedef struct {
typedef struct {
u32 keyid[2]; /* 64 bit keyid */
+ byte sig_class; /* sig classification */
+ byte digest_algo; /* algorithm used for digest */
+ byte pubkey_algo; /* algorithm used for public key scheme */
+ byte last; /* a stupid flag */
+} PKT_onepass_sig;
+
+
+typedef struct {
+ u32 keyid[2]; /* 64 bit keyid */
u32 timestamp; /* signature made */
byte sig_class; /* sig classification, append for MD calculation*/
byte pubkey_algo; /* algorithm used for public key scheme */
@@ -182,12 +191,10 @@ typedef struct {
/* combine all packets into a union */
struct packet_struct {
pkttype_t pkttype;
- PKT_public_cert *pkc_parent; /* the pubkey to which it belongs */
- PKT_secret_cert *skc_parent; /* the seckey to which it belongs */
- PKT_user_id *user_parent; /* the user_id to which it belongs */
union {
void *generic;
PKT_pubkey_enc *pubkey_enc; /* PKT_PUBKEY_ENC */
+ PKT_onepass_sig *onepass_sig; /* PKT_ONEPASS_SIG */
PKT_signature *signature; /* PKT_SIGNATURE */
PKT_public_cert *public_cert; /* PKT_PUBLIC_CERT */
PKT_secret_cert *secret_cert; /* PKT_SECRET_CERT */
@@ -200,9 +207,6 @@ struct packet_struct {
};
#define init_packet(a) do { (a)->pkttype = 0; \
- (a)->pkc_parent = NULL; \
- (a)->skc_parent = NULL; \
- (a)->user_parent = NULL; \
(a)->pkt.generic = NULL; \
} while(0)
diff --git a/g10/parse-packet.c b/g10/parse-packet.c
index dd049406b..6aef1b4fe 100644
--- a/g10/parse-packet.c
+++ b/g10/parse-packet.c
@@ -42,6 +42,8 @@ static int parse_publickey( IOBUF inp, int pkttype, unsigned long pktlen,
PACKET *packet );
static int parse_signature( IOBUF inp, int pkttype, unsigned long pktlen,
PKT_signature *sig );
+static int parse_onepass_sig( IOBUF inp, int pkttype, unsigned long pktlen,
+ PKT_onepass_sig *ops );
static int parse_certificate( IOBUF inp, int pkttype, unsigned long pktlen,
byte *hdr, int hdrlen, PACKET *packet );
static int parse_user_id( IOBUF inp, int pkttype, unsigned long pktlen,
@@ -159,6 +161,10 @@ parse_packet( IOBUF inp, PACKET *pkt )
pkt->pkt.signature = m_alloc_clear(sizeof *pkt->pkt.signature );
rc = parse_signature(inp, pkttype, pktlen, pkt->pkt.signature );
break;
+ case PKT_ONEPASS_SIG:
+ pkt->pkt.onepass_sig = m_alloc_clear(sizeof *pkt->pkt.onepass_sig );
+ rc = parse_onepass_sig(inp, pkttype, pktlen, pkt->pkt.onepass_sig );
+ break;
case PKT_USER_ID:
rc = parse_user_id(inp, pkttype, pktlen, pkt );
break;
@@ -340,6 +346,42 @@ parse_signature( IOBUF inp, int pkttype, unsigned long pktlen,
}
+static int
+parse_onepass_sig( IOBUF inp, int pkttype, unsigned long pktlen,
+ PKT_onepass_sig *ops )
+{
+ int version;
+ unsigned n;
+
+ if( pktlen < 13 ) {
+ log_error("packet(%d) too short\n", pkttype);
+ goto leave;
+ }
+ version = iobuf_get_noeof(inp); pktlen--;
+ if( version != 3 ) {
+ log_error("onepass_sig with unknown version %d\n", version);
+ goto leave;
+ }
+ ops->sig_class = iobuf_get_noeof(inp); pktlen--;
+ ops->digest_algo = iobuf_get_noeof(inp); pktlen--;
+ ops->pubkey_algo = iobuf_get_noeof(inp); pktlen--;
+ ops->keyid[0] = read_32(inp); pktlen -= 4;
+ ops->keyid[1] = read_32(inp); pktlen -= 4;
+ ops->last = iobuf_get_noeof(inp); pktlen--;
+ if( list_mode )
+ printf(":onepass_sig packet: keyid %08lX%08lX\n"
+ "\tversion %d, sigclass %02x, digest %d, pubkey %d, last=%d\n",
+ ops->keyid[0], ops->keyid[1],
+ version, ops->sig_class,
+ ops->digest_algo, ops->pubkey_algo, ops->last );
+
+
+ leave:
+ skip_rest(inp, pktlen);
+ return 0;
+}
+
+
static int
diff --git a/util/iobuf.c b/util/iobuf.c
index 466f07e31..61e1c5909 100644
--- a/util/iobuf.c
+++ b/util/iobuf.c
@@ -283,7 +283,7 @@ iobuf_cancel( IOBUF a )
{
const char *s;
- if( a->usage == 2 ) {
+ if( a && a->usage == 2 ) {
s = iobuf_get_fname(a);
if( s && *s )
remove(s); /* remove the file. Fixme: this will fail for MSDOZE*/