gpg: Allow --dearmor to decode all kinds of armor files.

* g10/filter.h (armor_filter_context_t): New fields dearmor_mode and
dearmor_state.
* g10/dearmor.c (dearmor_file): Set dearmor_mode.
* g10/armor.c (is_armor_header): Magic to switch to generic dearmor
mode.
(parse_header_line): Treat non OpenPGP armor in a special way.
(check_input): Ditto.
(radix64_read): Detect non OpenPGP armor END lines.
This commit is contained in:
Werner Koch 2022-01-28 12:09:34 +01:00
parent f2d1187fcd
commit 34ea19aff9
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B
4 changed files with 35 additions and 8 deletions

View File

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

View File

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

View File

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

View File

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