Sicherung

This commit is contained in:
Werner Koch 1997-12-02 19:36:53 +00:00
parent 5c1cca042e
commit cccf1efa4b
7 changed files with 186 additions and 11 deletions

9
TODO
View File

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

View File

@ -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:
@ -398,6 +403,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)
{

View File

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

View File

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

View File

@ -63,6 +63,15 @@ typedef struct {
} PKT_pubkey_enc;
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 */
@ -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)

View File

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

View File

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