Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes for armor and cleartext messages parsing #423

Merged
merged 7 commits into from
Aug 24, 2017
19 changes: 15 additions & 4 deletions src/lib/writer.c
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,7 @@ dash_esc_writer(const uint8_t *src, unsigned len, pgp_error_t **errors, pgp_writ
{
dashesc_t *dash = pgp_writer_get_arg(writer);
unsigned n;
bool escape;

if (rnp_get_debug(__FILE__)) {
unsigned i = 0;
Expand All @@ -441,11 +442,11 @@ dash_esc_writer(const uint8_t *src, unsigned len, pgp_error_t **errors, pgp_writ
for (n = 0; n < len; ++n) {
unsigned l;

if (dash->seen_nl) {
if (src[n] == '-' && !stacked_write(writer, "- ", 2, errors)) {
return false;
escape = false;
if (dash->seen_nl || dash->seen_cr) {
if (src[n] == '-') {
escape = true;
}
dash->seen_nl = 0;
}
dash->seen_nl = src[n] == '\n';

Expand All @@ -455,8 +456,18 @@ dash_esc_writer(const uint8_t *src, unsigned len, pgp_error_t **errors, pgp_writ
}
pgp_sig_add_data(dash->sig, "\r", 1);
}
if (dash->seen_cr && !dash->seen_nl) {
if (!stacked_write(writer, "\n", 1, errors)) {
return false;
}
pgp_sig_add_data(dash->sig, "\n", 1);
}
dash->seen_cr = src[n] == '\r';

if (escape && !stacked_write(writer, "- ", 2, errors)) {
return false;
}

if (!stacked_write(writer, &src[n], 1, errors)) {
return false;
}
Expand Down
65 changes: 54 additions & 11 deletions src/librepgp/reader.c
Original file line number Diff line number Diff line change
Expand Up @@ -516,6 +516,7 @@ process_dash_escaped(pgp_stream_t *stream,
pgp_packet_t content;
const char * hashstr;
int total;
bool hadcr = false;
pgp_hash_alg_t alg = PGP_HASH_MD5; // default

body = &content.u.cleartext_body;
Expand Down Expand Up @@ -568,35 +569,63 @@ process_dash_escaped(pgp_stream_t *stream,
return -1;
}
}

// treating CR as newline, and then skipping LF
if (c == '\r') {
c = '\n';
hadcr = true;
} else if ((c == '\n') && hadcr) {
continue;
} else {
hadcr = false;
}

if (c == '\n' && body->length) {
if (memchr(body->data + 1, '\n', body->length - 1) != NULL) {
if ((body->length > 2) &&
(memchr(body->data + 2, '\n', body->length - 2) != NULL)) {
(void) fprintf(stderr, "process_dash_escaped: newline found\n");
return -1;
}
if (rnp_get_debug(__FILE__)) {
fprintf(stderr, "Got body:\n%s\n", body->data);
fprintf(stderr, "Got body:\n%.*s\n", body->length, body->data);
}

// Removing trailing whitespaces as per RFC
while ((body->length > 0) && ((body->data[body->length - 1] == 0x20) ||
(body->data[body->length - 1] == 0x09))) {
body->length--;
}

CALLBACK(PGP_PTAG_CT_SIGNED_CLEARTEXT_BODY, cbinfo, &content);
body->length = 0;
}

if (c == '\n') {
body->data[body->length++] = '\r';
total++;
}
body->data[body->length++] = c;
total += 1;
if (body->length == sizeof(body->data)) {
total++;

if (body->length == sizeof(body->data) - 1) {
if (rnp_get_debug(__FILE__)) {
(void) fprintf(stderr, "Got body (2):\n%s\n", body->data);
(void) fprintf(stderr, "Got body (2):\n%.*s\n", body->length, body->data);
}
CALLBACK(PGP_PTAG_CT_SIGNED_CLEARTEXT_BODY, cbinfo, &content);
body->length = 0;
}
}
if (body->data[0] != '\n') {

if (body->data[1] != '\n') {
(void) fprintf(stderr, "process_dash_escaped: no newline in body data\n");
return -1;
}
if (body->length != 1) {

if (body->length != 2) {
(void) fprintf(stderr, "process_dash_escaped: bad body length\n");
return -1;
}

/* don't send that one character, because it's part of the trailer */
(void) memset(&content2, 0x0, sizeof(content2));
CALLBACK(PGP_PTAG_CT_SIGNED_CLEARTEXT_TRAILER, cbinfo, &content2);
Expand Down Expand Up @@ -948,11 +977,23 @@ armoured_data_reader(pgp_stream_t *stream,
unsigned first;
uint8_t * dest = dest_;
char buf[1024];
int saved;
size_t saved;
rnp_result ret;
int n;

dearmour = pgp_reader_get_arg(readinfo);
saved = (int) length;
saved = length;

if (!stream->coalescing && stream->virtualc && stream->virtualoff < stream->virtualc) {
n = read_partial_data(stream, dest_, length);
if ((n < 0) || (n == length)) {
return n;
} else {
length -= n;
dest_ = (char*)dest_ + n;
}
}

if (dearmour->eof64 && !dearmour->buffered) {
if (dearmour->state != OUTSIDE_BLOCK && dearmour->state != AT_TRAILER_NAME) {
(void) fprintf(stderr, "armoured_data_reader: bad dearmour state\n");
Expand Down Expand Up @@ -1092,11 +1133,13 @@ armoured_data_reader(pgp_stream_t *stream,
"armoured_data_reader: bad dearmour eof64\n");
return 0;
}
dearmour->state = AT_TRAILER_NAME;

if (first) {
dearmour->state = AT_TRAILER_NAME;
goto reloop;
} else {
return saved - length;
}
return -1;
}
}
if (!dearmour->buffered) {
Expand Down
3 changes: 2 additions & 1 deletion src/tests/cli_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ def pswd_pipe(passphrase):
return pr

def random_text(path, size):
st = ''.join(random.choice(string.printable) for _ in range(size))
#st = ''.join(random.choice(string.printable) for _ in range(size))
st = ''.join(random.choice(string.ascii_letters + string.digits + " \t\n-,.") for _ in range(size))
with open(path, 'w+') as f:
f.write(st)

Expand Down
Loading