Prevent read_openpgp_stream from returning empty packets
authorJonathan McDowell <noodles@earth.li>
Sun, 29 Sep 2013 21:12:21 +0000 (22:12 +0100)
committerJonathan McDowell <noodles@earth.li>
Sun, 29 Sep 2013 21:12:21 +0000 (22:12 +0100)
If read_openpgp_stream got an invalid packet that had a semi valid
header it could potentially return an empty package, which would
confuse splitkeys. Cleanup the final package returned if it turns
out we didn't have valid data for it.

Fixes Debian bug #716350

parsekey.c
splitkeys.c

index aedbd14d8361a395b71d18abe7ee92eec4298c0d..b8bb5b0b44dbb64bf42b0952376c5f66c24bcff9 100644 (file)
@@ -191,7 +191,7 @@ onak_status_t read_openpgp_stream(int (*getchar_func)(void *ctx, size_t count,
                                int maxnum)
 {
        unsigned char                    curchar = 0;
-       struct openpgp_packet_list      *curpacket = NULL;
+       struct openpgp_packet_list      *curpacket = NULL, **packetend = NULL;
        onak_status_t                    rc = ONAK_E_OK;
        int                              keys = 0;
        bool                             inpacket = false;
@@ -216,10 +216,12 @@ onak_status_t read_openpgp_stream(int (*getchar_func)(void *ctx, size_t count,
                        inpacket = true;
                        if (curpacket != NULL) {
                                curpacket->next = malloc(sizeof (*curpacket));
+                               packetend = &curpacket->next;
                                curpacket = curpacket->next;
                        } else {
                                *packets = curpacket =
                                        malloc(sizeof (*curpacket));
+                               packetend = packets;
                        }
                        memset(curpacket, 0, sizeof(*curpacket));
                        curpacket->packet =
@@ -245,7 +247,9 @@ onak_status_t read_openpgp_stream(int (*getchar_func)(void *ctx, size_t count,
                                        curpacket->packet->length += 192;
                                } else if (curpacket->packet->length > 223 &&
                                        curpacket->packet->length < 255) {
-                                       return ONAK_E_UNSUPPORTED_FEATURE;
+                                       free(curpacket->packet);
+                                       curpacket->packet = NULL;
+                                       rc = ONAK_E_UNSUPPORTED_FEATURE;
                                } else if (curpacket->packet->length == 255) {
                                        /*
                                         * 5 byte length; ie 255 followed by 3
@@ -292,8 +296,8 @@ onak_status_t read_openpgp_stream(int (*getchar_func)(void *ctx, size_t count,
                                        break;
                                case 3:
                                        rc = ONAK_E_UNSUPPORTED_FEATURE;
-                                       curpacket->packet->length = 0;
-                                       curpacket->packet->data = NULL;
+                                       free(curpacket->packet);
+                                       curpacket->packet = NULL;
                                        break;
                                }
                        }
@@ -320,6 +324,12 @@ onak_status_t read_openpgp_stream(int (*getchar_func)(void *ctx, size_t count,
                }
        }
 
+       /* Trim the last packet if it doesn't actually exist */
+       if (packetend != NULL && (*packetend)->packet == NULL) {
+               free(*packetend);
+               *packetend = NULL;
+       }
+
        return (rc);
 }
 
index 2d3c58c8ea4a76ba13244ce3b08d59438a079fae..2a91d2faeac75fdd2eeb480126d67ead9a68786f 100644 (file)
@@ -63,7 +63,7 @@ int main(int argc, char *argv[])
                                        tmp->next = NULL;
                                }
                        }
-                       if (tmp->next != NULL) {
+                       if (tmp != NULL && tmp->next != NULL) {
                                list_end = NULL;
                        }