This helper simplifies handling, ensures that there are no resource
leaks, and checks for EOF more robustly.
Also introduce error reporting at all call sites to give the user some
feedback when something went wrong.
Signed-off-by: Matthias Schiffer <mschiffer@universe-factory.net>
#include <fcntl.h>
#include <dlfcn.h>
#include <fcntl.h>
#include <dlfcn.h>
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
return (outlen == len);
}
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) {
/* load certfile into list */
static int cert_load(const char *certfile, struct list_head *chain) {
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;
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");
bufpt = (struct blob_attr *)filebuf;
do {
bufpt = (struct blob_attr *)filebuf;
do {
/* no attributes found */
break;
/* 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
/* blob exceeds filebuffer */
break;
else
list_add_tail(&cobj->list, chain);
ret += pret;
/* repeat parsing while there is still enough remaining data in buffer */
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)));
#ifdef UCERT_FULL
/* append signature to certfile */
static int cert_append(const char *certfile, const char *sigfile) {
#ifdef UCERT_FULL
/* append signature to certfile */
static int cert_append(const char *certfile, const char *sigfile) {
char filebuf[CERT_BUF_LEN];
struct blob_buf sigbuf = {0};
char filebuf[CERT_BUF_LEN];
struct blob_buf sigbuf = {0};
- 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)
blob_buf_init(&sigbuf, 0);
blob_put(&sigbuf, CERT_ATTR_SIGNATURE, filebuf, len);
blob_buf_init(&sigbuf, 0);
blob_put(&sigbuf, CERT_ATTR_SIGNATURE, filebuf, len);
struct blob_buf payloadbuf = {0};
struct blob_buf certbuf = {0};
struct timeval tv;
struct blob_buf payloadbuf = {0};
struct blob_buf certbuf = {0};
struct timeval tv;
int revoker = 1;
void *c;
int revoker = 1;
void *c;
char pkb[512];
char sigb[1024];
char fname[256], sfname[256];
char pkfp[17];
char tmpdir[] = "/tmp/ucert-XXXXXX";
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 (usign_f_pubkey(pkfp, pubkeyfile))
return -1;
if (usign_f_pubkey(pkfp, pubkeyfile))
return -1;
if (usign_s(fname, seckeyfile, sfname, quiet))
return 1;
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)
unlink(fname);
unlink(sfname);
unlink(fname);
unlink(sfname);