X-Git-Url: https://git.librecmc.org/?p=oweals%2Fucert.git;a=blobdiff_plain;f=ucert.c;fp=ucert.c;h=89bf0c64d4b500e971f23e70125c588a806b0563;hp=7de4c12711e861bbf1ca0e5c26c082c3e04c832a;hb=854d93e2326a0c027686b0058116629002fd011f;hpb=afc86f352bf7915f81e9d38949e91306542aadee diff --git a/ucert.c b/ucert.c index 7de4c12..89bf0c6 100644 --- a/ucert.c +++ b/ucert.c @@ -15,6 +15,7 @@ #include #include +#include #include #include #include @@ -129,28 +130,51 @@ static bool write_file(const char *filename, void *buf, size_t len, bool append) return (outlen == len); } +/* reads a whole file to a buffer - returns -1 on errors and sets errno */ +static ssize_t read_file(const char *filename, void *buf, size_t len, size_t minlen) { + FILE *f; + ssize_t ret; + + f = fopen(filename, "r"); + if (!f) + return -1; + + ret = fread(buf, 1, len, f); + + /* Ensure that feof() yields the correct result when the file is exactly + * len bytes long */ + fgetc(f); + + if (ferror(f)) { + ret = -1; + } else if (!feof(f)) { + errno = EOVERFLOW; + ret = -1; + } else if ((size_t)ret < minlen) { + errno = EINVAL; + ret = -1; + } + + fclose(f); + return ret; +} + /* load certfile into list */ static int cert_load(const char *certfile, struct list_head *chain) { - FILE *f; struct blob_attr *certtb[CERT_ATTR_MAX]; struct blob_attr *bufpt; struct cert_object *cobj; char filebuf[CERT_BUF_LEN]; int ret = 0, pret = 0; - size_t len, pos = 0; - - f = fopen(certfile, "r"); - if (!f) - return 1; - - len = fread(&filebuf, 1, CERT_BUF_LEN - 1, f); - if (len < 64) - return 1; + size_t pos = 0; + ssize_t len; - ret = ferror(f) || !feof(f); - fclose(f); - if (ret) + len = read_file(certfile, filebuf, sizeof(filebuf) - 1, 0); + if (len < 0) { + if (!quiet) + perror("Unable to load certificate file"); return 1; + } bufpt = (struct blob_attr *)filebuf; do { @@ -159,7 +183,7 @@ static int cert_load(const char *certfile, struct list_head *chain) { /* no attributes found */ break; - if (pos + blob_pad_len(bufpt) > len) + if (pos + blob_pad_len(bufpt) > (size_t) len) /* blob exceeds filebuffer */ break; else @@ -177,7 +201,7 @@ static int cert_load(const char *certfile, struct list_head *chain) { list_add_tail(&cobj->list, chain); ret += pret; /* repeat parsing while there is still enough remaining data in buffer */ - } while(len > pos + sizeof(struct blob_attr) && (bufpt = blob_next(bufpt))); + } while((size_t) len > pos + sizeof(struct blob_attr) && (bufpt = blob_next(bufpt))); return (ret <= 0); } @@ -185,21 +209,18 @@ static int cert_load(const char *certfile, struct list_head *chain) { #ifdef UCERT_FULL /* append signature to certfile */ static int cert_append(const char *certfile, const char *sigfile) { - FILE *fs; char filebuf[CERT_BUF_LEN]; struct blob_buf sigbuf = {0}; - int len; + ssize_t len; int ret; - fs = fopen(sigfile, "r"); - if (!fs) - return 1; + len = read_file(sigfile, filebuf, sizeof(filebuf) - 1, 64); + if (len < 0) { + if (!quiet) + perror("Unable to load signature file"); - len = fread(&filebuf, 1, CERT_BUF_LEN - 1, fs); - ret = ferror(fs) || !feof(fs) || (len < 64); - fclose(fs); - if (ret) return 1; + } blob_buf_init(&sigbuf, 0); blob_put(&sigbuf, CERT_ATTR_SIGNATURE, filebuf, len); @@ -420,27 +441,24 @@ static int cert_issue(const char *certfile, const char *pubkeyfile, const char * struct blob_buf payloadbuf = {0}; struct blob_buf certbuf = {0}; struct timeval tv; - int pklen, siglen; + ssize_t pklen, siglen; int revoker = 1; void *c; - FILE *pkf, *sigf; char pkb[512]; char sigb[1024]; char fname[256], sfname[256]; char pkfp[17]; char tmpdir[] = "/tmp/ucert-XXXXXX"; - pkf = fopen(pubkeyfile, "r"); - if (!pkf) - return -1; - - pklen = fread(pkb, 1, 512, pkf); - pkb[pklen] = '\0'; + pklen = read_file(pubkeyfile, pkb, sizeof(pkb) - 1, 32); + if (pklen < 0) { + if (!quiet) + perror("Unable to load public key file"); - if (pklen < 32) return -1; + } - fclose(pkf); + pkb[pklen] = '\0'; if (usign_f_pubkey(pkfp, pubkeyfile)) return -1; @@ -471,16 +489,15 @@ static int cert_issue(const char *certfile, const char *pubkeyfile, const char * if (usign_s(fname, seckeyfile, sfname, quiet)) return 1; - sigf = fopen(sfname, "r"); - if (!sigf) - return 1; + siglen = read_file(sfname, sigb, sizeof(sigb) - 1, 1); + if (siglen < 0) { + if (!quiet) + perror("Unable to load signature file"); - siglen = fread(sigb, 1, 1024, sigf); - if (siglen < 1) return 1; + } sigb[siglen] = '\0'; - fclose(sigf); unlink(fname); unlink(sfname);