diff --git a/doc/gpg.texi b/doc/gpg.texi index 537b8900f..ff66301d1 100644 --- a/doc/gpg.texi +++ b/doc/gpg.texi @@ -630,6 +630,7 @@ with ant release. @opindex dearmor Pack or unpack an arbitrary input into/from an OpenPGP ASCII armor. This is a GnuPG extension to OpenPGP and in general not very useful. +The @option{--dearmor} command can also be used to dearmor PEM armors. @item --unwrap @opindex unwrap diff --git a/g10/armor.c b/g10/armor.c index eb2d28bca..769348364 100644 --- a/g10/armor.c +++ b/g10/armor.c @@ -381,9 +381,9 @@ is_armor_tag(const char *line) } /**************** - * Check whether this is a armor line. - * returns: -1 if it is not a armor header or the index number of the - * armor header. + * Check whether this is a armor line. Returns: -1 if it is not a + * armor header, 42 if it is a generic header, or the index number of + * the armor header. */ static int is_armor_header( byte *line, unsigned len ) @@ -430,8 +430,12 @@ is_armor_header( byte *line, unsigned len ) if( !strcmp(s, p) ) break; *save_p = save_c; - if( !s ) + if (!s) + { + if (!strncmp (p, "BEGIN ", 6)) + return 42; return -1; /* unknown armor line */ + } if( opt.verbose > 1 ) log_info(_("armor: %s\n"), head_strings[i]); @@ -470,6 +474,8 @@ parse_header_line( armor_filter_context_t *afx, byte *line, unsigned int len ) */ p = strchr( line, ':'); + if (!p && afx->dearmor_state) + return 0; /* Special treatment in --dearmor mode. */ if( !p || (RFC2440 && p[1]!=' ') || (!RFC2440 && p[1]!=' ' && p[1]!='\n' && p[1]!='\r')) { @@ -489,7 +495,9 @@ parse_header_line( armor_filter_context_t *afx, byte *line, unsigned int len ) log_printf ("\n"); } - if( afx->in_cleartext ) + if (afx->dearmor_mode) + ; + else if (afx->in_cleartext) { if( (hashes=parse_hash_header( line )) ) afx->hashes |= hashes; @@ -559,17 +567,25 @@ check_input( armor_filter_context_t *afx, IOBUF a ) /* find the armor header */ while(len) { i = is_armor_header( line, len ); - if( i >= 0 && !(afx->only_keyblocks && i != 1 && i != 5 && i != 6 )) { + if ( i == 42 ) { + if (afx->dearmor_mode) { + afx->dearmor_state = 1; + break; + } + } + else if (i >= 0 + && !(afx->only_keyblocks && i != 1 && i != 5 && i != 6 )) { hdr_line = i; if( hdr_line == BEGIN_SIGNED_MSG_IDX ) { - if( afx->in_cleartext ) { + if( afx->in_cleartext ) { log_error(_("nested clear text signatures\n")); rc = gpg_error (GPG_ERR_INV_ARMOR); - } + } afx->in_cleartext = 1; } break; } + /* read the next line (skip all truncated lines) */ do { maxlen = MAX_LINELEN; @@ -692,6 +708,8 @@ fake_packet( armor_filter_context_t *afx, IOBUF a, /* Five dashes in a row mean it's probably armor header. */ int type = is_armor_header( p, n ); + if (type == 42) + type = -1; /* Only OpenPGP armors are expected. */ if( afx->not_dash_escaped && type != BEGIN_SIGNATURE ) ; /* this is okay */ else @@ -998,6 +1016,11 @@ radix64_read( armor_filter_context_t *afx, IOBUF a, size_t *retn, checkcrc++; break; } + else if (afx->dearmor_state && c == '-' + && afx->buffer_pos + 8 < afx->buffer_len + && !strncmp (afx->buffer, "-----END ", 8)) { + break; /* End in --dearmor mode. */ + } else { log_error(_("invalid radix64 character %02X skipped\n"), c); continue; diff --git a/g10/dearmor.c b/g10/dearmor.c index 92239ccfd..d364678c7 100644 --- a/g10/dearmor.c +++ b/g10/dearmor.c @@ -45,6 +45,7 @@ dearmor_file( const char *fname ) int c; afx = new_armor_context (); + afx->dearmor_mode = 1; /* prepare iobufs */ inp = iobuf_open(fname); diff --git a/g10/filter.h b/g10/filter.h index b2ef3828f..46342d2ad 100644 --- a/g10/filter.h +++ b/g10/filter.h @@ -35,6 +35,7 @@ typedef struct { /* these fields may be initialized */ int what; /* what kind of armor headers to write */ int only_keyblocks; /* skip all headers but ".... key block" */ + int dearmor_mode; /* dearmor all kind of stuff. */ const char *hdrlines; /* write these headerlines */ /* these fields must be initialized to zero */ @@ -49,6 +50,7 @@ typedef struct { int faked; /* we are faking a literal data packet */ int truncated; /* number of truncated lines */ int qp_detected; + int dearmor_state; /* helper for dearmor_mode. */ byte eol[3]; /* The end of line characters as a zero-terminated string. Defaults (eol[0]=='\0') to whatever the local