diff --git a/generate_sbat_var_defs.c b/generate_sbat_var_defs.c index 1bf53a261..df642ac40 100644 --- a/generate_sbat_var_defs.c +++ b/generate_sbat_var_defs.c @@ -9,119 +9,158 @@ #include #include +#include #include typedef struct sbat_revocation sbat_revocation; struct sbat_revocation { - int date; + unsigned int date; char *revocations; sbat_revocation *next; }; static sbat_revocation *revlisthead; -int -readfile(char *SbatLevel_Variable) +static void +free_revocation_list(void) +{ + sbat_revocation *rle = revlisthead; + while (rle) { + sbat_revocation *next = rle->next; + free(rle->revocations); + free(rle); + rle = next; + } + revlisthead = NULL; +} + +static int +check_revocation_line(const char *line) +{ + int num = -1; + if (sscanf(line, "%*[^, \t],%*[0-9]%n", &num) < 0 || + num < 0 || line[num] != '\0') { + fprintf(stderr, "Invalid revocation line: %s\n", line); + return -1; + } + return 0; +} + +static void +chomp(char *str) +{ + size_t len = strlen(str); + if (len > 0 && str[--len] == '\n') + str[len] = '\0'; +} + +static int +readfile(const char *SbatLevel_Variable) { FILE *varfilep; char line[1024]; - int date; int ret = -1; - unsigned int revocationsp = 0; - sbat_revocation *revlistlast = NULL; sbat_revocation *revlistentry = NULL; - revlisthead = NULL; + free_revocation_list(); varfilep = fopen(SbatLevel_Variable, "r"); - if (varfilep == NULL) + if (varfilep == NULL) { + fprintf(stderr, "Error opening file %s\n", SbatLevel_Variable); return -1; + } while (fgets(line, sizeof(line), varfilep) != NULL) { - if (sscanf(line, "sbat,1,%d\n", &date) && strlen(line) == 18) { - revlistentry = calloc(1, sizeof(sbat_revocation)); - if (revlistentry == NULL) + unsigned int date; + size_t revocationsp = 0; + + if (!sscanf(line, "sbat,1,%u\n", &date) || strlen(line) != 18) + continue; + revlistentry = calloc(1, sizeof(sbat_revocation)); + if (revlistentry == NULL) { + fprintf(stderr, "Out of memory\n"); + goto err; + } + if (revlisthead == NULL) + revlisthead = revlistentry; + else + revlistlast->next = revlistentry; + + revlistlast = revlistentry; + + revlistentry->date = date; + while (fgets(line, sizeof(line), varfilep) != NULL) { + chomp(line); + + char *new = NULL; + new = realloc(revlistentry->revocations, + revocationsp + strlen(line) + 3); + if (new == NULL) { + fprintf(stderr, "Out of memory\n"); goto err; - if (revlisthead == NULL) - revlisthead = revlistentry; - else - revlistlast->next = revlistentry; - - revlistlast = revlistentry; - - revlistentry->date = date; - while (line[0] != '\n' && - fgets(line, sizeof(line), varfilep) != NULL) { - char *new = NULL; - new = realloc(revlistentry->revocations, - revocationsp + strlen(line) + 2); - if (new == NULL) { - ret = -1; - goto err; - } - revlistentry->revocations = new; - if (strlen(line) > 1) { - line[strlen(line) - 1] = 0; - sprintf(revlistentry->revocations + - revocationsp, - "%s\\n", line); - revocationsp = - revocationsp + strlen(line) + 2; - } } - revocationsp = 0; + new[revocationsp] = '\0'; + revlistentry->revocations = new; + if (strlen(line) == 0) + break; + + if (check_revocation_line(line)) + goto err; + sprintf(revlistentry->revocations + revocationsp, + "%s\\n", line); + revocationsp = strlen(revlistentry->revocations); } } - ret = 1; + if (!ferror(varfilep)) + ret = 0; err: - if (ret < 0 && revlisthead) { - sbat_revocation *rle = revlisthead; - while (rle) { - sbat_revocation *next = rle->next; - if (rle->revocations) - free(rle->revocations); - free(rle); - rle = next; - } - revlisthead = NULL; - } + if (ret < 0) + free_revocation_list(); fclose(varfilep); return ret; } -int -writefile() +static int +writefile(void) { - int epochfound = 0; - int epochdate = 2021030218; - int latestdate = 0; + bool epochfound = false; + unsigned int epochdate = 2021030218; + unsigned int latestdate = 0; - sbat_revocation *revlistentry; - sbat_revocation *latest_revlistentry = NULL; + const sbat_revocation *revlistentry; + const sbat_revocation *latest_revlistentry = NULL; revlistentry = revlisthead; while (revlistentry != NULL) { if (revlistentry->date == epochdate) { - printf("#ifndef GEN_SBAT_VAR_DEFS_H_\n" + if (epochfound) { + fprintf(stderr, "Only one epoch expected\n"); + return -1; + } + printf("// Autogenerated by generate_sbat_var_defs\n\n" + "#ifndef GEN_SBAT_VAR_DEFS_H_\n" "#define GEN_SBAT_VAR_DEFS_H_\n" "#ifndef ENABLE_SHIM_DEVEL\n\n" "#ifndef SBAT_AUTOMATIC_DATE\n" "#define SBAT_AUTOMATIC_DATE 2024040900\n" - "#endif /* SBAT_AUTOMATIC_DATE */\n" - "#if SBAT_AUTOMATIC_DATE == %d\n" + "#endif /* SBAT_AUTOMATIC_DATE */\n\n" + "#if SBAT_AUTOMATIC_DATE == %u\n" "#define SBAT_VAR_AUTOMATIC_REVOCATIONS\n", revlistentry->date); - epochfound = 1; - } else if (epochfound == 1) { - printf("#elif SBAT_AUTOMATIC_DATE == %d\n" + epochfound = true; + } else if (epochfound) { + printf("#elif SBAT_AUTOMATIC_DATE == %u\n" "#define SBAT_VAR_AUTOMATIC_REVOCATIONS \"%s\"\n", revlistentry->date, revlistentry->revocations); + } else { + fprintf(stderr, "Revocation not expected before epoch\n"); + return -1; } if (revlistentry->date > latestdate) { latest_revlistentry = revlistentry; @@ -130,25 +169,27 @@ writefile() revlistentry = revlistentry->next; } - if (epochfound == 0 || !latest_revlistentry) + if (!epochfound || !latest_revlistentry) { + fprintf(stderr, "Epoch not found\n"); return -1; + } printf("#else\n" "#error \"Unknown SBAT_AUTOMATIC_DATE\"\n" "#endif /* SBAT_AUTOMATIC_DATE == */\n\n" "#define SBAT_VAR_AUTOMATIC_DATE QUOTEVAL(SBAT_AUTOMATIC_DATE)\n" "#define SBAT_VAR_AUTOMATIC \\\n" - " SBAT_VAR_SIG SBAT_VAR_VERSION SBAT_VAR_AUTOMATIC_DATE \"\\n\" \\\n" - " SBAT_VAR_AUTOMATIC_REVOCATIONS\n\n"); + " SBAT_VAR_SIG SBAT_VAR_VERSION SBAT_VAR_AUTOMATIC_DATE \"\\n\" \\\n" + " SBAT_VAR_AUTOMATIC_REVOCATIONS\n\n"); - printf("#define SBAT_VAR_LATEST_DATE \"%d\"\n" + printf("#define SBAT_VAR_LATEST_DATE \"%u\"\n" "#define SBAT_VAR_LATEST_REVOCATIONS \"%s\"\n", latest_revlistentry->date, latest_revlistentry->revocations); printf("#define SBAT_VAR_LATEST \\\n" - " SBAT_VAR_SIG SBAT_VAR_VERSION SBAT_VAR_LATEST_DATE \"\\n\" \\\n" - " SBAT_VAR_LATEST_REVOCATIONS\n\n" + " SBAT_VAR_SIG SBAT_VAR_VERSION SBAT_VAR_LATEST_DATE \"\\n\" \\\n" + " SBAT_VAR_LATEST_REVOCATIONS\n\n" "#endif /* !ENABLE_SHIM_DEVEL */\n" "#endif /* !GEN_SBAT_VAR_DEFS_H_ */\n"); @@ -161,13 +202,12 @@ main(int argc, char *argv[]) { char SbatLevel_Variable[2048]; - if (argc == 2) + if (argc >= 2) snprintf(SbatLevel_Variable, 2048, "%s/SbatLevel_Variable.txt", argv[1]); else snprintf(SbatLevel_Variable, 2048, "SbatLevel_Variable.txt"); if (readfile(SbatLevel_Variable)) - return writefile(); - else return -1; + return writefile(); }