diff --git a/src/Makefile b/src/Makefile index c9d1d41f01ef2c55bc1cad746e733fe0c84066bf..7a8ba94aa1c78079c40dbd499a19f02741dcb371 100644 --- a/src/Makefile +++ b/src/Makefile @@ -15,8 +15,8 @@ CFLAGS += -W -Wall -Wpedantic -Wno-language-extension-token CLANG ?= clang-6.0 CC=$(CLANG) -SAN_FLAGS ?= -fsanitize=address -fno-omit-frame-pointer -FUZZ_FLAGS ?= -DPASSBOOK_LIBFUZZER -fsanitize=fuzzer,address -fno-omit-frame-pointer +SAN_FLAGS ?= -fsanitize=address -fno-omit-frame-pointer -DPASSBOOK_FUZZ +FUZZ_FLAGS ?= -DPASSBOOK_LIBFUZZER -fsanitize=fuzzer,address -fno-omit-frame-pointer -DPASSBOOK_FUZZ NO_STRICT_OVERFLOW_CFLAGS ?= -fwrapv -fno-strict-overflow -Wstrict-overflow COV_FLAGS ?= -fprofile-instr-generate -fcoverage-mapping diff --git a/src/passbook.c b/src/passbook.c index c2063dc61a4f1d1a514267976053086949fb0f45..b7cb845d9d7ae542d57261fe51618f2e2cfc2d22 100644 --- a/src/passbook.c +++ b/src/passbook.c @@ -28,6 +28,8 @@ const char INSTRUCTION_SAVE[] = "save"; const char INSTRUCTION_LIST[] = "list"; +const char INSTRUCTION_MASTERPW[] = "masterpw"; + typedef struct { char * username; char * password; @@ -223,9 +225,13 @@ unsigned int tokenise(char *str, char * toks[], unsigned int toksLen){ /* two extra chars in each line: the newline '\n' and NUL '\0' */ #define INSTRUCTION_LENGTH (MAX_LINE_LENGTH+2) + /* a global instruction buffer */ char inst[INSTRUCTION_LENGTH]; +/* a global buffer to hold master password input. */ +char pwbuf[INSTRUCTION_LENGTH]; + /* password mapping for each url: initially empty */ node_t * map = NULL; @@ -370,17 +376,30 @@ void node_save(const node_t *p, FILE *f){ fprintf(f,"%s",p->cred.password); fprintf(f,"\n"); } - + +void masterpw_save(const char *pw, FILE *f){ + fprintf(f,"%s",INSTRUCTION_MASTERPW); + fprintf(f," "); + fprintf(f,"%s",pw); + fprintf(f,"\n"); +} + /* level order (i.e. breadth-first) traversal to print nodes out in the order that they would need to be put back in to an empty tree to ensure that the resulting tree has the same structure as the original one that was printed out. Returns 0 on success; nonzero on failure */ -int save_levelorder(const node_t *p, const char * filename){ +int save_levelorder(const node_t *p, const char *masterpw, + const char * filename){ +#ifdef PASSBOOK_FUZZ // ignore the file name when fuzzing + FILE *f = fopen(".passbook_fuzz_save_file","w"); +#else FILE *f = fopen(filename,"w"); +#endif if (f == NULL){ fprintf(stderr,"Couldn't open file %s for writing.\n",filename); return -1; } + masterpw_save(masterpw,f); nodeptr_list_t lst = {.head = NULL, .last = NULL}; if (p != NULL){ lst = list_push(lst,p); @@ -440,15 +459,32 @@ static int execute(void){ map = put(map,toks[1],cred); } else if (strcmp(toks[0],INSTRUCTION_SAVE) == 0){ - if (numToks != 2){ + if (numToks != 3){ return -1; } - debug_printf("Saving to: %s\n",toks[1]); - if (save_levelorder(map,toks[1]) != 0){ + debug_printf("Saving under master password %s to file: %s\n",toks[1],toks[2]); + if (save_levelorder(map,toks[1],toks[2]) != 0){ return -1; } debug_printf("---\n"); + } else if (strcmp(toks[0],INSTRUCTION_MASTERPW) == 0){ + if (numToks != 2){ + return -1; + } + printf("Enter master password: "); + char * res = fgets(pwbuf,sizeof(pwbuf),stdin); + char * pwtoks[1]; + const unsigned int numPWToks = tokenise(pwbuf,pwtoks,1); + if (res == NULL || numPWToks != 1 || strcmp(pwtoks[0],toks[1]) != 0){ + fprintf(stderr,"Master password incorrect! Exiting immediately.\n"); +#ifdef PASSBOOK_FUZZ // actually don't exit but keep going when fuzzing + return -1; +#else + exit(1); +#endif + } + } else if (strcmp(toks[0],INSTRUCTION_LIST) == 0){ if (numToks != 1){ return -1; @@ -473,7 +509,7 @@ static int run(FILE *f){ int instructionCount = 0; while (instructionCount < MAX_INSTRUCTIONS){ memset(inst,0,sizeof(inst)); - char * res = fgets(inst,MAX_LINE_LENGTH+2,f); + char * res = fgets(inst,sizeof(inst),f); if (res == NULL){ if (feof(f)){ /* end of file */