/// /// Returns the file type of a given input file. /// fn is provided so that error messages can be printed. /// hashlist::hashfile_format hashlist::identify_format(class display *ocb, const std::string &fn, FILE *handle) { char buf[MAX_STRING_LENGTH]; // Find the header if ((fgets(buf,MAX_STRING_LENGTH,handle)) == NULL) { return file_unknown; } chop_line(buf); if ( ! STRINGS_EQUAL(buf,HASHDEEP_HEADER_10)) { return file_unknown; } // Find which hashes are in this file if ((fgets(buf,MAX_STRING_LENGTH,handle)) == NULL) { return file_unknown; } chop_line(buf); // We don't use STRINGS_EQUAL here because we only care about // the first ten characters for right now. if (strncasecmp("%%%% size,",buf,10)) { return file_unknown; } /** * Remember previously loaded hashes. */ std::string previously_enabled_algorithms = last_enabled_algorithms; // Skip the "%%%% size," when parsing the list of hashes enable_hashing_algorithms_from_hashdeep_file(ocb,fn,buf + 10); // If the set of hashes now in use doesn't match those previously in use, // give a warning. if (previously_enabled_algorithms.size()>0 && previously_enabled_algorithms != last_enabled_algorithms){ if(ocb) ocb->error("%s: Hashes not in same format as previously loaded", fn.c_str()); } return file_hashdeep_10; }
/// @brief Read the next entry in a file of known hashes and convert /// it to a Filedata /// /// @param s State variable /// @param f Structure where to store the data we read /// /// @return Returns true if there is no entry to read or on error. /// Otherwise, false. bool sig_file_next(state *s, Filedata ** f) { if (NULL == s or NULL == f or NULL == s->known_handle) return true; char buffer[MAX_STR_LEN]; memset(buffer,0,MAX_STR_LEN); if (NULL == fgets(buffer,MAX_STR_LEN,s->known_handle)) return true; s->line_number++; chop_line(buffer); try { *f = new Filedata(std::string(buffer),s->known_fn); } catch (std::bad_alloc) { // This can happen on a badly formatted line, or a blank one. // We don't display errors on blank lines. if (strlen(buffer) > 0) print_error(s, "%s: Bad hash in line %llu", s->known_fn, s->line_number); return true; } return false; }
/// Open a file of known hashes and determine if it's valid /// /// @param s State variable /// @param fn filename to open /// /// @return Returns false success, true on error bool sig_file_open(state *s, const char * fn) { if (NULL == s or NULL == fn) return true; s->known_handle = fopen(fn,"rb"); if (NULL == s->known_handle) { if ( ! (MODE(mode_silent)) ) perror(fn); return true; } // The first line of the file should contain a valid ssdeep header. char buffer[MAX_STR_LEN]; if (NULL == fgets(buffer,MAX_STR_LEN,s->known_handle)) { if ( ! (MODE(mode_silent)) ) perror(fn); fclose(s->known_handle); return true; } chop_line(buffer); if (strncmp(buffer,SSDEEPV1_0_HEADER,MAX_STR_LEN) and strncmp(buffer,SSDEEPV1_1_HEADER,MAX_STR_LEN)) { if ( ! (MODE(mode_silent)) ) print_error(s,"%s: Invalid file header.", fn); fclose(s->known_handle); return true; } // We've now read the first line s->line_number = 1; s->known_fn = strdup(fn); return false; }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Read and parse syslinux config file. // // return: // 0: ok, 1: error // int read_config_file(void) { FILE *f; char *s, *t, buf[MAX_CONFIG_LINE_LEN]; unsigned u, menu_idx = 0, label_size = 0, append_size = 0; menu_t *menu_ptr = NULL, **menu_next = &menu; menu_default = calloc(1, sizeof *menu_default); if(!(f = fopen(syslinux_config_file(), "r"))) return 1; while((s = fgets(buf, sizeof buf, f))) { chop_line(s); s = skip_spaces(s); if(!*s || *s == '#') continue; t = skip_nonspaces(s); if(*t) *t++ = 0; t = skip_spaces(t); if(!strcasecmp(s, "timeout")) { timeout = atoi(t); continue; } if(!strcasecmp(s, "default")) { menu_default->label = strdup(t); u = strlen(t); if(u > label_size) label_size = u; continue; } if(!strcasecmp(s, "label")) { menu_ptr = *menu_next = calloc(1, sizeof **menu_next); menu_next = &menu_ptr->next; menu_idx++; menu_ptr->label = menu_ptr->menu_label = strdup(t); u = strlen(t); if(u > label_size) label_size = u; continue; } if(!strcasecmp(s, "kernel") && menu_ptr) { menu_ptr->kernel = strdup(t); continue; } if(!strcasecmp(s, "linux") && menu_ptr) { menu_ptr->linux = strdup(t); continue; } if(!strcasecmp(s, "localboot") && menu_ptr) { menu_ptr->localboot = strdup(t); continue; } if(!strcasecmp(s, "initrd") && menu_ptr) { menu_ptr->initrd = strdup(t); continue; } if(!strcasecmp(s, "append")) { (menu_ptr ?: menu_default)->append = strdup(t); u = strlen(t); if(u > append_size) append_size = u; continue; } if(!strcasecmp(s, "ipappend")) { (menu_ptr ?: menu_default)->ipappend = strdup(t); continue; }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Read and parse syslinux config file. // // return: // 0: ok, 1: error // int read_config_file(const char *filename) { FILE *f; char *s, *t, buf[MAX_CONFIG_LINE_LEN]; unsigned u, top_level = 0, text = 0; if(!strcmp(filename, "~")) { top_level = 1; filename = syslinux_config_file(); gfx_menu.entries = 0; gfx_menu.label_size = 0; gfx_menu.arg_size = 0; menu_ptr = NULL; menu_next = &menu; menu_default = calloc(1, sizeof *menu_default); } if(!(f = fopen(filename, "r"))) return 1; while((s = fgets(buf, sizeof buf, f))) { chop_line(s); s = skipspace(s); if(!*s || *s == '#') continue; t = skip_nonspaces(s); if(*t) *t++ = 0; t = skipspace(t); if(!strcasecmp(s, "endtext")) { text = 0; continue; } if (text) continue; if(!strcasecmp(s, "timeout")) { timeout = atoi(t); continue; } if(!strcasecmp(s, "default")) { menu_default->label = strdup(t); u = strlen(t); if(u > gfx_menu.label_size) gfx_menu.label_size = u; continue; } if(!strcasecmp(s, "label")) { menu_ptr = *menu_next = calloc(1, sizeof **menu_next); menu_next = &menu_ptr->next; gfx_menu.entries++; menu_ptr->label = menu_ptr->menu_label = strdup(t); u = strlen(t); if(u > gfx_menu.label_size) gfx_menu.label_size = u; continue; } if(!strcasecmp(s, "kernel") && menu_ptr) { menu_ptr->kernel = strdup(t); continue; } if(!strcasecmp(s, "linux") && menu_ptr) { menu_ptr->linux = strdup(t); continue; } if(!strcasecmp(s, "localboot") && menu_ptr) { menu_ptr->localboot = strdup(t); continue; } if(!strcasecmp(s, "initrd") && menu_ptr) { menu_ptr->initrd = strdup(t); continue; } if(!strcasecmp(s, "append")) { (menu_ptr ?: menu_default)->append = strdup(t); u = strlen(t); if(u > gfx_menu.arg_size) gfx_menu.arg_size = u; continue; } if(!strcasecmp(s, "ipappend")) { (menu_ptr ?: menu_default)->ipappend = strdup(t); continue; }
// // Loads a file of known hashes. // First identifies the file type, then reads the file. // hashlist::loadstatus_t hashlist::load_hash_file(display *ocb,const std::string &fn) { loadstatus_t status = loadstatus_ok; hashfile_format type; FILE *hl_handle = fopen(fn.c_str(),"rb"); if (NULL == hl_handle) { if (ocb) ocb->error("%s: %s", fn.c_str(), strerror(errno)); return status_file_error; } type = identify_format(ocb,fn,hl_handle); if (file_unknown == type) { if (ocb) ocb->error("%s: Unable to identify file format", fn.c_str()); fclose(hl_handle); hl_handle = 0; return status_unknown_filetype; } bool contains_bad_lines = false; bool record_valid; // We start our counter at line number two for the two lines // of header we've already read uint64_t line_number = 2; // TODO: Read the line directly into a std::string char line[MAX_STRING_LENGTH]; while (fgets(line,MAX_STRING_LENGTH,hl_handle)) { line_number++; // Lines starting with a pound sign are comments and can be ignored if ('#' == line[0]) continue; // C++ typically fails with a bad_alloc, but you can make it return null // http://www.cplusplus.com/reference/std/new/bad_alloc/ // http://www.cplusplus.com/reference/std/new/nothrow/ file_data_t *t = new (std::nothrow) file_data_t(); if (NULL == t) { ocb->fatal_error("%s: Out of memory in line %"PRIu64, fn.c_str(), line_number); } chop_line(line); record_valid = true; // Convert the input line to a string for easier manipulations std::string line_as_string(line); std::vector<std::string> fields = split(line_as_string,','); size_t column_number; for (column_number=0 ; column_number<fields.size() ; column_number++) { std::string word = fields[column_number]; // The first column should always be the file size if (0 == column_number) { t->file_bytes = (uint64_t)strtoll(word.c_str(),NULL,10); continue; } if (column_number == filename_column) { // If the filename contained commas, it was split // incorrectly by the 'split' statememt above. The filename // will be split across more than one column. // As such we need to 'find' everything // in the string starting with the current location. // The result should be closer to the end of the string than // the start, so we can use rfind. (This also avoids a problem // when the filename is the same as one of the hashes, which // happens now and again.) size_t start = line_as_string.rfind(word); t->file_name = line_as_string.substr(start,std::string::npos); // This should be the last column, so we break out now. break; } // All other columns should contain a valid hash in hex if ( !algorithm_t::valid_hash(hash_column[column_number],word)) { if (ocb) ocb->error("%s: Invalid %s hash in line %"PRIu64, fn.c_str(), hashes[hash_column[column_number]].name.c_str(), line_number); contains_bad_lines = true; record_valid = false; // Break out (done = true) and then process the next line break; } // Convert the hash to a std::string and save it lowercase(word); t->hash_hex[hash_column[column_number]] = word; } if (record_valid) add_fdt(t); } fclose(hl_handle); hl_handle = 0; if (contains_bad_lines) return status_contains_bad_hashes; return status; }
static Param_Type *create_param_type (char *line) { Param_Type *p; char *name, *type, *mode, *min, *max, *value, *prompt; p = (Param_Type *) _pf_malloc (sizeof (Param_Type)); if (p == NULL) return NULL; if (NULL == (p->name = _pf_create_string (line))) { goto free_and_return_error; } /* p->name is special. See comment in pf.h */ if (-1 == chop_line (line, &name, &type, &mode, &value, &min, &max, &prompt)) { goto free_and_return_error; } p->name[strlen (name)] = 0; if (type == NULL) { p->type = PF_COMMENT_TYPE; return p; } if (-1 == parse_type (type, &p->type)) { goto free_and_return_error; } if (-1 == _pf_parse_mode (mode, &p->mode)) { goto free_and_return_error; } if (min != NULL) { if (NULL == (p->min = _pf_unescape_string (min))) goto free_and_return_error; } if (max != NULL) { if (NULL == (p->max = _pf_unescape_string (max))) goto free_and_return_error; } if (value != NULL) { if (NULL == (p->value = _pf_unescape_string (value))) goto free_and_return_error; /* This is a weakness in the definition of parameter files. There * seems to be NO WAY to have a parameter whose value begins with * a ')' character. Actually, I think there is but the existing * practice seems to defeat my solution. */ if (*p->value == ')') p->flags |= PF_INDIRECT_VALUE; } if (prompt != NULL) { if (NULL == (p->prompt = _pf_unescape_string (prompt))) goto free_and_return_error; } return p; free_and_return_error: if ((p != NULL) && (p->name != NULL)) { pf_error ("Error processing parameter/line %s", p->name); } free_param_type (p); return NULL; }