X-Git-Url: https://git.librecmc.org/?p=oweals%2Fucert.git;a=blobdiff_plain;f=ucert.c;h=6cdc2201fb3933bacfdfbb011102a167571206ee;hp=7e419d4d8b04700df3b6f06803706f5be3ba6185;hb=46eec66b190470254fc01973f208dc056bcb9780;hpb=bdc1ec45134f4f954365b3bb13b617b93c8c9bd1 diff --git a/ucert.c b/ucert.c index 7e419d4..6cdc220 100644 --- a/ucert.c +++ b/ucert.c @@ -47,6 +47,11 @@ static enum { } cmd = CMD_NONE; static bool quiet; +#ifndef UCERT_STRIP_MESSAGES +#define DPRINTF(format, ...) if (!quiet) fprintf(stderr, "%s(%d): " format, __func__, __LINE__, ## __VA_ARGS__) +#else +#define DPRINTF(format, ...) +#endif /* * ucert structure @@ -156,17 +161,24 @@ 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); /* repeat parsing while there is still enough remaining data in buffer */ - } while(len > pos + sizeof(struct blob_attr)); + } while(len > pos + sizeof(struct blob_attr) && (bufpt = blob_next(bufpt))); return (ret <= 0); } +#ifdef UCERT_FULL /* append signature to certfile */ static int cert_append(const char *certfile, const char *sigfile) { FILE *fs; @@ -191,6 +203,7 @@ static int cert_append(const char *certfile, const char *sigfile) { blob_buf_free(&sigbuf); return ret; } +#endif /* verify the signature of a single chain element */ static int cert_verify_blob(struct blob_attr *cert[CERT_ATTR_MAX], @@ -243,6 +256,7 @@ static int chain_verify(const char *msgfile, const char *pubkeyfile, char extsigfile[256] = {0}; int ret = 1; int checkmsg = 0; + struct timeval tv; if (mkdtemp(tmpdir) == NULL) return errno; @@ -250,10 +264,11 @@ static int chain_verify(const char *msgfile, const char *pubkeyfile, if (msgfile) checkmsg = -1; + gettimeofday(&tv, NULL); + list_for_each_entry(cobj, chain, list) { /* blob has payload, verify that using signature */ if (cobj->cert[CERT_ATTR_PAYLOAD]) { - struct timeval tv; uint64_t validfrom; uint64_t expiresat; uint32_t certtype; @@ -269,7 +284,7 @@ static int chain_verify(const char *msgfile, const char *pubkeyfile, blob_len(cobj->cert[CERT_ATTR_PAYLOAD])); if (!containertb[CERT_CT_ATTR_PAYLOAD]) { ret = 1; - fprintf(stderr, "no ucert in signed payload\n"); + DPRINTF("no ucert in signed payload\n"); goto clean_and_return; } blobmsg_parse(cert_payload_policy, @@ -283,7 +298,7 @@ static int chain_verify(const char *msgfile, const char *pubkeyfile, !payloadtb[CERT_PL_ATTR_EXPIRETIME] || !payloadtb[CERT_PL_ATTR_PUBKEY]) { ret = 1; - fprintf(stderr, "missing mandatory ucert attributes\n"); + DPRINTF("missing mandatory ucert attributes\n"); goto clean_and_return; } certtype = blobmsg_get_u32(payloadtb[CERT_PL_ATTR_CERTTYPE]); @@ -292,15 +307,14 @@ static int chain_verify(const char *msgfile, const char *pubkeyfile, if (certtype != CERTTYPE_AUTH) { ret = 2; - fprintf(stderr, "wrong certificate type\n"); + DPRINTF("wrong certificate type\n"); goto clean_and_return; } - gettimeofday(&tv, NULL); if (tv.tv_sec < validfrom || tv.tv_sec >= expiresat) { ret = 3; - fprintf(stderr, "certificate expired\n"); + DPRINTF("certificate expired\n"); goto clean_and_return; } @@ -311,14 +325,12 @@ static int chain_verify(const char *msgfile, const char *pubkeyfile, false); if (usign_f_pubkey(chainedfp, chainedpubkey)) { - if (!quiet) - fprintf(stderr, "cannot get fingerprint for chained key\n"); + DPRINTF("cannot get fingerprint for chained key\n"); ret = 2; goto clean_and_return; } if (pubkeydir && _usign_key_is_revoked(chainedfp, pubkeydir)) { - if (!quiet) - fprintf(stderr, "key %s has been revoked!\n", chainedfp); + DPRINTF("key %s has been revoked!\n", chainedfp); ret = 4; goto clean_and_return; } @@ -335,14 +347,14 @@ static int chain_verify(const char *msgfile, const char *pubkeyfile, pubkeydir, extsigfile, quiet); unlink(extsigfile); } else { - fprintf(stderr, "stray trailing signature without anything to verify!\n"); + DPRINTF("stray trailing signature without anything to verify!\n"); ret = 1; }; } } if (checkmsg == -1) - fprintf(stderr, "missing signature to verify message!\n"); + DPRINTF("missing signature to verify message!\n"); clean_and_return: if (chainedpubkey[0]) @@ -351,6 +363,7 @@ clean_and_return: return ret | checkmsg; } +#ifdef UCERT_FULL /* dump single chain element to console */ static void cert_dump_blob(struct blob_attr *cert[CERT_ATTR_MAX]) { int i; @@ -379,14 +392,13 @@ static int cert_dump(const char *certfile) { unsigned int count = 0; if (cert_load(certfile, &certchain)) { - fprintf(stderr, "cannot parse cert\n"); + DPRINTF("cannot parse cert\n"); return 1; } list_for_each_entry(cobj, &certchain, list) { - fprintf(stderr, "=== CHAIN ELEMENT %02u ===\n", ++count); + fprintf(stdout, "=== CHAIN ELEMENT %02u ===\n", ++count); cert_dump_blob(cobj->cert); - fprintf(stderr, "========================\n"); } return 0; @@ -397,7 +409,6 @@ static int cert_issue(const char *certfile, const char *pubkeyfile, const char * struct blob_buf certbuf; struct blob_buf payloadbuf; struct timeval tv; - struct stat st; int pklen, siglen; int revoker = 1; void *c; @@ -408,11 +419,6 @@ static int cert_issue(const char *certfile, const char *pubkeyfile, const char * char pkfp[17]; char tmpdir[] = "/tmp/ucert-XXXXXX"; - if (stat(certfile, &st) == 0) { - fprintf(stderr, "certfile %s exists, won't overwrite.\n", certfile); - return -1; - } - pkf = fopen(pubkeyfile, "r"); if (!pkf) return -1; @@ -472,7 +478,7 @@ static int cert_issue(const char *certfile, const char *pubkeyfile, const char * blob_put(&certbuf, CERT_ATTR_SIGNATURE, sigb, siglen); blob_put(&certbuf, CERT_ATTR_PAYLOAD, blob_data(payloadbuf.head), blob_len(payloadbuf.head)); snprintf(fname, sizeof(fname) - 1, "%s%s", certfile, revoker?".revoke":""); - write_file(fname, certbuf.head, blob_raw_len(certbuf.head), false); + write_file(fname, certbuf.head, blob_raw_len(certbuf.head), true); blob_buf_free(&certbuf); blob_buf_free(&payloadbuf); @@ -483,6 +489,7 @@ static int cert_issue(const char *certfile, const char *pubkeyfile, const char * return 0; } +#endif /* process revoker certificate */ static int cert_process_revoker(const char *certfile, const char *pubkeydir) { @@ -500,14 +507,17 @@ static int cert_process_revoker(const char *certfile, const char *pubkeydir) { int ret; if (cert_load(certfile, &certchain)) { - fprintf(stderr, "cannot parse cert\n"); + DPRINTF("cannot parse cert\n"); return 1; } + gettimeofday(&tv, NULL); + list_for_each_entry(cobj, &certchain, list) { - /* blob has payload, verify that using signature */ if (!cobj->cert[CERT_ATTR_PAYLOAD]) return 2; + + /* blob has payload, verify that using signature */ ret = cert_verify_blob(cobj->cert, NULL, pubkeydir); if (ret) return ret; @@ -518,7 +528,7 @@ static int cert_process_revoker(const char *certfile, const char *pubkeydir) { blob_data(cobj->cert[CERT_ATTR_PAYLOAD]), blob_len(cobj->cert[CERT_ATTR_PAYLOAD])); if (!containertb[CERT_CT_ATTR_PAYLOAD]) { - fprintf(stderr, "no ucert in signed payload\n"); + DPRINTF("no ucert in signed payload\n"); return 2; } @@ -531,7 +541,7 @@ static int cert_process_revoker(const char *certfile, const char *pubkeydir) { if (!payloadtb[CERT_PL_ATTR_CERTTYPE] || !payloadtb[CERT_PL_ATTR_VALIDFROMTIME] || !payloadtb[CERT_PL_ATTR_KEY_FINGERPRINT]) { - fprintf(stderr, "missing mandatory ucert attributes\n"); + DPRINTF("missing mandatory ucert attributes\n"); return 2; } @@ -540,11 +550,10 @@ static int cert_process_revoker(const char *certfile, const char *pubkeydir) { fingerprint = blobmsg_get_string(payloadtb[CERT_PL_ATTR_KEY_FINGERPRINT]); if (certtype != CERTTYPE_REVOKE) { - fprintf(stderr, "wrong certificate type\n"); + DPRINTF("wrong certificate type\n"); return 2; } - gettimeofday(&tv, NULL); if (tv.tv_sec < validfrom) { return 3; } @@ -553,8 +562,7 @@ static int cert_process_revoker(const char *certfile, const char *pubkeydir) { /* check if entry in pubkeydir exists */ if (stat(rfname, &st) == 0) { if (_usign_key_is_revoked(fingerprint, pubkeydir)) { - if (!quiet) - fprintf(stdout, "existing revoker deadlink for key %s\n", fingerprint); + DPRINTF("existing revoker deadlink for key %s\n", fingerprint); continue; }; @@ -567,8 +575,7 @@ static int cert_process_revoker(const char *certfile, const char *pubkeydir) { if (ret) return ret; - if (!quiet) - fprintf(stdout, "created revoker deadlink for key %s\n", fingerprint); + DPRINTF("created revoker deadlink for key %s\n", fingerprint); }; return ret; @@ -579,7 +586,7 @@ static int cert_verify(const char *certfile, const char *pubkeyfile, const char static LIST_HEAD(certchain); if (cert_load(certfile, &certchain)) { - fprintf(stderr, "cannot parse cert\n"); + DPRINTF("cannot parse cert\n"); return 1; } @@ -589,12 +596,15 @@ static int cert_verify(const char *certfile, const char *pubkeyfile, const char /* output help */ static int usage(const char *cmd) { +#ifndef UCERT_STRIP_MESSAGES fprintf(stderr, "Usage: %s \n" "Commands:\n" +#ifdef UCERT_FULL " -A: append signature (needs -c and -x)\n" " -D: dump (needs -c)\n" " -I: issue cert and revoker (needs -c and -p and -s)\n" +#endif /* UCERT_FULL */ " -R: process revoker certificate (needs -c and -P)\n" " -V: verify (needs -c and -p|-P, may have -m)\n" "Options:\n" @@ -603,10 +613,13 @@ static int usage(const char *cmd) " -p : public key file\n" " -P : public key directory (verify only)\n" " -q: quiet (do not print verification result, use return code only)\n" +#ifdef UCERT_FULL " -s : secret key file (issue only)\n" - " -x : signature file\n" + " -x : signature file (append only)\n" +#endif /* UCERT_FULL */ "\n", cmd); +#endif /* UCERT_STRIP_MESSAGES */ return 1; } @@ -614,15 +627,23 @@ static int usage(const char *cmd) int main(int argc, char *argv[]) { int ch; const char *msgfile = NULL; - const char *sigfile = NULL; const char *pubkeyfile = NULL; const char *pubkeydir = NULL; const char *certfile = NULL; +#ifdef UCERT_FULL + const char *sigfile = NULL; const char *seckeyfile = NULL; +#endif quiet = false; - while ((ch = getopt(argc, argv, "ADIRVc:m:p:P:qs:x:")) != -1) { + while ((ch = getopt(argc, argv, + "RVc:m:p:P:q" +#ifdef UCERT_FULL + "ADIs:x:" +#endif + )) != -1) { switch (ch) { +#ifdef UCERT_FULL case 'A': if (cmd != CMD_NONE) return usage(argv[0]); @@ -638,6 +659,7 @@ int main(int argc, char *argv[]) { return usage(argv[0]); cmd = CMD_ISSUE; break; +#endif case 'R': if (cmd != CMD_NONE) return usage(argv[0]); @@ -669,10 +691,11 @@ int main(int argc, char *argv[]) { pubkeydir = optarg; break; case 'q': - if (quiet || cmd == CMD_NONE) + if (quiet) return usage(argv[0]); quiet = true; break; +#ifdef UCERT_FULL case 's': if (seckeyfile || cmd != CMD_ISSUE || cmd == CMD_NONE) return usage(argv[0]); @@ -683,12 +706,14 @@ int main(int argc, char *argv[]) { return usage(argv[0]); sigfile = optarg; break; +#endif default: return usage(argv[0]); } } switch (cmd) { +#ifdef UCERT_FULL case CMD_APPEND: if (certfile && sigfile) return cert_append(certfile, sigfile); @@ -704,6 +729,7 @@ int main(int argc, char *argv[]) { return cert_issue(certfile, pubkeyfile, seckeyfile); else return usage(argv[0]); +#endif case CMD_REVOKE: if (certfile && pubkeydir) return cert_process_revoker(certfile, pubkeydir); @@ -714,7 +740,7 @@ int main(int argc, char *argv[]) { return cert_verify(certfile, pubkeyfile, pubkeydir, msgfile); else return usage(argv[0]); - case CMD_NONE: + default: return usage(argv[0]); }