fix memory corruption caused by use-after-free
[oweals/ucert.git] / ucert.c
diff --git a/ucert.c b/ucert.c
index 12b42a875830f0e6857b2e8c5d953befd413562f..49d39e9fa58c226aad93d1d48694609b86145b48 100644 (file)
--- a/ucert.c
+++ b/ucert.c
@@ -156,8 +156,15 @@ static int cert_load(const char *certfile, struct list_head *chain) {
                else
                        pos += blob_pad_len(bufpt);
 
+               if (!certtb[CERT_ATTR_SIGNATURE])
+                       /* no signature -> drop */
+                       break;
+
                cobj = calloc(1, sizeof(*cobj));
-               memcpy(cobj->cert, &certtb, sizeof(certtb));
+               cobj->cert[CERT_ATTR_SIGNATURE] = blob_memdup(certtb[CERT_ATTR_SIGNATURE]);
+               if (certtb[CERT_ATTR_PAYLOAD])
+                       cobj->cert[CERT_ATTR_PAYLOAD] = blob_memdup(certtb[CERT_ATTR_PAYLOAD]);
+
                list_add_tail(&cobj->list, chain);
                ret += pret;
                bufpt = blob_next(bufpt);
@@ -624,39 +631,63 @@ int main(int argc, char *argv[]) {
        while ((ch = getopt(argc, argv, "ADIRVc:m:p:P:qs:x:")) != -1) {
                switch (ch) {
                case 'A':
+                       if (cmd != CMD_NONE)
+                               return usage(argv[0]);
                        cmd = CMD_APPEND;
                        break;
                case 'D':
+                       if (cmd != CMD_NONE)
+                               return usage(argv[0]);
                        cmd = CMD_DUMP;
                        break;
                case 'I':
+                       if (cmd != CMD_NONE)
+                               return usage(argv[0]);
                        cmd = CMD_ISSUE;
                        break;
                case 'R':
+                       if (cmd != CMD_NONE)
+                               return usage(argv[0]);
                        cmd = CMD_REVOKE;
                        break;
                case 'V':
+                       if (cmd != CMD_NONE)
+                               return usage(argv[0]);
                        cmd = CMD_VERIFY;
                        break;
                case 'c':
+                       if (certfile || cmd == CMD_NONE)
+                               return usage(argv[0]);
                        certfile = optarg;
                        break;
                case 'm':
+                       if (msgfile || cmd != CMD_VERIFY)
+                               return usage(argv[0]);
                        msgfile = optarg;
                        break;
                case 'p':
+                       if (pubkeyfile || (cmd != CMD_VERIFY && cmd != CMD_ISSUE) || cmd == CMD_NONE)
+                               return usage(argv[0]);
                        pubkeyfile = optarg;
                        break;
                case 'P':
+                       if (pubkeydir || (cmd != CMD_VERIFY && cmd != CMD_REVOKE) || cmd == CMD_NONE)
+                               return usage(argv[0]);
                        pubkeydir = optarg;
                        break;
                case 'q':
+                       if (quiet || cmd == CMD_NONE)
+                               return usage(argv[0]);
                        quiet = true;
                        break;
                case 's':
+                       if (seckeyfile || cmd != CMD_ISSUE || cmd == CMD_NONE)
+                               return usage(argv[0]);
                        seckeyfile = optarg;
                        break;
                case 'x':
+                       if (sigfile || cmd != CMD_APPEND || cmd == CMD_NONE)
+                               return usage(argv[0]);
                        sigfile = optarg;
                        break;
                default: