diff --git a/src/passbook.c b/src/passbook.c
index 39589184c4c12ca191f0954261ef1fa9f72b1b3a..cfbd18095e9aa155cd6c76068de286b3e25e3ad5 100644
--- a/src/passbook.c
+++ b/src/passbook.c
@@ -7,11 +7,6 @@
#include "debug.h"
-/*
- FIXME: the save command is a DoS. Allow this to be turned off
- and ensure it is turned off when testing student submissions
-*/
-
#ifdef PASSBOOK_LIBFUZZER
#include <stdint.h>
const char LIBFUZZER_INPUT_FILE[] = "libFuzzerInput.tmp";
@@ -32,6 +27,7 @@ const char INSTRUCTION_LIST[] = "list";
const char INSTRUCTION_MASTERPW[] = "masterpw";
+/* a credential is a username/password pair */
typedef struct {
char * username;
char * password;
@@ -64,6 +60,7 @@ static void node_print(const node_t *p){
printf("URL: %s, Username: %s, Password: %s\n",p->url,p->cred.username,p->cred.password);
}
+/* construct a new node */
static node_t *node_new(const char *url, const cred_t cred){
node_t *new = malloc(sizeof(node_t));
assert(new != NULL && "new: malloc failed");
@@ -119,7 +116,6 @@ static node_t * node_insert(node_t *p, node_t *q){
/* edit the node in place */
node_edit_cred(p,q);
/* q is now freed so cannot be used anymore */
-
return start;
}else if (ret < 0){
if (p->left == NULL){
@@ -199,20 +195,16 @@ unsigned int tokenise(char *str, char * toks[], unsigned int toksLen){
while (numToks < toksLen){
/* strip leading whitespace */
size_t start = strspn(str,WHITESPACE);
- debug_printf("start: %lu\n",start);
if (str[start] != '\0'){
toks[numToks] = &(str[start]);
- debug_printf("Token %u starts here: --begintok--%s--end--\n",numToks,toks[numToks]);
/* compute the length of the token */
const size_t tokLen = strcspn(toks[numToks],WHITESPACE);
if (tokLen > 0){
toks[numToks][tokLen] = '\0';
- debug_printf("Found token %d: --begintok--%s--endtok--\n",numToks,toks[numToks]);
str = &(toks[numToks][tokLen+1]);
numToks++;
}else{
- debug_printf("tokLen was: %lu\n",tokLen);
return numToks;
}
}else{
@@ -231,16 +223,14 @@ unsigned int tokenise(char *str, char * toks[], unsigned int toksLen){
/* 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;
/* a doubly-linked list of node pointers
is used to implement stacks/queues of nodes so we can implement various
tree traversal algorithms without using recursion (to avoid stack overflow
- for very large trees). */
+ for very large trees). Stack overflow is a trivial form of memory-safety
+ vulnerability. */
typedef struct nodeptr_list_elem {
const node_t *p;
struct nodeptr_list_elem *next;
@@ -253,6 +243,7 @@ typedef struct nodeptr_list {
} nodeptr_list_t;
+/* push an element p onto the front of a nodeptr list lst */
nodeptr_list_t list_push(nodeptr_list_t lst, const node_t *p){
nodeptr_list_elem_t *n = malloc(sizeof(nodeptr_list_elem_t));
assert(n != NULL && "push: malloc failed");
@@ -310,36 +301,8 @@ nodeptr_list_t list_dequeue(nodeptr_list_t lst, const node_t **out){
return lst;
}
-#ifdef UNUSED_FUNCTIONS
-nodeptr_list_t list_destroy(nodeptr_list_t lst){
- while (lst.head != NULL){
- lst = list_pop(lst,NULL);
- }
- return lst;
-}
-
-void list_print(nodeptr_list_t lst){
- printf("\nBegin list print:\n");
- while (lst.head != NULL){
- const node_t *p;
- lst = list_pop(lst,&p);
- node_print(p);
- }
- printf("End list print.\n\n");
-}
-
-void list_print_rev(nodeptr_list_t lst){
- printf("\nBegin list reverse print:\n");
- while (lst.last != NULL){
- const node_t *p;
- lst = list_dequeue(lst,&p);
- node_print(p);
- }
- printf("End list reverse print.\n\n");
-}
-#endif
-
-/* in order traversal to print out nodes in sorted order */
+/* in order traversal to print out nodes in sorted order. Is used to
+ implement listing of all entries in the passbook */
void print_inorder(const node_t *p){
nodeptr_list_t lst = {.head = NULL, .last = NULL};
if (p != NULL){
@@ -368,6 +331,9 @@ void print_inorder(const node_t *p){
}
}
+/* save a node to the given file. We save to the file a "put" instruction
+ that will cause the node to be placed back into the passbook when the
+ file is read. */
void node_save(const node_t *p, FILE *f){
fprintf(f,"%s",INSTRUCTION_PUT);
fprintf(f," ");
@@ -379,6 +345,9 @@ void node_save(const node_t *p, FILE *f){
fprintf(f,"\n");
}
+/* save the master password to the given file. We save a "masterpw"
+ instruction that will cause the passbook to prompt the user for the
+ given master password the next time the file is read */
void masterpw_save(const char *pw, FILE *f){
fprintf(f,"%s",INSTRUCTION_MASTERPW);
fprintf(f," ");
@@ -387,12 +356,14 @@ void masterpw_save(const char *pw, FILE *f){
}
/* 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 */
+ order that they need to be put back in to an empty tree to ensure
+ that the resulting tree has the same structure as the original one.
+ This is how we save the passbook to a file.
+ Returns 0 on success; nonzero on failure */
int save_levelorder(const node_t *p, const char *masterpw,
const char * filename){
-#ifdef PASSBOOK_FUZZ // ignore the file name when fuzzing
+#ifdef PASSBOOK_FUZZ
+ // ignore the file name when fuzzing etc. to avoid DoS on the server
FILE *f = fopen(".passbook_fuzz_save_file","w");
#else
FILE *f = fopen(filename,"w");
@@ -425,7 +396,6 @@ int save_levelorder(const node_t *p, const char *masterpw,
static int execute(void){
char * toks[4]; /* these are pointers to start of different tokens */
const unsigned int numToks = tokenise(inst,toks,4);
- debug_printf("got %u tokens\n",numToks);
if (numToks == 0){
/* blank line */
@@ -434,6 +404,7 @@ static int execute(void){
if (strcmp(toks[0],INSTRUCTION_GET) == 0){
if (numToks != 2){
+ debug_printf("Expected 1 argument to %s instruction but instead found %u\n",INSTRUCTION_GET,numToks-1);
return -1;
}
debug_printf("Looking up: %s\n",toks[1]);
@@ -446,6 +417,7 @@ static int execute(void){
} else if (strcmp(toks[0],INSTRUCTION_REM) == 0){
if (numToks != 2){
+ debug_printf("Expected 1 argument to %s instruction but instead found %u\n",INSTRUCTION_REM,numToks-1);
return -1;
}
debug_printf("Removing: %s\n",toks[1]);
@@ -453,6 +425,7 @@ static int execute(void){
} else if (strcmp(toks[0],INSTRUCTION_PUT) == 0){
if (numToks != 4){
+ debug_printf("Expected 3 arguments to %s instruction but instead found %u\n",INSTRUCTION_PUT,numToks-1);
return -1;
}
cred_t cred;
@@ -462,17 +435,18 @@ static int execute(void){
} else if (strcmp(toks[0],INSTRUCTION_SAVE) == 0){
if (numToks != 3){
+ debug_printf("Expected 2 arguments to %s instruction but instead found %u\n",INSTRUCTION_SAVE,numToks-1);
return -1;
}
debug_printf("Saving under master password %s to file: %s\n",toks[1],toks[2]);
if (save_levelorder(map,toks[1],toks[2]) != 0){
+ debug_printf("Error saving to file %s\n",toks[2]);
return -1;
}
- debug_printf("---\n");
} else if (strcmp(toks[0],INSTRUCTION_MASTERPW) == 0){
if (numToks != 2){
- return -1;
+ debug_printf("Expected 1 argument to %s instruction but instead found %u\n",INSTRUCTION_MASTERPW,numToks-1); return -1;
}
// when fuzzing (or gathering coverage stats, etc.) don't check master pw
#ifndef PASSBOOK_FUZZ
@@ -487,12 +461,13 @@ static int execute(void){
} else if (strcmp(toks[0],INSTRUCTION_LIST) == 0){
if (numToks != 1){
+ debug_printf("Expected 0 arguments to %s instruction but instead found %u\n",INSTRUCTION_LIST,numToks-1);
return -1;
}
print_inorder(map);
}else{
- debug_printf("Unrecognised instruction\n");
+ debug_printf("Unrecognised instruction %s\n",toks[0]);
return -1;
}
@@ -502,8 +477,6 @@ static int execute(void){
/* returns >=0 on success, in which case the number of instructions executed
is returned. Returns < 0 on failure. */
static int run(FILE *f){
- debug_printf("Attempting to read program. max line length: %d\n",MAX_LINE_LENGTH);
-
assert(f != NULL);
int instructionCount = 0;