From 7debff3867c0c087ccae465517aa26e475266427 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Wed, 20 Jan 1999 18:10:35 +0000 Subject: [PATCH] See ChangeLog: Wed Jan 20 18:59:49 CET 1999 Werner Koch --- NEWS | 2 + THANKS | 1 + cipher/ChangeLog | 4 + cipher/rndunix.c | 5 +- g10/ChangeLog | 5 ++ g10/armor.c | 2 - g10/filter.h | 6 ++ g10/mainproc.c | 2 +- g10/plaintext.c | 48 +++++++++++- g10/sign.c | 27 +++++-- g10/textfilter.c | 186 +++++++++++++++++++++++++++++++++++++---------- include/iobuf.h | 1 + include/util.h | 1 + util/ChangeLog | 4 + util/http.c | 90 ++++++++++++++++++++--- 15 files changed, 321 insertions(+), 63 deletions(-) diff --git a/NEWS b/NEWS index eec5c8f86..163c967aa 100644 --- a/NEWS +++ b/NEWS @@ -5,6 +5,8 @@ * Upgraded to zlib 1.1.3 + * More cleanup on the cleartext signatures. + Noteworthy changes in version 0.9.1 ----------------------------------- diff --git a/THANKS b/THANKS index fb9835ff3..e880ad224 100644 --- a/THANKS +++ b/THANKS @@ -72,6 +72,7 @@ SL Baur steve@xemacs.org Stefan Karrmann S.Karrmann@gmx.net Steffen Ullrich ccrlphr@xensei.com Steffen Zahn zahn@berlin.snafu.de +Steven Bakker steven@icoe.att.com Susanne Schultz schultz@hsp.de Thiago Jung Bauermann jungmann@usa.net Thomas Roessler roessler@guug.de diff --git a/cipher/ChangeLog b/cipher/ChangeLog index c46ca5d86..273b6fdee 100644 --- a/cipher/ChangeLog +++ b/cipher/ChangeLog @@ -1,3 +1,7 @@ +Wed Jan 20 18:59:49 CET 1999 Werner Koch + + * rndunix.c (gather_random): Fix to avoid infinite loop. + Sun Jan 17 11:04:33 CET 1999 Werner Koch * des.c (is_weak_key): Replace system memcmp due to bugs diff --git a/cipher/rndunix.c b/cipher/rndunix.c index f0b631975..716b02672 100644 --- a/cipher/rndunix.c +++ b/cipher/rndunix.c @@ -709,6 +709,7 @@ gather_random( void (*add)(const void*, size_t, int), int requester, /* now read from the gatherer */ while( length ) { int goodness; + ulong subtract; if( read_a_msg( pipedes[0], &msg ) ) { g10_log_error("reading from gatherer pipe failed: %s\n", @@ -742,7 +743,9 @@ gather_random( void (*add)(const void*, size_t, int), int requester, (*add)( msg.data, n, requester ); /* this is the trick how e cope with the goodness */ - length -= (ulong)n * goodness / 100; + subtract = (ulong)n * goodness / 100; + /* subtract at least 1 byte to avoid infinite loops */ + length -= subtract ? subtract : 1; } return 0; diff --git a/g10/ChangeLog b/g10/ChangeLog index c9137ed01..e3ba21f58 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,8 @@ +Wed Jan 20 18:59:49 CET 1999 Werner Koch + + * textfilter.c: Mostly rewritten + * plaintext.c (handle_plaintext): Use now text_filter semantics. + Tue Jan 19 19:34:58 CET 1999 Werner Koch * export.c (export_pubkeys_stream): New. diff --git a/g10/armor.c b/g10/armor.c index 491cab4fa..195fc2cb9 100644 --- a/g10/armor.c +++ b/g10/armor.c @@ -518,8 +518,6 @@ fake_packet( armor_filter_context_t *afx, IOBUF a, putc('\n', stderr); } lastline = 1; - if( len >= 2 && !afx->not_dash_escaped ) - len -= 2; /* remove the last CR,LF */ rc = -1; } } diff --git a/g10/filter.h b/g10/filter.h index df436be74..bfd1e7a91 100644 --- a/g10/filter.h +++ b/g10/filter.h @@ -86,6 +86,12 @@ typedef struct { unsigned buffer_len; /* used length of the buffer */ unsigned buffer_pos; /* read position */ int truncated; /* number of truncated lines */ + int clearsign; + int not_dash_escaped; + int escape_from; + MD_HANDLE md; + int pending_lf; + int pending_esc; } text_filter_context_t; diff --git a/g10/mainproc.c b/g10/mainproc.c index 2e5575dd8..51547b886 100644 --- a/g10/mainproc.c +++ b/g10/mainproc.c @@ -279,7 +279,7 @@ proc_plaintext( CTX c, PACKET *pkt ) md_enable( c->mfx.md, DIGEST_ALGO_SHA1 ); md_enable( c->mfx.md, DIGEST_ALGO_MD5 ); } - /*md_start_debug( c->mfx.md, "verify" );*/ + md_start_debug( c->mfx.md, "verify" ); rc = handle_plaintext( pt, &c->mfx, c->sigs_only, clearsig ); if( rc == G10ERR_CREATE_FILE && !c->sigs_only) { /* can't write output but we hash it anyway to diff --git a/g10/plaintext.c b/g10/plaintext.c index 0dc246939..98c4314ea 100644 --- a/g10/plaintext.c +++ b/g10/plaintext.c @@ -89,6 +89,7 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx, } if( pt->len ) { + assert( !clearsig ); for( ; pt->len; pt->len-- ) { if( (c = iobuf_get(pt->buf)) == -1 ) { log_error("Problem reading source (%u bytes remaining)\n", @@ -98,7 +99,7 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx, } if( mfx->md ) md_putc(mfx->md, c ); - if( convert && !clearsig && c == '\r' ) + if( convert && c == '\r' ) continue; /* fixme: this hack might be too simple */ if( fp ) { if( putc( c, fp ) == EOF ) { @@ -110,11 +111,11 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx, } } } - else { + else if( !clearsig ) { while( (c = iobuf_get(pt->buf)) != -1 ) { if( mfx->md ) md_putc(mfx->md, c ); - if( convert && !clearsig && c == '\r' ) + if( convert && c == '\r' ) continue; /* fixme: this hack might be too simple */ if( fp ) { if( putc( c, fp ) == EOF ) { @@ -127,6 +128,47 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx, } pt->buf = NULL; } + else { /* clear text signature - don't hash the last cr,lf */ + int state = 0; + + while( (c = iobuf_get(pt->buf)) != -1 ) { + if( fp ) { + if( putc( c, fp ) == EOF ) { + log_error("Error writing to `%s': %s\n", + fname, strerror(errno) ); + rc = G10ERR_WRITE_FILE; + goto leave; + } + } + if( !mfx->md ) + continue; + if( state == 2 ) { + md_putc(mfx->md, '\r' ); + md_putc(mfx->md, '\n' ); + state = 0; + } + if( !state ) { + if( c == '\r' ) + state = 1; + else + md_putc(mfx->md, c ); + } + else if( state == 1 ) { + if( c == '\n' ) + state = 2; + else { + md_putc(mfx->md, '\r' ); + if( c == '\r' ) + state = 1; + else { + state = 0; + md_putc(mfx->md, c ); + } + } + } + } + pt->buf = NULL; + } if( fp && fp != stdout && fclose(fp) ) { log_error("Error closing `%s': %s\n", fname, strerror(errno) ); diff --git a/g10/sign.c b/g10/sign.c index e8582f43d..fe13461d6 100644 --- a/g10/sign.c +++ b/g10/sign.c @@ -455,7 +455,7 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr, } - +#if 0 /**************** * Note: We do not calculate the hash over the last CR,LF */ @@ -554,7 +554,7 @@ write_dash_escaped( IOBUF inp, IOBUF out, MD_HANDLE md ) return 0; /* fixme: add error handling */ } - +#endif /**************** * make a clear signature. note that opt.armor is not needed @@ -572,6 +572,7 @@ clearsign_file( const char *fname, STRLIST locusr, const char *outfile ) SK_LIST sk_rover = NULL; int old_style = opt.rfc1991; int only_md5 = 0; + int c; memset( &afx, 0, sizeof afx); memset( &tfx, 0, sizeof tfx); @@ -645,13 +646,23 @@ clearsign_file( const char *fname, STRLIST locusr, const char *outfile ) PKT_secret_key *sk = sk_rover->sk; md_enable(textmd, hash_for(sk->pubkey_algo)); } - /*md_start_debug( textmd, "create" );*/ - if( !opt.not_dash_escaped ) - iobuf_push_filter( inp, text_filter, &tfx ); - rc = write_dash_escaped( inp, out, textmd ); - if( rc ) - goto leave; + md_start_debug( textmd, "sign" ); + tfx.clearsign = 1; + tfx.not_dash_escaped = opt.not_dash_escaped; + tfx.escape_from = opt.escape_from; + tfx.md = textmd; + iobuf_push_filter( inp, text_filter, &tfx ); + /* read input and write it to the output. The textfilter handles + * the calculation of the hash and the dash escaping */ + while( (c=iobuf_get(inp)) != -1 ) { + if( iobuf_put(out, c) == -1 ) { + rc = G10ERR_WRITE_FILE; + goto leave; + } + } + /* fixme: check for read errors */ + /* now write the armor */ afx.what = 2; iobuf_push_filter( out, armor_filter, &afx ); diff --git a/g10/textfilter.c b/g10/textfilter.c index 9959c9335..07630d050 100644 --- a/g10/textfilter.c +++ b/g10/textfilter.c @@ -1,5 +1,5 @@ /* textfilter.c - * Copyright (C) 1998 Free Software Foundation, Inc. + * Copyright (C) 1998,1999 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -33,7 +33,147 @@ #include "i18n.h" -#define MAX_LINELEN 20000 +#define MAX_LINELEN 19995 /* a little bit smaller than in armor.c */ + /* to make sure that a warning is displayed while */ + /* creating a message */ + +unsigned +len_without_trailing_ws( byte *line, unsigned len ) +{ + byte *p, *mark; + unsigned n; + + for(mark=NULL, p=line, n=0; n < len; n++, p++ ) { + if( strchr(" \t\r\n", *p ) ) { + if( !mark ) + mark = p; + } + else + mark = NULL; + } + + return mark? (mark - line) : len; +} + + + + +static int +standard( text_filter_context_t *tfx, IOBUF a, + byte *buf, size_t size, size_t *ret_len) +{ + int rc=0; + size_t len = 0; + unsigned maxlen; + + assert( size > 10 ); + size -= 2; /* reserve 2 bytes to append CR,LF */ + while( !rc && len < size ) { + int lf_seen; + + while( len < size && tfx->buffer_pos < tfx->buffer_len ) + buf[len++] = tfx->buffer[tfx->buffer_pos++]; + if( len >= size ) + continue; + + /* read the next line */ + maxlen = MAX_LINELEN; + tfx->buffer_pos = 0; + tfx->buffer_len = iobuf_read_line( a, &tfx->buffer, + &tfx->buffer_size, &maxlen ); + if( !maxlen ) + tfx->truncated++; + if( !tfx->buffer_len ) { + if( !len ) + rc = -1; /* eof */ + break; + } + lf_seen = tfx->buffer[tfx->buffer_len-1] == '\n'; + tfx->buffer_len = trim_trailing_ws( tfx->buffer, tfx->buffer_len ); + if( lf_seen ) { + tfx->buffer[tfx->buffer_len++] = '\r'; + tfx->buffer[tfx->buffer_len++] = '\n'; + } + } + *ret_len = len; + return rc; +} + +static int +clearsign( text_filter_context_t *tfx, IOBUF a, + byte *buf, size_t size, size_t *ret_len) +{ + int rc=0; + size_t len = 0; + unsigned maxlen; + + assert( size > 2 ); + size -= 3; /* reserve for dash escaping and extra LF */ + while( !rc && len < size ) { + unsigned n; + byte *p; + + if( tfx->pending_esc ) { + buf[len++] = '-'; + buf[len++] = ' '; + tfx->pending_esc = 0; + } + while( len < size && tfx->buffer_pos < tfx->buffer_len ) + buf[len++] = tfx->buffer[tfx->buffer_pos++]; + if( len >= size ) + continue; + + /* read the next line */ + maxlen = MAX_LINELEN; + tfx->buffer_pos = 0; + tfx->buffer_len = iobuf_read_line( a, &tfx->buffer, + &tfx->buffer_size, &maxlen ); + p = tfx->buffer; + n = tfx->buffer_len; + if( !maxlen ) + tfx->truncated++; + if( !n ) { /* readline has returned eof */ + /* don't hash a pending lf here because the last one is + * not part of the signed material. OpenPGP does not + * hash the last LF because it may have to add an + * extra one in case that the original material + * does not end with one. The clear signed text + * must end in a LF, so that the following armor + * line can be detected by the parser + */ + if( !tfx->pending_lf ) { + /* make sure that the file ends with a LF */ + buf[len++] = '\n'; + if( tfx->not_dash_escaped ) + md_putc(tfx->md, '\n' ); + tfx->pending_lf = 1; + } + if( !len ) + rc = -1; /* eof */ + break; + } + if( tfx->md ) { + if( tfx->not_dash_escaped ) + md_write( tfx->md, p, n ); + else { + if( tfx->pending_lf ) { + md_putc(tfx->md, '\r' ); + md_putc(tfx->md, '\n' ); + } + md_write( tfx->md, p, len_without_trailing_ws( p, n ) ); + } + } + tfx->pending_lf = p[n-1] == '\n'; + if( tfx->not_dash_escaped ) + ; + else if( *p == '-' ) + tfx->pending_esc = 1; + else if( tfx->escape_from && n > 4 && !memcmp(p, "From ", 5 ) ) + tfx->pending_esc = 1; + } + *ret_len = len; + return rc; +} /**************** @@ -49,43 +189,11 @@ text_filter( void *opaque, int control, int rc=0; if( control == IOBUFCTRL_UNDERFLOW ) { - size_t len = 0; - unsigned maxlen; - - assert( size > 10 ); - size -= 2; /* reserve 2 bytes to append CR,LF */ - while( !rc && len < size ) { - int lf_seen; - - while( len < size && tfx->buffer_pos < tfx->buffer_len ) - buf[len++] = tfx->buffer[tfx->buffer_pos++]; - if( len >= size ) - continue; - - /* read the next line */ - maxlen = MAX_LINELEN; - tfx->buffer_pos = 0; - tfx->buffer_len = iobuf_read_line( a, &tfx->buffer, - &tfx->buffer_size, &maxlen ); - if( !maxlen ) - tfx->truncated++; - if( !tfx->buffer_len ) { - if( !len ) - rc = -1; /* eof */ - break; - } - lf_seen = tfx->buffer[tfx->buffer_len-1] == '\n'; - tfx->buffer_len = trim_trailing_ws( tfx->buffer, tfx->buffer_len ); - if( lf_seen ) { - tfx->buffer[tfx->buffer_len++] = '\r'; - tfx->buffer[tfx->buffer_len++] = '\n'; - } - } - - *ret_len = len; + if( tfx->clearsign ) + rc = clearsign( tfx, a, buf, size, ret_len ); + else + rc = standard( tfx, a, buf, size, ret_len ); } - else if( control == IOBUFCTRL_DESC ) - *(char**)buf = "text_filter"; else if( control == IOBUFCTRL_FREE ) { if( tfx->truncated ) log_error(_("can't handle text lines longer than %d characters\n"), @@ -93,6 +201,8 @@ text_filter( void *opaque, int control, m_free( tfx->buffer ); tfx->buffer = NULL; } + else if( control == IOBUFCTRL_DESC ) + *(char**)buf = "text_filter"; return rc; } diff --git a/include/iobuf.h b/include/iobuf.h index 9f4e8e72c..92671005c 100644 --- a/include/iobuf.h +++ b/include/iobuf.h @@ -104,6 +104,7 @@ int iobuf_writebyte(IOBUF a, unsigned c); int iobuf_write(IOBUF a, byte *buf, unsigned buflen ); int iobuf_writestr(IOBUF a, const char *buf ); +void iobuf_flush_temp( IOBUF temp ); int iobuf_write_temp( IOBUF a, IOBUF temp ); size_t iobuf_temp_to_buffer( IOBUF a, byte *buffer, size_t buflen ); void iobuf_unget_and_close_temp( IOBUF a, IOBUF temp ); diff --git a/include/util.h b/include/util.h index 892d508cc..8b8df37e8 100644 --- a/include/util.h +++ b/include/util.h @@ -161,6 +161,7 @@ STRLIST strlist_last( STRLIST node ); const char *memistr( const char *buf, size_t buflen, const char *sub ); char *mem2str( char *, const void *, size_t); char *trim_spaces( char *string ); +unsigned trim_trailing_ws( byte *line, unsigned len ); int string_count_chr( const char *string, int c ); int set_native_charset( const char *newset ); char *native_to_utf8( const char *string ); diff --git a/util/ChangeLog b/util/ChangeLog index 356e6df86..1afdf7602 100644 --- a/util/ChangeLog +++ b/util/ChangeLog @@ -1,3 +1,7 @@ +Wed Jan 20 18:59:49 CET 1999 Werner Koch + + * http.c (send_request): Removed double LF + Tue Jan 19 19:34:58 CET 1999 Werner Koch * * iobuf.c (iobuf_push_filter): Allow filters for temp streams diff --git a/util/http.c b/util/http.c index 22c5699e7..4f04b62e9 100644 --- a/util/http.c +++ b/util/http.c @@ -90,7 +90,7 @@ http_open( HTTP_HD hd, HTTP_REQ_TYPE reqtype, const char *url, } } - if( !hd->fp_read && !hd->fp_write ) + if( !hd->fp_read && !hd->fp_write && hd->socket != -1 ) close( hd->socket ); iobuf_close( hd->fp_read ); iobuf_close( hd->fp_write); @@ -102,7 +102,7 @@ http_open( HTTP_HD hd, HTTP_REQ_TYPE reqtype, const char *url, void -ttp_start_data( HTTP_HD hd ) +http_start_data( HTTP_HD hd ) { if( !hd->in_data ) { iobuf_put( hd->fp_write, '\n' ); @@ -166,7 +166,7 @@ http_close( HTTP_HD hd ) { if( !hd || !hd->initialized ) return; - if( !hd->fp_read && !hd->fp_write ) + if( !hd->fp_read && !hd->fp_write && hd->socket != -1 ) close( hd->socket ); iobuf_close( hd->fp_read ); iobuf_close( hd->fp_write ); @@ -433,7 +433,7 @@ send_request( HTTP_HD hd ) p = build_rel_path( hd->uri ); request = m_alloc( strlen(p) + 20 ); - sprintf( request, "%s %s%s HTTP/1.0\r\n\r\n", + sprintf( request, "%s %s%s HTTP/1.0\r\n", hd->req_type == HTTP_REQ_GET ? "GET" : hd->req_type == HTTP_REQ_HEAD? "HEAD": hd->req_type == HTTP_REQ_POST? "POST": "OOPS", @@ -553,12 +553,77 @@ parse_response( HTTP_HD hd ) return 0; } +#if 0 +static int +start_server() +{ + struct sockaddr_in mya; + struct sockaddr_in peer; + int fd, client; + fd_set rfds; + int addrlen; + int i; + + if( (fd=socket(AF_INET,SOCK_STREAM, 0)) == -1 ) { + log_error("socket() failed: %s\n", strerror(errno)); + return -1; + } + i = 1; + if( setsockopt( fd, SOL_SOCKET, SO_REUSEADDR, (byte*)&i, sizeof(i) ) ) + log_info("setsockopt(SO_REUSEADDR) failed: %s\n", strerror(errno) ); + + mya.sin_family=AF_INET; + memset(&mya.sin_addr, 0, sizeof(mya.sin_addr)); + mya.sin_port=htons(11371); + + if( bind( fd, (struct sockaddr *)&mya, sizeof(mya)) ) { + log_error("bind to port 11371 failed: %s\n", strerror(errno) ); + close( fd ); + return -1; + } + + if( listen( fd, 5 ) ) { + log_error("listen failed: %s\n", strerror(errno) ); + close( fd ); + return -1; + } + + for(;;) { + FD_ZERO(&rfds); + FD_SET( fd, &rfds ); + + if( select( fd+1, &rfds, NULL, NULL, NULL) <= 0 ) + continue; /* ignore any errors */ + + if( !FD_ISSET( fd, &rfds ) ) + continue; + + addrlen = sizeof peer; + client = accept( fd, (struct sockaddr *)&peer, &addrlen); + if( client == -1 ) + continue; /* oops */ + + log_info("connect from %s\n", inet_ntoa( peer.sin_addr ) ); + + fflush(stdout); + fflush(stderr); + if( !fork() ) { + int c; + FILE *fp; + + fp = fdopen( client , "r" ); + while( (c=getc(fp)) != EOF ) + putchar(c); + fclose(fp); + exit(0); + } + close( client ); + } - - - - + return 0; +} +#endif @@ -632,6 +697,11 @@ main(int argc, char **argv) int c; log_set_name("http-test"); + if( argc == 1 ) { + start_server(); + return 0; + } + if( argc != 2 ) { fprintf(stderr,"usage: http-test uri\n"); return 1; @@ -663,7 +733,7 @@ main(int argc, char **argv) } release_parsed_uri( uri ); uri = NULL; - rc = open_http_document( &hd, *argv, 0 ); + rc = http_open_document( &hd, *argv, 0 ); if( rc ) { log_error("can't get `%s': %s\n", *argv, g10_errstr(rc)); return 1; @@ -671,7 +741,7 @@ main(int argc, char **argv) log_info("open_http_document succeeded; status=%u\n", hd.status_code ); while( (c=iobuf_get( hd.fp_read)) != -1 ) putchar(c); - close_http_document( &hd ); + http_close( &hd ); return 0; } #endif /*TEST*/