mirror of
git://git.gnupg.org/gnupg.git
synced 2025-04-17 15:44:34 +02:00
armor rewritten, but still buggy
This commit is contained in:
parent
899b8378ec
commit
9886ad8098
9
NEWS
9
NEWS
@ -1,7 +1,14 @@
|
|||||||
|
|
||||||
|
* It's now 64 bit clean and runs fine on an alpha--linux.
|
||||||
|
|
||||||
|
* Key generation is much faster now. I fixed this by using not
|
||||||
|
so strong random number for the primes (this was a bug because the
|
||||||
|
ElGamal primes are public parameters and it does not make sense
|
||||||
|
to generate them from strong random). The real secret is the x value
|
||||||
|
which is still generated from strong (okay: /dev/random) random bits.
|
||||||
|
|
||||||
* added option "--status-fd": see g10/OPTIONS
|
* added option "--status-fd": see g10/OPTIONS
|
||||||
|
|
||||||
|
|
||||||
* We have secure memeory on systems which support mlock().
|
* We have secure memeory on systems which support mlock().
|
||||||
It is not complete yet, because we do not have signal handler
|
It is not complete yet, because we do not have signal handler
|
||||||
which does a cleanup in very case.
|
which does a cleanup in very case.
|
||||||
|
4
TODO
4
TODO
@ -27,3 +27,7 @@
|
|||||||
we have a self-signature -> put this stuff into a kind of directory
|
we have a self-signature -> put this stuff into a kind of directory
|
||||||
record, as it does not belong to the pubkey record?
|
record, as it does not belong to the pubkey record?
|
||||||
|
|
||||||
|
* Have no prototype for stpcpy() when using glibc 2; must switch on
|
||||||
|
the GNU extensions or see how configure can fix it.
|
||||||
|
|
||||||
|
|
||||||
|
@ -20,6 +20,10 @@
|
|||||||
#ifndef G10_CONFIG_H
|
#ifndef G10_CONFIG_H
|
||||||
#define G10_CONFIG_H
|
#define G10_CONFIG_H
|
||||||
|
|
||||||
|
/* need this, because some autoconf tests rely on this (e.g. stpcpy)
|
||||||
|
* and it should be used for new programs
|
||||||
|
*/
|
||||||
|
#define _GNU_SOURCE 1
|
||||||
|
|
||||||
@TOP@
|
@TOP@
|
||||||
|
|
||||||
|
@ -21,6 +21,10 @@
|
|||||||
#ifndef G10_CONFIG_H
|
#ifndef G10_CONFIG_H
|
||||||
#define G10_CONFIG_H
|
#define G10_CONFIG_H
|
||||||
|
|
||||||
|
/* need this, because some autoconf tests rely on this (e.g. stpcpy)
|
||||||
|
* and it should be used for new programs
|
||||||
|
*/
|
||||||
|
#define _GNU_SOURCE 1
|
||||||
|
|
||||||
|
|
||||||
/* Define to empty if the keyword does not work. */
|
/* Define to empty if the keyword does not work. */
|
||||||
|
228
g10/armor.c
228
g10/armor.c
@ -32,6 +32,8 @@
|
|||||||
#include "filter.h"
|
#include "filter.h"
|
||||||
#include "packet.h"
|
#include "packet.h"
|
||||||
#include "options.h"
|
#include "options.h"
|
||||||
|
#include "main.h"
|
||||||
|
#include "status.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -65,8 +67,12 @@ typedef enum {
|
|||||||
fhdrEMPTYClearsig,
|
fhdrEMPTYClearsig,
|
||||||
fhdrCHECKClearsig,
|
fhdrCHECKClearsig,
|
||||||
fhdrCHECKClearsig2,
|
fhdrCHECKClearsig2,
|
||||||
|
fhdrCHECKDashEscaped,
|
||||||
|
fhdrCHECKDashEscaped2,
|
||||||
|
fhdrCHECKDashEscaped3,
|
||||||
fhdrREADClearsigNext,
|
fhdrREADClearsigNext,
|
||||||
fhdrENDClearsig,
|
fhdrENDClearsig,
|
||||||
|
fhdrTESTSpaces,
|
||||||
fhdrTEXT,
|
fhdrTEXT,
|
||||||
fhdrERROR,
|
fhdrERROR,
|
||||||
fhdrERRORShow,
|
fhdrERRORShow,
|
||||||
@ -92,8 +98,8 @@ static char *tail_strings[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static fhdr_state_t find_header( fhdr_state_t state,
|
static fhdr_state_t find_header( fhdr_state_t state, byte *buf,
|
||||||
byte *buf, size_t *r_buflen, IOBUF a, size_t n);
|
size_t *r_buflen, IOBUF a, size_t n, unsigned *r_empty);
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -156,26 +162,36 @@ is_armored( byte *buf )
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
invalid_armor(void)
|
||||||
|
{
|
||||||
|
write_status(STATUS_BADARMOR);
|
||||||
|
g10_exit(1); /* stop here */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/****************
|
/****************
|
||||||
* parse an ascii armor.
|
* parse an ascii armor.
|
||||||
* Returns: the state,
|
* Returns: the state,
|
||||||
* the remaining bytes in BUF are returned in RBUFLEN.
|
* the remaining bytes in BUF are returned in RBUFLEN.
|
||||||
|
* r_empty return the # of empty lines before the buffer
|
||||||
*/
|
*/
|
||||||
static fhdr_state_t
|
static fhdr_state_t
|
||||||
find_header( fhdr_state_t state, byte *buf, size_t *r_buflen, IOBUF a, size_t n)
|
find_header( fhdr_state_t state, byte *buf, size_t *r_buflen,
|
||||||
|
IOBUF a, size_t n, unsigned *r_empty)
|
||||||
{
|
{
|
||||||
int c, i;
|
int c, i;
|
||||||
const char *s;
|
const char *s;
|
||||||
char *p;
|
byte *p;
|
||||||
size_t buflen;
|
size_t buflen;
|
||||||
int cont;
|
int cont;
|
||||||
int clearsig=0;
|
int clearsig=0;
|
||||||
int hdr_line=0;
|
int hdr_line=0;
|
||||||
|
unsigned empty = 0;
|
||||||
|
|
||||||
buflen = *r_buflen;
|
buflen = *r_buflen;
|
||||||
assert(buflen >= 100 );
|
assert(buflen >= 100 );
|
||||||
buflen--;
|
buflen -= 3; /* reserved room for CR,LF and one extra */
|
||||||
|
|
||||||
do {
|
do {
|
||||||
switch( state ) {
|
switch( state ) {
|
||||||
@ -183,7 +199,7 @@ find_header( fhdr_state_t state, byte *buf, size_t *r_buflen, IOBUF a, size_t n)
|
|||||||
/* read 28 bytes, which is the bare minimum for a BEGIN...
|
/* read 28 bytes, which is the bare minimum for a BEGIN...
|
||||||
* and check wether this has a Armor. */
|
* and check wether this has a Armor. */
|
||||||
c = 0;
|
c = 0;
|
||||||
for(n=0; n < 28 && (c=iobuf_get(a)) != -1 && c != '\n'; )
|
for(n=0; n < 28 && (c=iobuf_get2(a)) != -1 && c != '\n'; )
|
||||||
buf[n++] = c;
|
buf[n++] = c;
|
||||||
if( n < 28 || c == -1 )
|
if( n < 28 || c == -1 )
|
||||||
state = fhdrNOArmor; /* too short */
|
state = fhdrNOArmor; /* too short */
|
||||||
@ -197,27 +213,27 @@ find_header( fhdr_state_t state, byte *buf, size_t *r_buflen, IOBUF a, size_t n)
|
|||||||
n = 0;
|
n = 0;
|
||||||
case fhdrINITCont: /* read more stuff into buffer */
|
case fhdrINITCont: /* read more stuff into buffer */
|
||||||
c = 0;
|
c = 0;
|
||||||
for(; n < buflen && (c=iobuf_get(a)) != -1 && c != '\n'; )
|
for(; n < buflen && (c=iobuf_get2(a)) != -1 && c != '\n'; )
|
||||||
buf[n++] = c;
|
buf[n++] = c;
|
||||||
state = c == '\n' ? fhdrCHECKBegin :
|
state = c == '\n' ? fhdrCHECKBegin :
|
||||||
c == -1 ? fhdrEOF : fhdrINITSkip;
|
c == -1 ? fhdrEOF : fhdrINITSkip;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case fhdrINITSkip:
|
case fhdrINITSkip:
|
||||||
while( (c=iobuf_get(a)) != -1 && c != '\n' )
|
while( (c=iobuf_get2(a)) != -1 && c != '\n' )
|
||||||
;
|
;
|
||||||
state = c == -1? fhdrEOF : fhdrINIT;
|
state = c == -1? fhdrEOF : fhdrINIT;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case fhdrSKIPHeader:
|
case fhdrSKIPHeader:
|
||||||
while( (c=iobuf_get(a)) != -1 && c != '\n' )
|
while( (c=iobuf_get2(a)) != -1 && c != '\n' )
|
||||||
;
|
;
|
||||||
state = c == -1? fhdrEOF : fhdrWAITHeader;
|
state = c == -1? fhdrEOF : fhdrWAITHeader;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case fhdrWAITHeader: /* wait for Header lines */
|
case fhdrWAITHeader: /* wait for Header lines */
|
||||||
c = 0;
|
c = 0;
|
||||||
for(n=0; n < buflen && (c=iobuf_get(a)) != -1 && c != '\n'; )
|
for(n=0; n < buflen && (c=iobuf_get2(a)) != -1 && c != '\n'; )
|
||||||
buf[n++] = c;
|
buf[n++] = c;
|
||||||
buf[n] = 0;
|
buf[n] = 0;
|
||||||
if( n < buflen || c == '\n' ) {
|
if( n < buflen || c == '\n' ) {
|
||||||
@ -229,21 +245,21 @@ find_header( fhdr_state_t state, byte *buf, size_t *r_buflen, IOBUF a, size_t n)
|
|||||||
state = fhdrWAITHeader;
|
state = fhdrWAITHeader;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
state = fhdrTEXT;
|
state = fhdrCHECKDashEscaped3;
|
||||||
}
|
}
|
||||||
else if( !n || (buf[0] == '\r' && !buf[1]) ) { /* empty line */
|
else if( !n || (buf[0] == '\r' && !buf[1]) ) { /* empty line */
|
||||||
if( clearsig )
|
if( clearsig )
|
||||||
state = fhdrWAITClearsig;
|
state = fhdrWAITClearsig;
|
||||||
else {
|
else {
|
||||||
/* this is not really correct: if we do not have
|
/* this is not really correct: if we do not have
|
||||||
* a clearsig and not armor lines we are not allowed
|
* a clearsig and no armor lines we are not allowed
|
||||||
* to have an empty line */
|
* to have an empty line */
|
||||||
n = 0;
|
n = 0;
|
||||||
state = fhdrTEXT;
|
state = fhdrTEXT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
log_debug("invalid armor header: ");
|
log_error("invalid armor header: ");
|
||||||
print_string( stderr, buf, n );
|
print_string( stderr, buf, n );
|
||||||
putc('\n', stderr);
|
putc('\n', stderr);
|
||||||
state = fhdrERROR;
|
state = fhdrERROR;
|
||||||
@ -265,17 +281,21 @@ find_header( fhdr_state_t state, byte *buf, size_t *r_buflen, IOBUF a, size_t n)
|
|||||||
|
|
||||||
case fhdrWAITClearsig: /* skip all empty lines (for clearsig) */
|
case fhdrWAITClearsig: /* skip all empty lines (for clearsig) */
|
||||||
c = 0;
|
c = 0;
|
||||||
for(n=0; n < buflen && (c=iobuf_get(a)) != -1 && c != '\n'; )
|
for(n=0; n < buflen && (c=iobuf_get2(a)) != -1 && c != '\n'; )
|
||||||
buf[n++] = c;
|
buf[n++] = c;
|
||||||
if( n < buflen || c == '\n' ) {
|
if( n < buflen || c == '\n' ) {
|
||||||
buf[n] = 0;
|
buf[n] = 0;
|
||||||
if( !n || (buf[0]=='\r' && !buf[1]) ) /* empty line */
|
if( !n || (buf[0]=='\r' && !buf[1]) ) /* empty line */
|
||||||
;
|
;
|
||||||
else
|
else
|
||||||
state = fhdrTEXT;
|
state = fhdrCHECKDashEscaped3;
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
|
/* fixme: we should check wether this linee continues
|
||||||
|
* it is poosible that we have only read ws until here
|
||||||
|
* and more stuff is to come */
|
||||||
state = fhdrEOF;
|
state = fhdrEOF;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case fhdrENDClearsig:
|
case fhdrENDClearsig:
|
||||||
@ -313,17 +333,17 @@ find_header( fhdr_state_t state, byte *buf, size_t *r_buflen, IOBUF a, size_t n)
|
|||||||
case fhdrEMPTYClearsig:
|
case fhdrEMPTYClearsig:
|
||||||
case fhdrREADClearsig:
|
case fhdrREADClearsig:
|
||||||
/* we are at the start of a line: read a clearsig into the buffer
|
/* we are at the start of a line: read a clearsig into the buffer
|
||||||
* we have to look for a the header line or dashd escaped text*/
|
* we have to look for a the header line or dashed escaped text*/
|
||||||
n = 0;
|
n = 0;
|
||||||
c = 0;
|
c = 0;
|
||||||
for(; n < buflen && (c=iobuf_get(a)) != -1 && c != '\n'; )
|
while( n < buflen && (c=iobuf_get2(a)) != -1 && c != '\n' )
|
||||||
buf[n++] = c;
|
buf[n++] = c;
|
||||||
buf[n] = 0;
|
buf[n] = 0;
|
||||||
if( c == -1 )
|
if( c == -1 )
|
||||||
state = fhdrEOF;
|
state = fhdrEOF;
|
||||||
else if( !n || ( buf[0]=='\r' && !buf[1] ) ) {
|
else if( !n || ( buf[0]=='\r' && !buf[1] ) ) {
|
||||||
state = fhdrEMPTYClearsig;
|
state = fhdrEMPTYClearsig;
|
||||||
/* FIXME: handle it */
|
empty++;
|
||||||
}
|
}
|
||||||
else if( c == '\n' )
|
else if( c == '\n' )
|
||||||
state = fhdrCHECKClearsig2;
|
state = fhdrCHECKClearsig2;
|
||||||
@ -331,43 +351,86 @@ find_header( fhdr_state_t state, byte *buf, size_t *r_buflen, IOBUF a, size_t n)
|
|||||||
state = fhdrCHECKClearsig;
|
state = fhdrCHECKClearsig;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case fhdrCHECKClearsig:
|
case fhdrCHECKDashEscaped3:
|
||||||
case fhdrCHECKClearsig2:
|
if( !(n > 1 && buf[0] == '-' && buf[1] == ' ' ) ) {
|
||||||
/* check the clearsig line */
|
state = fhdrTEXT;
|
||||||
if( n > 15 && !memcmp(buf, "-----", 5 ) )
|
break;
|
||||||
state = fhdrENDClearsig;
|
}
|
||||||
else if( buf[0] == '-' && buf[1] == ' ' ) {
|
/* fall through */
|
||||||
/* dash escaped line */
|
case fhdrCHECKDashEscaped2:
|
||||||
|
case fhdrCHECKDashEscaped:
|
||||||
|
/* check dash escaped line */
|
||||||
if( buf[2] == '-' || ( n > 6 && !memcmp(buf+2, "From ", 5))) {
|
if( buf[2] == '-' || ( n > 6 && !memcmp(buf+2, "From ", 5))) {
|
||||||
for(i=2; i < n; i++ )
|
for(i=2; i < n; i++ )
|
||||||
buf[i-2] = buf[i];
|
buf[i-2] = buf[i];
|
||||||
n -= 2;
|
n -= 2;
|
||||||
buf[n] = 0; /* not really needed */
|
buf[n] = 0; /* not really needed */
|
||||||
state = state == fhdrCHECKClearsig2 ?
|
state = state == fhdrCHECKDashEscaped3 ? fhdrTEXT :
|
||||||
fhdrREADClearsig : fhdrREADClearsigNext;
|
state == fhdrCHECKDashEscaped2 ?
|
||||||
/* FIXME: add the lf to the buffer */
|
fhdrREADClearsig : fhdrTESTSpaces;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
log_debug("invalid dash escaped line: ");
|
log_error("invalid dash escaped line: ");
|
||||||
print_string( stderr, buf, n );
|
print_string( stderr, buf, n );
|
||||||
putc('\n', stderr);
|
putc('\n', stderr);
|
||||||
state = fhdrERROR;
|
state = fhdrERROR;
|
||||||
}
|
}
|
||||||
}
|
break;
|
||||||
|
|
||||||
|
case fhdrCHECKClearsig:
|
||||||
|
case fhdrCHECKClearsig2:
|
||||||
|
/* check the clearsig line */
|
||||||
|
if( n > 15 && !memcmp(buf, "-----", 5 ) )
|
||||||
|
state = fhdrENDClearsig;
|
||||||
|
else if( buf[0] == '-' && buf[1] == ' ' )
|
||||||
|
state = fhdrCHECKDashEscaped;
|
||||||
else {
|
else {
|
||||||
state = state == fhdrCHECKClearsig2 ?
|
state = state == fhdrCHECKClearsig2 ?
|
||||||
fhdrREADClearsig : fhdrREADClearsigNext;
|
fhdrREADClearsig : fhdrTESTSpaces;
|
||||||
/* FIXME: add the lf to the buffer */
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case fhdrREADClearsigNext:
|
case fhdrREADClearsigNext:
|
||||||
/* Read to the end of the line, do not care about checking
|
/* Read to the end of the line, do not care about checking
|
||||||
* for dashed escaped text of headers */
|
* for dashed escaped text of headers */
|
||||||
|
c = 0;
|
||||||
|
n = 0;
|
||||||
|
while( n < buflen && (c=iobuf_get2(a)) != -1 && c != '\n' )
|
||||||
|
buf[n++] = c;
|
||||||
|
buf[n] = 0;
|
||||||
|
if( c == -1 )
|
||||||
|
state = fhdrEOF;
|
||||||
|
else if( c == '\n' )
|
||||||
|
state = fhdrREADClearsig;
|
||||||
|
else
|
||||||
|
state = fhdrTESTSpaces;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case fhdrTESTSpaces: {
|
||||||
|
/* but must check wether the rest of the line
|
||||||
|
* does only contain white spaces; this is problematic
|
||||||
|
* since we may have to restore the stuffs. simply
|
||||||
|
* counting spaces is not enough, because it may be a
|
||||||
|
* mix of different white space chacters */
|
||||||
|
IOBUF b = iobuf_temp();
|
||||||
|
while( (c=iobuf_get2(a)) != -1 && c != '\n' ) {
|
||||||
|
iobuf_put(b,c);
|
||||||
|
if( c != ' ' && c != '\t' && c != '\r' )
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if( c == '\n' ) {
|
||||||
|
/* okay we can skip the rest of the line */
|
||||||
|
iobuf_close(b);
|
||||||
|
state = fhdrREADClearsig;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
iobuf_unget_and_close_temp(a,b);
|
||||||
|
state = fhdrREADClearsigNext;
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
case fhdrERRORShow:
|
case fhdrERRORShow:
|
||||||
log_debug("invalid clear text header: ");
|
log_error("invalid clear text header: ");
|
||||||
print_string( stderr, buf, n );
|
print_string( stderr, buf, n );
|
||||||
putc('\n', stderr);
|
putc('\n', stderr);
|
||||||
state = fhdrERROR;
|
state = fhdrERROR;
|
||||||
@ -386,6 +449,10 @@ find_header( fhdr_state_t state, byte *buf, size_t *r_buflen, IOBUF a, size_t n)
|
|||||||
case fhdrEMPTYClearsig:
|
case fhdrEMPTYClearsig:
|
||||||
case fhdrCHECKClearsig:
|
case fhdrCHECKClearsig:
|
||||||
case fhdrCHECKClearsig2:
|
case fhdrCHECKClearsig2:
|
||||||
|
case fhdrCHECKDashEscaped:
|
||||||
|
case fhdrCHECKDashEscaped2:
|
||||||
|
case fhdrCHECKDashEscaped3:
|
||||||
|
case fhdrTESTSpaces:
|
||||||
case fhdrERRORShow:
|
case fhdrERRORShow:
|
||||||
cont = 1;
|
cont = 1;
|
||||||
break;
|
break;
|
||||||
@ -395,7 +462,28 @@ find_header( fhdr_state_t state, byte *buf, size_t *r_buflen, IOBUF a, size_t n)
|
|||||||
|
|
||||||
if( clearsig && state == fhdrTEXT )
|
if( clearsig && state == fhdrTEXT )
|
||||||
state = fhdrCLEARSIG;
|
state = fhdrCLEARSIG;
|
||||||
|
|
||||||
|
if( state == fhdrCLEARSIG || state == fhdrREADClearsig ) {
|
||||||
|
/* append CR,LF after removing trailing wspaces */
|
||||||
|
for(p=buf+n-1; n; n--, p-- ) {
|
||||||
|
assert( *p != '\n' );
|
||||||
|
if( *p != ' ' && *p != '\t' && *p != '\r' ) {
|
||||||
|
p[1] = '\r';
|
||||||
|
p[2] = '\n';
|
||||||
|
n += 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if( !n ) {
|
||||||
|
buf[0] = '\r';
|
||||||
|
buf[1] = '\n';
|
||||||
|
n = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
*r_buflen = n;
|
*r_buflen = n;
|
||||||
|
*r_empty = empty;
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -407,12 +495,13 @@ check_input( armor_filter_context_t *afx, IOBUF a )
|
|||||||
int rc = 0;
|
int rc = 0;
|
||||||
size_t n;
|
size_t n;
|
||||||
fhdr_state_t state = afx->parse_state;
|
fhdr_state_t state = afx->parse_state;
|
||||||
|
unsigned emplines;
|
||||||
|
|
||||||
if( state != fhdrENDClearsig )
|
if( state != fhdrENDClearsig )
|
||||||
state = fhdrHASArmor;
|
state = fhdrHASArmor;
|
||||||
|
|
||||||
n = DIM(afx->helpbuf);
|
n = DIM(afx->helpbuf);
|
||||||
state = find_header( state, afx->helpbuf, &n, a, afx->helplen );
|
state = find_header( state, afx->helpbuf, &n, a, afx->helplen, &emplines);
|
||||||
switch( state ) {
|
switch( state ) {
|
||||||
case fhdrNOArmor:
|
case fhdrNOArmor:
|
||||||
afx->inp_checked = 1;
|
afx->inp_checked = 1;
|
||||||
@ -421,6 +510,9 @@ check_input( armor_filter_context_t *afx, IOBUF a )
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case fhdrERROR:
|
case fhdrERROR:
|
||||||
|
invalid_armor();
|
||||||
|
break;
|
||||||
|
|
||||||
case fhdrEOF:
|
case fhdrEOF:
|
||||||
rc = -1;
|
rc = -1;
|
||||||
break;
|
break;
|
||||||
@ -458,12 +550,21 @@ fake_packet( armor_filter_context_t *afx, IOBUF a,
|
|||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
size_t n, nn;
|
size_t n, nn;
|
||||||
fhdr_state_t state = afx->parse_state;
|
fhdr_state_t state = afx->parse_state;
|
||||||
|
unsigned emplines = afx->empty;
|
||||||
|
|
||||||
size = 100; /* FIXME: only used for testing (remove it) */
|
size = 100; /* FIXME: only used for testing (remove it) */
|
||||||
|
|
||||||
len = 2; /* reserve 2 bytes for the length header */
|
len = 2; /* reserve 2 bytes for the length header */
|
||||||
size -= 2; /* and 2 for the term header */
|
size -= 3; /* and 1 for empline handling and 2 for the term header */
|
||||||
while( !rc && len < size ) {
|
while( !rc && len < size ) {
|
||||||
|
if( emplines ) {
|
||||||
|
while( emplines && len < size ) {
|
||||||
|
buf[len++] = '\r';
|
||||||
|
buf[len++] = '\n';
|
||||||
|
emplines--;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if( afx->helpidx < afx->helplen ) { /* flush the last buffer */
|
if( afx->helpidx < afx->helplen ) { /* flush the last buffer */
|
||||||
n = afx->helplen;
|
n = afx->helplen;
|
||||||
for(nn=afx->helpidx; len < size && nn < n ; nn++ )
|
for(nn=afx->helpidx; len < size && nn < n ; nn++ )
|
||||||
@ -478,14 +579,19 @@ fake_packet( armor_filter_context_t *afx, IOBUF a,
|
|||||||
/* read a new one */
|
/* read a new one */
|
||||||
n = DIM(afx->helpbuf);
|
n = DIM(afx->helpbuf);
|
||||||
afx->helpidx = 0;
|
afx->helpidx = 0;
|
||||||
state = find_header( state, afx->helpbuf, &n, a, 0 );
|
state = find_header( state, afx->helpbuf, &n, a, 0, &emplines );
|
||||||
switch( state) {
|
switch( state) {
|
||||||
case fhdrERROR:
|
case fhdrERROR:
|
||||||
|
invalid_armor();
|
||||||
|
break;
|
||||||
|
|
||||||
case fhdrEOF:
|
case fhdrEOF:
|
||||||
rc = -1;
|
rc = -1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case fhdrCLEARSIG:
|
case fhdrCLEARSIG:
|
||||||
|
BUG();
|
||||||
|
|
||||||
case fhdrREADClearsig:
|
case fhdrREADClearsig:
|
||||||
case fhdrREADClearsigNext:
|
case fhdrREADClearsigNext:
|
||||||
afx->helplen = n;
|
afx->helplen = n;
|
||||||
@ -509,6 +615,7 @@ fake_packet( armor_filter_context_t *afx, IOBUF a,
|
|||||||
}
|
}
|
||||||
|
|
||||||
afx->parse_state = state;
|
afx->parse_state = state;
|
||||||
|
afx->empty = emplines;
|
||||||
*retn = len;
|
*retn = len;
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@ -600,6 +707,8 @@ radix64_read( armor_filter_context_t *afx, IOBUF a, size_t *retn,
|
|||||||
log_error("CRC error; %06lx - %06lx\n",
|
log_error("CRC error; %06lx - %06lx\n",
|
||||||
(ulong)afx->crc, (ulong)mycrc);
|
(ulong)afx->crc, (ulong)mycrc);
|
||||||
else {
|
else {
|
||||||
|
rc = 0;
|
||||||
|
#if 0
|
||||||
for(rc=0;!rc;) {
|
for(rc=0;!rc;) {
|
||||||
rc = 0 /*check_trailer( &fhdr, c )*/;
|
rc = 0 /*check_trailer( &fhdr, c )*/;
|
||||||
if( !rc ) {
|
if( !rc ) {
|
||||||
@ -615,6 +724,7 @@ radix64_read( armor_filter_context_t *afx, IOBUF a, size_t *retn,
|
|||||||
log_error("premature eof (in Trailer)\n");
|
log_error("premature eof (in Trailer)\n");
|
||||||
else
|
else
|
||||||
log_error("error in trailer line\n");
|
log_error("error in trailer line\n");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -641,6 +751,12 @@ armor_filter( void *opaque, int control,
|
|||||||
int idx, idx2;
|
int idx, idx2;
|
||||||
size_t n=0;
|
size_t n=0;
|
||||||
u32 crc;
|
u32 crc;
|
||||||
|
static FILE *fp ;
|
||||||
|
|
||||||
|
if( !fp ) {
|
||||||
|
fp = fopen("armor.out", "w");
|
||||||
|
assert(fp);
|
||||||
|
}
|
||||||
|
|
||||||
if( DBG_FILTER )
|
if( DBG_FILTER )
|
||||||
log_debug("armor-filter: control: %d\n", control );
|
log_debug("armor-filter: control: %d\n", control );
|
||||||
@ -655,8 +771,8 @@ armor_filter( void *opaque, int control,
|
|||||||
*ret_len = n;
|
*ret_len = n;
|
||||||
}
|
}
|
||||||
else if( control == IOBUFCTRL_UNDERFLOW ) {
|
else if( control == IOBUFCTRL_UNDERFLOW ) {
|
||||||
if( size < 20 )
|
if( size < 30 )
|
||||||
BUG(); /* supplied buffer maybe too short */
|
BUG(); /* supplied buffer too short */
|
||||||
|
|
||||||
if( afx->inp_eof ) {
|
if( afx->inp_eof ) {
|
||||||
*ret_len = 0;
|
*ret_len = 0;
|
||||||
@ -672,22 +788,36 @@ armor_filter( void *opaque, int control,
|
|||||||
if( afx->inp_bypass )
|
if( afx->inp_bypass )
|
||||||
;
|
;
|
||||||
else if( afx->faked ) {
|
else if( afx->faked ) {
|
||||||
/* the buffer is at least 20 bytes long, so it
|
/* the buffer is at least 30 bytes long, so it
|
||||||
* is easy to construct a packet */
|
* is easy to construct the packets */
|
||||||
buf[0] = 0xaf; /* old packet format, type 11, var length */
|
|
||||||
buf[1] = 0; /* set the length header */
|
/* first a onepass signature packet */
|
||||||
buf[2] = 6;
|
buf[0] = 0x90; /* old packet forma, type 4, 1 length byte */
|
||||||
buf[3] = 't'; /* canonical text */
|
buf[1] = 13; /* length */
|
||||||
buf[4] = 0; /* namelength */
|
buf[2] = 3; /* version */
|
||||||
buf[5] = buf[6] = buf[7] = buf[8] = 0; /* timestamp */
|
buf[3] = 0x01; /* sigclass 0x01 (data in canonical text mode)*/
|
||||||
n = 9;
|
buf[4] = 0; /* digest algo (don't know) */
|
||||||
|
buf[5] = 0; /* public key algo (don't know) */
|
||||||
|
memset(buf+6, 0, 8); /* don't know the keyid */
|
||||||
|
buf[14] = 1; /* this is the last one */
|
||||||
|
|
||||||
|
/* followed by a plaintext packet */
|
||||||
|
buf[15] = 0xaf; /* old packet format, type 11, var length */
|
||||||
|
buf[16] = 0; /* set the length header */
|
||||||
|
buf[17] = 6;
|
||||||
|
buf[18] = 't'; /* canonical text mode */
|
||||||
|
buf[19] = 0; /* namelength */
|
||||||
|
memset(buf+20, 0, 4); /* timestamp */
|
||||||
|
n = 24;
|
||||||
}
|
}
|
||||||
else if( !rc )
|
else if( !rc )
|
||||||
rc = radix64_read( afx, a, &n, buf, size );
|
rc = radix64_read( afx, a, &n, buf, size );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
rc = radix64_read( afx, a, &n, buf, size );
|
rc = radix64_read( afx, a, &n, buf, size );
|
||||||
|
if( n )
|
||||||
|
if( fwrite(buf, n, 1, fp ) != 1 )
|
||||||
|
BUG();
|
||||||
*ret_len = n;
|
*ret_len = n;
|
||||||
}
|
}
|
||||||
else if( control == IOBUFCTRL_FLUSH ) {
|
else if( control == IOBUFCTRL_FLUSH ) {
|
||||||
|
@ -35,6 +35,7 @@ typedef struct {
|
|||||||
u32 crc;
|
u32 crc;
|
||||||
byte helpbuf[100];
|
byte helpbuf[100];
|
||||||
int helpidx, helplen;
|
int helpidx, helplen;
|
||||||
|
unsigned empty; /* empty line counter */
|
||||||
int faked;
|
int faked;
|
||||||
int parse_state;
|
int parse_state;
|
||||||
int inp_checked; /* set if inp has been checked */
|
int inp_checked; /* set if inp has been checked */
|
||||||
@ -64,11 +65,10 @@ typedef struct {
|
|||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
size_t linesize;
|
|
||||||
byte *line;
|
|
||||||
size_t linelen;
|
|
||||||
size_t pos;
|
|
||||||
int eof;
|
int eof;
|
||||||
|
size_t idx;
|
||||||
|
size_t len;
|
||||||
|
byte buf[256];
|
||||||
} text_filter_context_t;
|
} text_filter_context_t;
|
||||||
|
|
||||||
|
|
||||||
|
59
g10/g10.c
59
g10/g10.c
@ -43,7 +43,7 @@
|
|||||||
|
|
||||||
enum cmd_values { aNull = 0,
|
enum cmd_values { aNull = 0,
|
||||||
aSym, aStore, aEncr, aKeygen, aSign, aSignEncr,
|
aSym, aStore, aEncr, aKeygen, aSign, aSignEncr,
|
||||||
aSignKey, aClearsig, aListPackets, aEditSig,
|
aSignKey, aClearsign, aListPackets, aEditSig,
|
||||||
aKMode, aKModeC, aChangePass, aImport,
|
aKMode, aKModeC, aChangePass, aImport,
|
||||||
aExport,
|
aExport,
|
||||||
aTest };
|
aTest };
|
||||||
@ -146,9 +146,9 @@ set_cmd( enum cmd_values *ret_cmd, enum cmd_values new_cmd )
|
|||||||
cmd = aSignEncr;
|
cmd = aSignEncr;
|
||||||
else if( cmd == aKMode && new_cmd == aSym )
|
else if( cmd == aKMode && new_cmd == aSym )
|
||||||
cmd = aKModeC;
|
cmd = aKModeC;
|
||||||
else if( ( cmd == aSign && new_cmd == aClearsig )
|
else if( ( cmd == aSign && new_cmd == aClearsign )
|
||||||
|| ( cmd == aClearsig && new_cmd == aSign ) )
|
|| ( cmd == aClearsign && new_cmd == aSign ) )
|
||||||
cmd = aClearsig;
|
cmd = aClearsign;
|
||||||
else {
|
else {
|
||||||
log_error(_("conflicting commands\n"));
|
log_error(_("conflicting commands\n"));
|
||||||
g10_exit(2);
|
g10_exit(2);
|
||||||
@ -210,6 +210,7 @@ main( int argc, char **argv )
|
|||||||
{ 536, "marginals-needed", 1, N_("(default is 3)")},
|
{ 536, "marginals-needed", 1, N_("(default is 3)")},
|
||||||
{ 537, "export", 0, N_("export all or the given keys") },
|
{ 537, "export", 0, N_("export all or the given keys") },
|
||||||
{ 538, "trustdb-name", 2, "\r" },
|
{ 538, "trustdb-name", 2, "\r" },
|
||||||
|
{ 539, "clearsign", 0, N_("make a clear text signature") },
|
||||||
|
|
||||||
{0} };
|
{0} };
|
||||||
ARGPARSE_ARGS pargs;
|
ARGPARSE_ARGS pargs;
|
||||||
@ -303,7 +304,7 @@ main( int argc, char **argv )
|
|||||||
case 'e': set_cmd( &cmd, aEncr); break;
|
case 'e': set_cmd( &cmd, aEncr); break;
|
||||||
case 'b': detached_sig = 1; /* fall trough */
|
case 'b': detached_sig = 1; /* fall trough */
|
||||||
case 's': set_cmd( &cmd, aSign ); break;
|
case 's': set_cmd( &cmd, aSign ); break;
|
||||||
case 't': set_cmd( &cmd , aClearsig); break;
|
case 't': set_cmd( &cmd , aClearsign); break;
|
||||||
case 'u': /* 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);
|
||||||
@ -362,6 +363,7 @@ main( int argc, char **argv )
|
|||||||
case 536: opt.marginals_needed = pargs.r.ret_int; break;
|
case 536: opt.marginals_needed = pargs.r.ret_int; break;
|
||||||
case 537: set_cmd( &cmd, aExport); break;
|
case 537: set_cmd( &cmd, aExport); break;
|
||||||
case 538: trustdb_name = pargs.r.ret_str; break;
|
case 538: trustdb_name = pargs.r.ret_str; break;
|
||||||
|
case 539: set_cmd( &cmd, aClearsign); break;
|
||||||
default : errors++; pargs.err = configfp? 1:2; break;
|
default : errors++; pargs.err = configfp? 1:2; break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -454,24 +456,24 @@ main( int argc, char **argv )
|
|||||||
switch( cmd ) {
|
switch( cmd ) {
|
||||||
case aStore: /* only store the file */
|
case aStore: /* only store the file */
|
||||||
if( argc > 1 )
|
if( argc > 1 )
|
||||||
usage(1);
|
wrong_args(_("--store [filename]"));
|
||||||
if( (rc = encode_store(fname)) )
|
if( (rc = encode_store(fname)) )
|
||||||
log_error("encode_store('%s'): %s\n",
|
log_error("%s: store failed: %s\n",
|
||||||
fname_print, g10_errstr(rc) );
|
fname_print, g10_errstr(rc) );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case aSym: /* encrypt the given file only with the symmetric cipher */
|
case aSym: /* encrypt the given file only with the symmetric cipher */
|
||||||
if( argc > 1 )
|
if( argc > 1 )
|
||||||
usage(1);
|
wrong_args(_("--symmetric [filename]"));
|
||||||
if( (rc = encode_symmetric(fname)) )
|
if( (rc = encode_symmetric(fname)) )
|
||||||
log_error("encode_symmetric('%s'): %s\n", fname_print, g10_errstr(rc) );
|
log_error("%s: symmetric encryption failed: %s\n", fname_print, g10_errstr(rc) );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case aEncr: /* encrypt the given file */
|
case aEncr: /* encrypt the given file */
|
||||||
if( argc > 1 )
|
if( argc > 1 )
|
||||||
usage(1);
|
wrong_args(_("--encrypt [filename]"));
|
||||||
if( (rc = encode_crypt(fname,remusr)) )
|
if( (rc = encode_crypt(fname,remusr)) )
|
||||||
log_error("encode_crypt('%s'): %s\n", fname_print, g10_errstr(rc) );
|
log_error("%s: encryption failed: %s\n", fname_print, g10_errstr(rc) );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case aSign: /* sign the given file */
|
case aSign: /* sign the given file */
|
||||||
@ -482,20 +484,20 @@ main( int argc, char **argv )
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if( argc > 1 )
|
if( argc > 1 )
|
||||||
usage(1);
|
wrong_args(_("--sign [filename]"));
|
||||||
if( argc ) {
|
if( argc ) {
|
||||||
sl = m_alloc_clear( sizeof *sl + strlen(fname));
|
sl = m_alloc_clear( sizeof *sl + strlen(fname));
|
||||||
strcpy(sl->d, fname);
|
strcpy(sl->d, fname);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if( (rc = sign_file( sl, detached_sig, locusr, 0, NULL, NULL)) )
|
if( (rc = sign_file( sl, detached_sig, locusr, 0, NULL, NULL)) )
|
||||||
log_error("sign_file: %s\n", g10_errstr(rc) );
|
log_error("signing failed: %s\n", g10_errstr(rc) );
|
||||||
free_strlist(sl);
|
free_strlist(sl);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case aSignEncr: /* sign and encrypt the given file */
|
case aSignEncr: /* sign and encrypt the given file */
|
||||||
if( argc > 1 )
|
if( argc > 1 )
|
||||||
usage(1);
|
wrong_args(_("--sign --encrypt [filename]"));
|
||||||
if( argc ) {
|
if( argc ) {
|
||||||
sl = m_alloc_clear( sizeof *sl + strlen(fname));
|
sl = m_alloc_clear( sizeof *sl + strlen(fname));
|
||||||
strcpy(sl->d, fname);
|
strcpy(sl->d, fname);
|
||||||
@ -503,33 +505,40 @@ main( int argc, char **argv )
|
|||||||
else
|
else
|
||||||
sl = NULL;
|
sl = NULL;
|
||||||
if( (rc = sign_file(sl, detached_sig, locusr, 1, remusr, NULL)) )
|
if( (rc = sign_file(sl, detached_sig, locusr, 1, remusr, NULL)) )
|
||||||
log_error("sign_file('%s'): %s\n", fname_print, g10_errstr(rc) );
|
log_error("%s: sign+encrypt failed: %s\n", fname_print, g10_errstr(rc) );
|
||||||
free_strlist(sl);
|
free_strlist(sl);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case aClearsign: /* make a clearsig */
|
||||||
|
if( argc > 1 )
|
||||||
|
wrong_args(_("--clearsign [filename]"));
|
||||||
|
if( (rc = clearsign_file(fname, locusr, NULL)) )
|
||||||
|
log_error("%s: clearsign failed: %s\n", fname_print, g10_errstr(rc) );
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
case aSignKey: /* sign the key given as argument */
|
case aSignKey: /* sign the key given as argument */
|
||||||
if( argc != 1 )
|
if( argc != 1 )
|
||||||
usage(1);
|
wrong_args(_("--sign-key username"));
|
||||||
/* note: fname is the user id! */
|
/* note: fname is the user id! */
|
||||||
if( (rc = sign_key(fname, locusr)) )
|
if( (rc = sign_key(fname, locusr)) )
|
||||||
log_error("sign_key('%s'): %s\n", fname_print, g10_errstr(rc) );
|
log_error("%s: sign key failed: %s\n", fname_print, g10_errstr(rc) );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case aEditSig: /* Edit a key signature */
|
case aEditSig: /* Edit a key signature */
|
||||||
if( argc != 1 )
|
if( argc != 1 )
|
||||||
usage(1);
|
wrong_args(_("--edit-sig username"));
|
||||||
/* note: fname is the user id! */
|
/* note: fname is the user id! */
|
||||||
if( (rc = edit_keysigs(fname)) )
|
if( (rc = edit_keysigs(fname)) )
|
||||||
log_error("edit_keysig('%s'): %s\n", fname_print, g10_errstr(rc) );
|
log_error("%s: edit signature failed: %s\n", fname_print, g10_errstr(rc) );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case aChangePass: /* Chnage the passphrase */
|
case aChangePass: /* Chnage the passphrase */
|
||||||
if( argc > 1 ) /* no arg: use default, 1 arg use this one */
|
if( argc > 1 ) /* no arg: use default, 1 arg use this one */
|
||||||
usage(1);
|
wrong_args(_("--change-passphrase [username]"));
|
||||||
/* note: fname is the user id! */
|
/* note: fname is the user id! */
|
||||||
if( (rc = change_passphrase(fname)) )
|
if( (rc = change_passphrase(fname)) )
|
||||||
log_error("change_passphrase('%s'): %s\n", fname_print,
|
log_error("%s: change passphrase failed: %s\n", fname_print,
|
||||||
g10_errstr(rc) );
|
g10_errstr(rc) );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -562,18 +571,18 @@ main( int argc, char **argv )
|
|||||||
iobuf_close(a);
|
iobuf_close(a);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
usage(1);
|
wrong_args(_("-k[v][v][v][c] [keyring]"));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case aKeygen: /* generate a key (interactive) */
|
case aKeygen: /* generate a key (interactive) */
|
||||||
if( argc )
|
if( argc )
|
||||||
usage(1);
|
wrong_args(_("--gen-key"));
|
||||||
generate_keypair();
|
generate_keypair();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case aImport:
|
case aImport:
|
||||||
if( !argc )
|
if( !argc )
|
||||||
usage(1);
|
wrong_args(_("nyi"));
|
||||||
for( ; argc; argc--, argv++ ) {
|
for( ; argc; argc--, argv++ ) {
|
||||||
rc = import_pubkeys( *argv );
|
rc = import_pubkeys( *argv );
|
||||||
if( rc )
|
if( rc )
|
||||||
@ -594,7 +603,7 @@ main( int argc, char **argv )
|
|||||||
opt.list_packets=1;
|
opt.list_packets=1;
|
||||||
default:
|
default:
|
||||||
if( argc > 1 )
|
if( argc > 1 )
|
||||||
usage(1);
|
wrong_args(_("[filename]"));
|
||||||
if( !(a = iobuf_open(fname)) )
|
if( !(a = iobuf_open(fname)) )
|
||||||
log_fatal(_("can't open '%s'\n"), fname_print);
|
log_fatal(_("can't open '%s'\n"), fname_print);
|
||||||
if( !opt.no_armor ) {
|
if( !opt.no_armor ) {
|
||||||
|
@ -50,6 +50,7 @@ int encrypt_filter( void *opaque, int control,
|
|||||||
/*-- sign.c --*/
|
/*-- sign.c --*/
|
||||||
int sign_file( STRLIST filenames, int detached, STRLIST locusr,
|
int sign_file( STRLIST filenames, int detached, STRLIST locusr,
|
||||||
int encrypt, STRLIST remusr, const char *outfile );
|
int encrypt, STRLIST remusr, const char *outfile );
|
||||||
|
int clearsign_file( const char *fname, STRLIST locusr, const char *outfile );
|
||||||
int sign_key( const char *username, STRLIST locusr );
|
int sign_key( const char *username, STRLIST locusr );
|
||||||
int edit_keysigs( const char *username );
|
int edit_keysigs( const char *username );
|
||||||
int change_passphrase( const char *username );
|
int change_passphrase( const char *username );
|
||||||
|
@ -274,6 +274,7 @@ 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);
|
||||||
|
md_enable( c->mfx.md, DIGEST_ALGO_MD5 );
|
||||||
rc = handle_plaintext( pt, &c->mfx );
|
rc = handle_plaintext( pt, &c->mfx );
|
||||||
if( rc )
|
if( rc )
|
||||||
log_error( "handle plaintext failed: %s\n", g10_errstr(rc));
|
log_error( "handle plaintext failed: %s\n", g10_errstr(rc));
|
||||||
@ -325,6 +326,11 @@ do_check_sig( CTX c, KBNODE node )
|
|||||||
if( sig->sig_class == 0x00 ) {
|
if( sig->sig_class == 0x00 ) {
|
||||||
md = md_copy( c->mfx.md );
|
md = md_copy( c->mfx.md );
|
||||||
}
|
}
|
||||||
|
else if( sig->sig_class == 0x01 ) {
|
||||||
|
/* how do we know that we have to hash the (already hashed) text
|
||||||
|
* in canonical mode ??? (calculating both modes???) */
|
||||||
|
md = md_copy( c->mfx.md );
|
||||||
|
}
|
||||||
else if( (sig->sig_class&~3) == 0x10 ) { /* classes 0x10 .. 0x13 */
|
else if( (sig->sig_class&~3) == 0x10 ) { /* classes 0x10 .. 0x13 */
|
||||||
if( c->cert->pkt->pkttype == PKT_PUBLIC_CERT ) {
|
if( c->cert->pkt->pkttype == PKT_PUBLIC_CERT ) {
|
||||||
KBNODE n1 = find_kbparent( c->cert, node );
|
KBNODE n1 = find_kbparent( c->cert, node );
|
||||||
|
@ -829,6 +829,8 @@ parse_plaintext( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *pkt )
|
|||||||
pktlen = 0;
|
pktlen = 0;
|
||||||
|
|
||||||
if( list_mode ) {
|
if( list_mode ) {
|
||||||
|
/* a value if 'c' is used by armor to indicate a faked packet
|
||||||
|
* it should be considered as 't' */
|
||||||
printf(":literal data packet:\n"
|
printf(":literal data packet:\n"
|
||||||
"\tmode %c, created %lu, name=\"",
|
"\tmode %c, created %lu, name=\"",
|
||||||
mode >= ' ' && mode <'z'? mode : '?',
|
mode >= ' ' && mode <'z'? mode : '?',
|
||||||
|
139
g10/sign.c
139
g10/sign.c
@ -301,6 +301,145 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr,
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
write_dash_escaped( IOBUF inp, IOBUF out, MD_HANDLE md )
|
||||||
|
{
|
||||||
|
int c;
|
||||||
|
int lastlf = 1;
|
||||||
|
|
||||||
|
while( (c = iobuf_get(inp)) != -1 ) {
|
||||||
|
/* Note: We don't escape "From " because the MUA should cope with it */
|
||||||
|
if( lastlf && c == '-' ) {
|
||||||
|
iobuf_put( out, c );
|
||||||
|
iobuf_put( out, ' ' );
|
||||||
|
}
|
||||||
|
|
||||||
|
md_putc(md, c );
|
||||||
|
iobuf_put( out, c );
|
||||||
|
lastlf = c == '\n';
|
||||||
|
}
|
||||||
|
return 0; /* fixme: add error handling */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/****************
|
||||||
|
* make a clear signature. note that opt.armor is not needed
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
clearsign_file( const char *fname, STRLIST locusr, const char *outfile )
|
||||||
|
{
|
||||||
|
armor_filter_context_t afx;
|
||||||
|
compress_filter_context_t zfx;
|
||||||
|
text_filter_context_t tfx;
|
||||||
|
MD_HANDLE textmd;
|
||||||
|
IOBUF inp = NULL, out = NULL;
|
||||||
|
PACKET pkt;
|
||||||
|
int rc = 0;
|
||||||
|
SKC_LIST skc_list = NULL;
|
||||||
|
SKC_LIST skc_rover = NULL;
|
||||||
|
|
||||||
|
memset( &afx, 0, sizeof afx);
|
||||||
|
memset( &zfx, 0, sizeof zfx);
|
||||||
|
memset( &tfx, 0, sizeof tfx);
|
||||||
|
init_packet( &pkt );
|
||||||
|
|
||||||
|
if( (rc=build_skc_list( locusr, &skc_list, 1 )) )
|
||||||
|
goto leave;
|
||||||
|
|
||||||
|
/* prepare iobufs */
|
||||||
|
if( !(inp = iobuf_open(fname)) ) {
|
||||||
|
log_error("can't open %s: %s\n", fname? fname: "[stdin]",
|
||||||
|
strerror(errno) );
|
||||||
|
rc = G10ERR_OPEN_FILE;
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( outfile ) {
|
||||||
|
if( !(out = iobuf_create( outfile )) ) {
|
||||||
|
log_error("can't create %s: %s\n", outfile, strerror(errno) );
|
||||||
|
rc = G10ERR_CREATE_FILE;
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
else if( opt.verbose )
|
||||||
|
log_info("writing to '%s'\n", outfile );
|
||||||
|
}
|
||||||
|
else if( !(out = open_outfile( fname, 1 )) ) {
|
||||||
|
rc = G10ERR_CREATE_FILE;
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
|
iobuf_writestr(out, "-----BEGIN PGP SIGNED MESSAGE-----\n\n" );
|
||||||
|
|
||||||
|
textmd = md_open(DIGEST_ALGO_RMD160, 0);
|
||||||
|
iobuf_push_filter( inp, text_filter, &tfx );
|
||||||
|
rc = write_dash_escaped( inp, out, textmd );
|
||||||
|
if( rc )
|
||||||
|
goto leave;
|
||||||
|
|
||||||
|
iobuf_writestr(out, "\n\n" );
|
||||||
|
afx.what = 2;
|
||||||
|
iobuf_push_filter( out, armor_filter, &afx );
|
||||||
|
|
||||||
|
/* loop over the secret certificates */
|
||||||
|
for( skc_rover = skc_list; skc_rover; skc_rover = skc_rover->next ) {
|
||||||
|
PKT_secret_cert *skc;
|
||||||
|
PKT_signature *sig;
|
||||||
|
MD_HANDLE md;
|
||||||
|
|
||||||
|
skc = skc_rover->skc;
|
||||||
|
|
||||||
|
/* build the signature packet */
|
||||||
|
sig = m_alloc_clear( sizeof *sig );
|
||||||
|
sig->pubkey_algo = skc->pubkey_algo;
|
||||||
|
sig->timestamp = make_timestamp();
|
||||||
|
sig->sig_class = 0x01;
|
||||||
|
|
||||||
|
md = md_copy( textmd );
|
||||||
|
md_putc( md, sig->sig_class );
|
||||||
|
{ u32 a = sig->timestamp;
|
||||||
|
md_putc( md, (a >> 24) & 0xff );
|
||||||
|
md_putc( md, (a >> 16) & 0xff );
|
||||||
|
md_putc( md, (a >> 8) & 0xff );
|
||||||
|
md_putc( md, a & 0xff );
|
||||||
|
}
|
||||||
|
md_final( md );
|
||||||
|
|
||||||
|
if( sig->pubkey_algo == PUBKEY_ALGO_ELGAMAL )
|
||||||
|
g10_elg_sign( skc, sig, md, DIGEST_ALGO_RMD160 );
|
||||||
|
else if( sig->pubkey_algo == PUBKEY_ALGO_RSA )
|
||||||
|
g10_rsa_sign( skc, sig, md, DIGEST_ALGO_RMD160 );
|
||||||
|
else
|
||||||
|
BUG();
|
||||||
|
|
||||||
|
md_close( md );
|
||||||
|
|
||||||
|
/* and write it */
|
||||||
|
init_packet(&pkt);
|
||||||
|
pkt.pkttype = PKT_SIGNATURE;
|
||||||
|
pkt.pkt.signature = sig;
|
||||||
|
rc = build_packet( out, &pkt );
|
||||||
|
free_packet( &pkt );
|
||||||
|
if( rc ) {
|
||||||
|
log_error("build signature packet failed: %s\n", g10_errstr(rc) );
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
leave:
|
||||||
|
if( rc )
|
||||||
|
iobuf_cancel(out);
|
||||||
|
else
|
||||||
|
iobuf_close(out);
|
||||||
|
iobuf_close(inp);
|
||||||
|
md_close( textmd );
|
||||||
|
release_skc_list( skc_list );
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
show_fingerprint( PKT_public_cert *pkc )
|
show_fingerprint( PKT_public_cert *pkc )
|
||||||
{
|
{
|
||||||
|
@ -49,6 +49,7 @@ write_status( int no )
|
|||||||
case STATUS_GOODSIG: s = "GOODSIG\n"; break;
|
case STATUS_GOODSIG: s = "GOODSIG\n"; break;
|
||||||
case STATUS_BADSIG : s = "BADSIG\n"; break;
|
case STATUS_BADSIG : s = "BADSIG\n"; break;
|
||||||
case STATUS_ERRSIG : s = "ERRSIG\n"; break;
|
case STATUS_ERRSIG : s = "ERRSIG\n"; break;
|
||||||
|
case STATUS_BADARMOR : s = "BADARMOR\n"; break;
|
||||||
default: s = "?\n"; break;
|
default: s = "?\n"; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
#define STATUS_ERRSIG 6
|
#define STATUS_ERRSIG 6
|
||||||
|
|
||||||
|
|
||||||
|
#define STATUS_BADARMOR 7
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
130
g10/textfilter.c
130
g10/textfilter.c
@ -32,6 +32,69 @@
|
|||||||
#include "filter.h"
|
#include "filter.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
read_line( byte *buf, size_t *r_buflen, IOBUF a )
|
||||||
|
{
|
||||||
|
int c;
|
||||||
|
int rc = 0;
|
||||||
|
byte *p;
|
||||||
|
size_t buflen;
|
||||||
|
int no_lf=0;
|
||||||
|
size_t n;
|
||||||
|
|
||||||
|
buflen = *r_buflen;
|
||||||
|
assert(buflen >= 20 );
|
||||||
|
buflen -= 3; /* leave some room for CR,LF and one extra */
|
||||||
|
|
||||||
|
for(c=0, n=0; n < buflen && (c=iobuf_get2(a)) != -1 && c != '\n'; )
|
||||||
|
buf[n++] = c;
|
||||||
|
buf[n] = 0;
|
||||||
|
if( c == -1 )
|
||||||
|
rc = -1;
|
||||||
|
else if( c != '\n' ) {
|
||||||
|
IOBUF b = iobuf_temp();
|
||||||
|
while( (c=iobuf_get2(a)) != -1 && c != '\n' ) {
|
||||||
|
iobuf_put(b,c);
|
||||||
|
if( c != ' ' && c != '\t' && c != '\r' )
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if( c == '\n' ) { /* okay we can skip the rest of the line */
|
||||||
|
iobuf_close(b);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
iobuf_unget_and_close_temp(a,b);
|
||||||
|
no_lf = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !no_lf ) {
|
||||||
|
/* append CR,LF after removing trailing wspaces */
|
||||||
|
for(p=buf+n-1; n; n--, p-- ) {
|
||||||
|
assert( *p != '\n' );
|
||||||
|
if( *p != ' ' && *p != '\t' && *p != '\r' ) {
|
||||||
|
p[1] = '\r';
|
||||||
|
p[2] = '\n';
|
||||||
|
n += 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if( !n ) {
|
||||||
|
buf[0] = '\r';
|
||||||
|
buf[1] = '\n';
|
||||||
|
n = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
*r_buflen = n;
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/****************
|
/****************
|
||||||
* The filter is used to make canonical text: Lines are terminated by
|
* The filter is used to make canonical text: Lines are terminated by
|
||||||
* CR, LF, trailing white spaces are removed.
|
* CR, LF, trailing white spaces are removed.
|
||||||
@ -42,60 +105,31 @@ text_filter( void *opaque, int control,
|
|||||||
{
|
{
|
||||||
size_t size = *ret_len;
|
size_t size = *ret_len;
|
||||||
text_filter_context_t *tfx = opaque;
|
text_filter_context_t *tfx = opaque;
|
||||||
int i, c, rc=0;
|
int rc=0;
|
||||||
byte *p;
|
size_t len, n, nn;
|
||||||
|
|
||||||
if( control == IOBUFCTRL_UNDERFLOW ) {
|
if( control == IOBUFCTRL_UNDERFLOW ) {
|
||||||
for(i=0; i < size; i++ ) {
|
assert( size > 30 );
|
||||||
if( !tfx->linelen && !tfx->eof ) { /* read a complete line */
|
len = 0;
|
||||||
for(;;) {
|
while( !rc && len < size ) {
|
||||||
if( (c = iobuf_get(a)) == -1 ) {
|
if( tfx->idx < tfx->len ) { /* flush the last buffer */
|
||||||
tfx->eof=1;
|
n = tfx->len;
|
||||||
break;
|
for(nn=tfx->idx; len < size && nn < n ; nn++ )
|
||||||
|
buf[len++] = tfx->buf[nn];
|
||||||
|
tfx->idx = nn;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
if( c == '\n' )
|
if( tfx->eof ) {
|
||||||
break;
|
|
||||||
if( tfx->linelen >= tfx->linesize ) {
|
|
||||||
tfx->linesize += 500;
|
|
||||||
tfx->line = m_realloc( tfx->line, tfx->linesize );
|
|
||||||
}
|
|
||||||
tfx->line[tfx->linelen++] = c;
|
|
||||||
}
|
|
||||||
/* remove trailing white spaces */
|
|
||||||
p = tfx->line + tfx->linelen - 1;
|
|
||||||
for( ; p >= tfx->line; p--, tfx->linelen-- ) {
|
|
||||||
if( *p != ' ' && *p == '\t' && *p != '\r' )
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if( tfx->linelen+2 >= tfx->linesize ) {
|
|
||||||
tfx->linesize += 10;
|
|
||||||
tfx->line = m_realloc( tfx->line, tfx->linesize );
|
|
||||||
}
|
|
||||||
tfx->line[tfx->linelen++] = '\r';
|
|
||||||
tfx->line[tfx->linelen++] = '\n';
|
|
||||||
tfx->pos=0;
|
|
||||||
}
|
|
||||||
if( tfx->pos < tfx->linelen )
|
|
||||||
buf[i] = tfx->line[tfx->pos++];
|
|
||||||
else if( tfx->eof )
|
|
||||||
break;
|
|
||||||
else
|
|
||||||
tfx->linelen = 0;
|
|
||||||
}
|
|
||||||
if( !i )
|
|
||||||
rc = -1;
|
rc = -1;
|
||||||
*ret_len = i;
|
continue;
|
||||||
}
|
}
|
||||||
else if( control == IOBUFCTRL_INIT ) {
|
n = DIM(tfx->buf);
|
||||||
tfx->linesize = 500;
|
tfx->idx = 0;
|
||||||
tfx->line = m_alloc(tfx->linesize);
|
if( read_line( tfx->buf, &n, a ) == -1 )
|
||||||
tfx->linelen = 0;
|
tfx->eof = 1;
|
||||||
tfx->pos = 0;
|
tfx->len = n;
|
||||||
tfx->eof = 0;
|
|
||||||
}
|
}
|
||||||
else if( control == IOBUFCTRL_FREE ) {
|
*ret_len = len;
|
||||||
m_free( tfx->line );
|
|
||||||
tfx->line = NULL;
|
|
||||||
}
|
}
|
||||||
else if( control == IOBUFCTRL_DESC )
|
else if( control == IOBUFCTRL_DESC )
|
||||||
*(char**)buf = "text_filter";
|
*(char**)buf = "text_filter";
|
||||||
|
@ -56,6 +56,12 @@ struct iobuf_struct {
|
|||||||
const char *desc;
|
const char *desc;
|
||||||
void *opaque; /* can be used to hold any information */
|
void *opaque; /* can be used to hold any information */
|
||||||
/* this value is copied to all instances */
|
/* this value is copied to all instances */
|
||||||
|
struct {
|
||||||
|
size_t size; /* allocated size */
|
||||||
|
size_t start; /* number of invalid bytes at the begin of the buffer */
|
||||||
|
size_t len; /* currently filled to this size */
|
||||||
|
byte *buf;
|
||||||
|
} unget;
|
||||||
};
|
};
|
||||||
|
|
||||||
int iobuf_debug_mode;
|
int iobuf_debug_mode;
|
||||||
@ -88,6 +94,7 @@ int iobuf_writestr(IOBUF a, const char *buf );
|
|||||||
|
|
||||||
int iobuf_write_temp( IOBUF a, IOBUF temp );
|
int iobuf_write_temp( IOBUF a, IOBUF temp );
|
||||||
size_t iobuf_temp_to_buffer( IOBUF a, byte *buffer, size_t buflen );
|
size_t iobuf_temp_to_buffer( IOBUF a, byte *buffer, size_t buflen );
|
||||||
|
void iobuf_unget_and_close_temp( IOBUF a, IOBUF temp );
|
||||||
|
|
||||||
u32 iobuf_get_filelength( IOBUF a );
|
u32 iobuf_get_filelength( IOBUF a );
|
||||||
const char *iobuf_get_fname( IOBUF a );
|
const char *iobuf_get_fname( IOBUF a );
|
||||||
@ -106,6 +113,10 @@ int iobuf_in_block_mode( IOBUF a );
|
|||||||
iobuf_readbyte((a)) : ( (a)->nbytes++, (a)->d.buf[(a)->d.start++] ) )
|
iobuf_readbyte((a)) : ( (a)->nbytes++, (a)->d.buf[(a)->d.start++] ) )
|
||||||
#define iobuf_get_noeof(a) (iobuf_get((a))&0xff)
|
#define iobuf_get_noeof(a) (iobuf_get((a))&0xff)
|
||||||
|
|
||||||
|
/* use this if you have ungetted stuff */
|
||||||
|
#define iobuf_get2(a) \
|
||||||
|
( ( (a)->unget.buf || (a)->nlimit || (a)->d.start >= (a)->d.len )? \
|
||||||
|
iobuf_readbyte((a)) : ( (a)->nbytes++, (a)->d.buf[(a)->d.start++] ) )
|
||||||
|
|
||||||
/* write a byte to the iobuf and return true on write error
|
/* write a byte to the iobuf and return true on write error
|
||||||
* This macro does only write the low order byte
|
* This macro does only write the low order byte
|
||||||
|
30
util/iobuf.c
30
util/iobuf.c
@ -700,6 +700,15 @@ iobuf_readbyte(IOBUF a)
|
|||||||
{
|
{
|
||||||
int c;
|
int c;
|
||||||
|
|
||||||
|
/* nlimit does not work together with unget */
|
||||||
|
/* nbytes is also not valid! */
|
||||||
|
if( a->unget.buf ) {
|
||||||
|
if( a->unget.start < a->unget.len )
|
||||||
|
return a->unget.buf[a->unget.start++];
|
||||||
|
m_free(a->unget.buf);
|
||||||
|
a->unget.buf = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if( a->nlimit && a->nbytes >= a->nlimit )
|
if( a->nlimit && a->nbytes >= a->nlimit )
|
||||||
return -1; /* forced EOF */
|
return -1; /* forced EOF */
|
||||||
|
|
||||||
@ -770,6 +779,27 @@ iobuf_temp_to_buffer( IOBUF a, byte *buffer, size_t buflen )
|
|||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/****************
|
||||||
|
* unget the contents of the temp io stream to A and close temp
|
||||||
|
* Could be optimized!!
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
iobuf_unget_and_close_temp( IOBUF a, IOBUF temp )
|
||||||
|
{
|
||||||
|
if( a->unget.buf ) {
|
||||||
|
if( a->unget.start < a->unget.len )
|
||||||
|
log_fatal("cannot do any more ungets on this buffer\n");
|
||||||
|
/* not yet cleaned up; do it now */
|
||||||
|
m_free(a->unget.buf);
|
||||||
|
a->unget.buf = NULL;
|
||||||
|
}
|
||||||
|
a->unget.size = temp->d.len;
|
||||||
|
a->unget.buf = m_alloc( a->unget.size );
|
||||||
|
a->unget.len = temp->d.len;
|
||||||
|
memcpy( a->unget.buf, temp->d.buf, a->unget.len );
|
||||||
|
iobuf_close(temp);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/****************
|
/****************
|
||||||
* Set a limit, how much bytes may be read from the input stream A.
|
* Set a limit, how much bytes may be read from the input stream A.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user