/** * Main entry. */ int main(int argc, char **argv) { autofree(GError) *error = NULL; autofree(GOptionContext) *context = NULL; int ret = EXIT_FAILURE; LIBXML_TEST_VERSION context = g_option_context_new(" - cve update"); g_option_context_add_main_entries(context, _entries, NULL); if (!g_option_context_parse(context, &argc, &argv, &error)) { g_printerr("Invalid options: %s\n", error->message); goto end; } if (_show_version) { show_version(); ret = EXIT_SUCCESS; goto end; } if (update_db(_quiet)) { ret = EXIT_SUCCESS; } else { fprintf(stderr, "Failed to update database\n"); } end: xmlCleanupParser(); return ret; }
bool rpm_is_patched(struct source_package_t *pkg, char *id) { bool ret = false; /* Determine if its patched. */ autofree(gchar) *pnamet = g_ascii_strdown((gchar*)id, -1); autofree(gchar) *pname = g_strdup_printf("%s.patch", pnamet); autofree(gchar) *tpath = g_build_filename(G_DIR_SEPARATOR_S, pkg->path, pname, NULL); ret = g_file_test(tpath, G_FILE_TEST_EXISTS); return ret; }
struct source_package_t *rpm_inspect_srpm(const char *dir, const char *name, const char *version, const char *release) { struct source_package_t *t = NULL; autofree(gchar) *path = NULL; autofree(gchar) *cmdline = NULL; autofree(GError) *error = NULL; gchar **splits = NULL; int exit = 0; autofree(gchar) *output = NULL; t = calloc(1, sizeof(struct source_package_t)); if (!t) { return NULL; } path = g_strdup_printf("%s%s%s-%s-%s.src.rpm", dir, G_DIR_SEPARATOR_S, name, version, release); if (!path) { free(t); return NULL; } if (!g_file_test(path, G_FILE_TEST_EXISTS)) { printf("Required source rpm not present: %s\n", path); free(t); return NULL; } cmdline = g_strdup_printf("rpm -qp --queryformat \'[%%{PATCH}\t]\n\' %s", path); if (!cmdline) { free(t); return NULL; } if (!g_spawn_command_line_sync(cmdline, &output, NULL, &exit, &error)) { g_printerr("Unable to run command: %s\n", error->message); free(t); return NULL; } if (exit != 0) { printf("Abnormal exit code for package %s: %s\n", name, output); } splits = g_strsplit(output, "\t", -1); if (g_strv_length(splits) > 0) { t->extra = splits; } else { g_strfreev(splits); } t->name = g_strdup(name); t->version = g_strdup(version); return t; }
END_TEST START_TEST(nc_inifile_bad_test) { const char *t_path = TOP_DIR "/tests/ini/sectionless.ini"; autofree(NcHashmap) *f = NULL; f = nc_ini_file_parse(t_path); fail_if(f != NULL, "Parsed illegal sectionless INI file"); t_path = TOP_DIR "/tests/ini/empty_key.ini"; f = nc_ini_file_parse(t_path); fail_if(f != NULL, "Parsed illegal INI file with empty keys"); t_path = TOP_DIR "/tests/ini/just_assign.ini"; f = nc_ini_file_parse(t_path); fail_if(f != NULL, "Parsed illegal assign-only INI file"); t_path = TOP_DIR "/tests/ini/broken_section_start.ini"; f = nc_ini_file_parse(t_path); fail_if(f != NULL, "Parsed illegal broken-section-start INI File"); t_path = TOP_DIR "/tests/ini/broken_section_end.ini"; f = nc_ini_file_parse(t_path); fail_if(f != NULL, "Parsed illegal broken-section-end INI File"); }
static inline bool load_template(const char *tmpl_name, gchar **ret) { autofree(GError) *error = NULL; if (!g_file_get_contents(tmpl_name, ret, NULL, &error)) { g_printerr("Unable to access mandatory template: %s\n", tmpl_name); *ret = NULL; return false; } return true; }
bool srpm_is_patched(struct source_package_t *t, char *id) { if (!t->extra) { return false; } autofree(gchar) *pnamet = g_ascii_strdown((gchar*)id, -1); autofree(gchar) *pname = g_strdup_printf("%s.patch", pnamet); gchar **list = t->extra; for (uint i = 0; i < g_strv_length(list); i++) { list[i] = g_strchomp(list[i]); if (g_str_equal(list[i], "")) { continue; } if (g_str_equal(pname, list[i])) { return true; } } return false; }
bool gunzip_file(const char *path) { GFile *in = NULL, *out = NULL; autofree(gchar) *newpath = NULL; autofree(GFileInputStream) *fis = NULL; autofree(GFileOutputStream) *fos = NULL; autofree(GOutputStream) *cos = NULL; autofree(GZlibDecompressor) *conv = NULL; gsize ret; newpath = g_strdup(path); if (g_str_has_suffix(newpath, ".gz")) { newpath = str_replace(newpath, ".gz", ""); } in = g_file_new_for_path(path); out = g_file_new_for_path(newpath); fis = g_file_read(in, NULL, NULL); if (!fis) { return NULL; } fos = g_file_replace(out, NULL, FALSE, 0, NULL, NULL); if (!fos) { return NULL; } conv = g_zlib_decompressor_new(G_ZLIB_COMPRESSOR_FORMAT_GZIP); cos = g_converter_output_stream_new(G_OUTPUT_STREAM(fos), G_CONVERTER(conv)); if (!cos) { return NULL; } ret = g_output_stream_splice(cos, G_INPUT_STREAM(fis), G_OUTPUT_STREAM_SPLICE_NONE, NULL, NULL); return (ret > 0 ? true : false ); }
END_TEST START_TEST(nc_inifile_good_test) { const char *wellformed[] = { TOP_DIR "/tests/ini/wellformed.ini", TOP_DIR "/tests/ini/valid_padding.ini" }; for (size_t i = 0; i < sizeof(wellformed) / sizeof(wellformed[0]); i++) { autofree(NcHashmap) *f = NULL; char *ret = NULL; f = nc_ini_file_parse(wellformed[i]); fail_if(f == NULL, "Failed to parse wellformed.ini"); fail_if(!nc_hashmap_contains(f, "John"), "INI File missing \"John\" section"); ret = nc_hashmap_get(nc_hashmap_get(f, "John"), "alive"); fail_if(!ret, "Failed to get known value from INI file"); fail_if(!streq(ret, "true"), "Incorrect value in INI file"); fail_if(!nc_hashmap_contains(f, "Alice"), "INI File missing \"Alice\" section"); ret = nc_hashmap_get(nc_hashmap_get(f, "Alice"), "alive"); fail_if(!ret, "Failed to get known value from INI file"); fail_if(!streq(ret, "false"), "Incorrect value in INI file #2"); ret = nc_hashmap_get(nc_hashmap_get(f, "John"), "Random"); fail_if(ret, "Got unexpected key in section"); ret = nc_hashmap_get(nc_hashmap_get(f, "Bob"), "Random"); fail_if(ret, "Got unexpected section"); } }
bool write_report(CveCheckTool *self, char *filename) { autofree(gchar) *bottom, *package, *top; autofree(GError) *error = NULL; bottom = package = top = NULL; autofree(GHashTable) *macros = NULL; autofree(gchar) *aff = NULL; autofree(gchar) *output = NULL; autofree(gchar) *body = NULL; GHashTableIter iter; gchar *key = NULL; struct source_package_t *v = NULL; GList *c = NULL; struct cve_entry_t *c_entry = NULL; gint affected = 0; guint row = 0; /* Mandatory template files */ LOAD_TEMPLATE(TMPL_BOTTOM, &bottom); LOAD_TEMPLATE(TMPL_PACKAGE, &package); LOAD_TEMPLATE(TMPL_TOP, &top); macros = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL); g_hash_table_insert(macros, "LNVD_CVE_URI", NVD_CVE_URI); g_hash_table_iter_init(&iter, self->db); while (g_hash_table_iter_next(&iter, (void**)&key, (void**)&v)) { bool hit = false; if (!v->issues && !v->patched && !self->show_unaffected) { continue; } if (!v->issues && self->hide_patched) { continue; } guint cve_len = 0; if (v->issues) { cve_len += g_list_length(v->issues); } if (v->patched && !self->hide_patched) { cve_len += g_list_length(v->patched); } g_hash_table_insert(macros, "PACKAGE_NAME", key); /* TODO: Collapse redundancy into helper. */ g_hash_table_insert(macros, "STATUS_CLASS", "not-patched"); g_hash_table_insert(macros, "STATUS_STRING", "Check"); for (c = v->issues; c; c = c->next) { autofree(gchar) *ent = NULL; c_entry = g_hash_table_lookup(self->cdb, (gchar*)c->data); if (self->modified > 0 && c_entry->modified > self->modified) { continue; } hit = true; g_hash_table_insert(macros, "LCVEID", c_entry->id); g_hash_table_insert(macros, "CVEID", c_entry->id); g_hash_table_insert(macros, "DESC", c_entry->summary); g_hash_table_insert(macros, "ROW_CLASS", row % 2 ? "even" : "odd"); g_hash_table_insert(macros, "SCORE", c_entry->score); /* TODO: Add links .. */ ent = g_strdup(package); ent = dotemplate(macros, ent); if (body) { body = _concat(body, ent); } else { body = g_strdup(ent); } ++row; } g_hash_table_insert(macros, "STATUS_CLASS", "patched"); g_hash_table_insert(macros, "STATUS_STRING", "Patched"); if (!self->hide_patched && v->patched) { for (c = v->patched; c; c = c->next) { autofree(gchar) *ent = NULL; c_entry = g_hash_table_lookup(self->cdb, (gchar*)c->data); if (self->modified > 0 && c_entry->modified > self->modified) { continue; } hit = true; g_hash_table_insert(macros, "LCVEID", c_entry->id); g_hash_table_insert(macros, "CVEID", c_entry->id); g_hash_table_insert(macros, "DESC", c_entry->summary); g_hash_table_insert(macros, "ROW_CLASS", row % 2 ? "even" : "odd"); g_hash_table_insert(macros, "SCORE", c_entry->score); /* TODO: Add links .. */ ent = g_strdup(package); ent = dotemplate(macros, ent); if (body) { body = _concat(body, ent); } else { body = g_strdup(ent); } ++row; } } if (hit) { ++affected; } } aff = g_strdup_printf("CVE Report for %d package%s", affected, affected > 1 ? "s" : ""); g_hash_table_insert(macros, "AFFECTED_STRING", aff); top = dotemplate(macros, top); output = g_strdup(top); output = _concat(output, body); output = _concat(output, bottom); /* Write file */ if (!g_file_set_contents(filename, output, -1, &error)) { g_printerr("Unable to write report: %s\n", error->message); return false; } return true; }
static char *cnvformat( void ) { // フォーマット付き文字列を作成する // #if ( WIN32 || _WIN32 ) && ! __CYGWIN__ #define SNPRINTF _snprintf #else #define SNPRINTF snprintf #endif char fstr[1024]; char *fp; int capacity; int len; char *p; strncpy( fstr, code_gets(), sizeof fstr ); fstr[sizeof(fstr)-1] = '\0'; fp = fstr; capacity = 1024; p = sbAlloc(capacity); len = 0; CAutoSbFree autofree(&p); while (1) { char fmt[32]; int i; int val_type; void *val_ptr; // '%' までをコピー i = 0; while( fp[i] != '\0' && fp[i] != '%' ) { i ++; } cnvformat_expand( &p, &capacity, len, i ); memcpy( p + len, fp, i ); len += i; fp += i; if ( *fp == '\0' ) break; // 変換指定を読み fmt にコピー i = (int)strspn( fp + 1, " #+-.0123456789" ) + 1; strncpy( fmt, fp, sizeof fmt ); fmt[sizeof(fmt)-1] = '\0'; if ( i + 1 < (int)(sizeof fmt) ) fmt[i+1] = '\0'; fp += i; char specifier = *fp; fp ++; #if ( WIN32 || _WIN32 ) && ! __CYGWIN__ if ( specifier == 'I' ) { // I64 prefix対応(VC++のみ) if ((fp[0]=='6')&&(fp[1]='4')) { memcpy( fmt+i+1, fp, 3 ); fmt[i+4] = 0; specifier = 'f'; fp += 3; } } #endif if ( specifier == '\0' ) break; if ( specifier == '%' ) { cnvformat_expand( &p, &capacity, len, 1 ); p[len++] = '%'; continue; } // 引数を取得 if ( code_get() <= PARAM_END ) throw HSPERR_INVALID_FUNCPARAM; switch (specifier) { case 'd': case 'i': case 'c': case 'o': case 'x': case 'X': case 'u': case 'p': val_type = HSPVAR_FLAG_INT; val_ptr = HspVarCoreCnvPtr( mpval, HSPVAR_FLAG_INT ); break; case 'f': case 'e': case 'E': case 'g': case 'G': val_type = HSPVAR_FLAG_DOUBLE; val_ptr = HspVarCoreCnvPtr( mpval, HSPVAR_FLAG_DOUBLE ); break; case 's': val_type = HSPVAR_FLAG_STR; val_ptr = HspVarCoreCnvPtr( mpval, HSPVAR_FLAG_STR ); break; default: throw HSPERR_INVALID_FUNCPARAM; } // snprintf が成功するまでバッファを広げていき、変換を行う while (1) { int n; int space = capacity - len - 1; if ( val_type == HSPVAR_FLAG_INT ) { n = SNPRINTF( p + len, space, fmt, *(int *)val_ptr ); } else if ( val_type == HSPVAR_FLAG_DOUBLE ) { n = SNPRINTF( p + len, space, fmt, *(HSPREAL *)val_ptr ); } else { n = SNPRINTF( p + len, space, fmt, (char *)val_ptr ); } if ( n >= 0 && n < space ) { len += n; break; } if ( n >= 0 ) { space = n + 1; } else { space *= 2; if ( space < 32 ) space = 32; } cnvformat_expand( &p, &capacity, len, space ); } } p[len] = '\0'; char *result = code_stmp(len + 1); strcpy(result, p); return result; }
/** * A simple JIRA plugin client for development purposes only. */ int main(int argc, char **argv) { int opt,test_case = -1; bool verbose_flag = false; gchar *jira_cfg_path = "jira.cfg"; gchar *json_path = NULL; autofree(gchar) *jira_issues_json = NULL; autofree(gchar) *jira_json = NULL; autofree(gchar) *summary = NULL; autofree(gchar) *description = g_strdup("This is just a test. Ignore"); GHashTable *jira_issues = NULL; GSList *jira_issues_list = NULL; time_t now = time(NULL); while ((opt = getopt(argc,argv,"c:ht:V")) != -1) switch(opt) { case 'c': jira_cfg_path = argv[optind-1]; break; case 't': test_case = atoi(argv[optind-1]); break; case 'V': verbose_flag = true; break; case 'h': show_usage(argv[0]); return 0; } if (test_case < 0) { show_usage(argv[0]); return -1; } printf("\n[Execute: test case %i using %s]\n\n", test_case, jira_cfg_path); if (!init_jira_plugin(NULL, jira_cfg_path)) return 1; set_verbose(verbose_flag); switch(test_case) { /* Check if JIRA server is responsive */ case 1: if (!is_jira_alive()) goto cleanup; break; /* Do a simple query */ case 2: if (!is_jira_alive()) goto cleanup; if (!build_search_jira_issues(&jira_json)) goto cleanup; if (!search_jira_issues(jira_json, &jira_issues_json)) goto cleanup; if (!parse_jira_issues(jira_issues_json, &jira_issues_list)) goto cleanup; show_jira_issues_list(jira_issues_list); if (!save_jira_issues_csv( jira_issues_list,"jira_test2_results.csv")) goto cleanup; if (!save_jira_issues_xml(jira_issues_list, "jira_test2_results.xml")) goto cleanup; if (!save(jira_json, "jira_test2_json.txt")) goto cleanup; if (!save(jira_issues_json, "jira_test2_issues_json.txt")) goto cleanup; free_jira_issues_list(&jira_issues_list); break; /* Add a new JIRA issue */ case 3: if (!is_jira_alive()) goto cleanup; summary = g_strdup_printf("CVE-%s (Test:3)", g_strstrip(ctime(&now))); if (!build_new_jira_issue(summary, description, false, &jira_json)) goto cleanup; printf("Adding new JIRA issue: [%s]\n", summary); if (!add_new_jira_issue(jira_json)) goto cleanup; g_free(jira_json); if (!build_search_jira_issues(&jira_json)) goto cleanup; if (!search_jira_issues(jira_json, &jira_issues_json)) goto cleanup; if (!parse_jira_issues(jira_issues_json, &jira_issues_list)) goto cleanup; show_jira_issues_list(jira_issues_list); if (!save_jira_issues_csv( jira_issues_list,"jira_test3_results_add.csv")) goto cleanup; if (!save_jira_issues_xml( jira_issues_list,"jira_test3_results_add.xml")) goto cleanup; free_jira_issues_list(&jira_issues_list); break; /* Add a new issue using a self-generated template */ case 4: summary = g_strdup_printf("CVE-%s (Test:4)", g_strstrip(ctime(&now))); if (!build_new_jira_issue(NULL, NULL, true, &jira_json)) goto cleanup; json_path = "jira_test4_results_template_raw.json"; if (!save(jira_json, json_path)) goto cleanup; g_free(jira_json); if (!build_new_jira_issue_file( json_path, summary, description, &jira_json)) goto cleanup; json_path = "jira_test4_results_template_resolved.json"; if (!save(jira_json, json_path)) goto cleanup; if (!add_new_jira_issue(jira_json)) goto cleanup; g_free(jira_json); if (!build_search_jira_issues(&jira_json)) goto cleanup; if (!search_jira_issues(jira_json, &jira_issues_json)) goto cleanup; if (!parse_jira_issues(jira_issues_json, &jira_issues_list)) goto cleanup; show_jira_issues_list(jira_issues_list); if (!save_jira_issues_csv( jira_issues_list,"jira_test4_results_add.csv")) goto cleanup; if (!save_jira_issues_xml( jira_issues_list,"jira_test4_results_add.xml")) goto cleanup; free_jira_issues_list(&jira_issues_list); break; case 5: summary = g_strdup_printf("CVE-%s (Test:5)", g_strstrip(ctime(&now))); if (!build_search_jira_issues(&jira_json)) { return false; } if (!get_jira_issues(jira_json, &jira_issues)) { return false; } show_jira_issues(jira_issues); free_jira_issues(&jira_issues); break; default: show_usage(argv[0]); printf("Error: Unknown test case: %i\n", test_case); break; } printf("Test passed!\n\n"); destroy_jira_plugin(); return 0; cleanup: printf("Test failed!\n\n"); destroy_jira_plugin(); return 1; }
struct source_package_t *rpm_inspect_spec(const char *filename) { struct source_package_t *t = NULL; autofree(GFile) *fi = g_file_new_for_path(filename); autofree(GError) *error = NULL; if (!fi) { return NULL; } autofree(GFileInputStream) *fis = g_file_read(fi, NULL, &error); if (error) { g_printerr("Unable to read: %s\n", error->message); return NULL; } autofree(GDataInputStream) *dis = g_data_input_stream_new(G_INPUT_STREAM(fis)); char *read = NULL; autofree(gchar) *name = NULL; autofree(gchar) *version = NULL; autofree(gchar) *release = NULL; autofree(GHashTable) *macros = NULL; autofree(gchar) *fpath = NULL; while ((read = g_data_input_stream_read_line(dis, NULL, NULL, NULL)) != NULL) { autofree(gstrv) *strv = NULL; const gchar *key = NULL; autofree(gchar) *value = NULL; read = g_strstrip(read); if (g_str_has_prefix(read, "%define") || g_str_has_prefix(read, "%global")) { strv = g_strsplit(read, " ", 3); if (g_strv_length(strv) != 3) { goto clean; } gchar *mkey = g_strstrip(g_strdup_printf("%%{%s}", strv[1])); gchar *mvalue = g_strstrip(g_strdup(strv[2])); if (!macros) { macros = g_hash_table_new_full(g_str_hash, g_str_equal, &g_free, &g_free); } if (!g_hash_table_contains(macros, mkey)) { g_hash_table_insert(macros, mkey, mvalue); } else { g_free(mkey); g_free(mvalue); } goto clean; } if (!strchr(read, ':')) { goto clean; } strv = g_strsplit(read, ":", -1); if (g_strv_length(strv) < 2) { goto clean; } key = g_strstrip(strv[0]); value = g_strjoinv(":", strv+1); value = g_strstrip(value); if (g_str_equal(key, "Name")) { name = g_strdup(value); } else if (g_str_equal(key, "Version")) { version = g_strdup(value); } else if (g_str_equal(key, "Release")) { release = g_strdup(value); } if (name && version && release) { g_free(read); break; } clean: g_free(read); } if (!name || !version || !release) { return NULL; } fpath = g_path_get_dirname(filename); if (!fpath) { return NULL; } if (macros) { name = demacro(macros, name); version = demacro(macros, version); release = demacro(macros, release); } t = calloc(1, sizeof(struct source_package_t)); if (!t) { return NULL; } t->name = g_strdup(name); t->version = g_strdup(version); t->release = atoi(release); t->path = get_absolute_path(fpath); return t; }