From 56c29066a72eaeb7e84a28aedc597f13f419359e Mon Sep 17 00:00:00 2001 From: lace <> Date: Mon, 26 Dec 2005 14:21:19 +0000 Subject: [PATCH] Force 'captivemodid' checking during any W32 module loading. --- src/client/cmdline/Makefile.am | 4 +- src/client/fuse/Makefile.am | 5 +- src/client/fuse/main.c | 9 +- src/client/sandbox-server/Makefile.am | 4 +- src/install/acquire/Makefile.am | 1 - src/install/acquire/cabinet.c | 2 +- src/install/acquire/main.c | 9 +- src/install/acquire/main.h | 2 + src/install/acquire/moduriload.c | 10 +- src/install/acquire/ui-line.c | 3 +- src/libcaptive/captivemodid/captivemodid.c | 251 +++++++++++++++++--------- src/libcaptive/client/options-module.c | 27 +++ src/libcaptive/client/options.c | 25 +++ src/libcaptive/include/captive/captivemodid.h | 32 +++- src/libcaptive/include/captive/options.h | 3 + 15 files changed, 278 insertions(+), 109 deletions(-) diff --git a/src/client/cmdline/Makefile.am b/src/client/cmdline/Makefile.am index b456c70..72b5053 100644 --- a/src/client/cmdline/Makefile.am +++ b/src/client/cmdline/Makefile.am @@ -63,8 +63,8 @@ captive_cmdline_SOURCES= \ main.h \ utf8.c \ utf8.h -captive_cmdline_CFLAGS= $(GNOME_VFS_CFLAGS) -captive_cmdline_LDADD =$(captive_library) $(GNOME_VFS_LIBS) $(READLINE_LIBS) $(INTLLIBS) +captive_cmdline_CFLAGS= $(GNOME_VFS_CFLAGS) $(LIBXML_CFLAGS) +captive_cmdline_LDADD =$(captive_library) $(GNOME_VFS_LIBS) $(LIBXML_LIBS) $(READLINE_LIBS) $(INTLLIBS) captive_cmdline_LDFLAGS=$(READLINE_LDFLAGS) bin_PROGRAMS+=captive-cmdline diff --git a/src/client/fuse/Makefile.am b/src/client/fuse/Makefile.am index 9d673c3..30de43f 100644 --- a/src/client/fuse/Makefile.am +++ b/src/client/fuse/Makefile.am @@ -64,13 +64,14 @@ mount_captive_SOURCES= \ gnomevfsfileinfo.h \ main.c \ main.h -mount_captive_CFLAGS= $(GNOME_VFS_CFLAGS) $(FUSE_CFLAGS) -mount_captive_LDADD =$(captive_library) $(GNOME_VFS_LIBS) $(FUSE_LIBS) $(INTLLIBS) +mount_captive_CFLAGS= $(GNOME_VFS_CFLAGS) $(LIBXML_CFLAGS) $(FUSE_CFLAGS) +mount_captive_LDADD =$(captive_library) $(GNOME_VFS_LIBS) $(LIBXML_LIBS) $(FUSE_LIBS) $(INTLLIBS) mount_captive_LDFLAGS=$(READLINE_LDFLAGS) mount_captive_CFLAGS+=-DLIBEXECDIR="$(libexecdir)" mount_captive_CFLAGS+=-DVARLIBCAPTIVEDIR="$(localstatedir)/lib/$(PACKAGE)" + if ENABLE_FUSE if ENABLE_SBIN_MOUNT mount_captive_cond=mount.captive diff --git a/src/client/fuse/main.c b/src/client/fuse/main.c index 0935914..b805c71 100644 --- a/src/client/fuse/main.c +++ b/src/client/fuse/main.c @@ -29,6 +29,7 @@ #include #include #include +#include #include "main.h" /* self */ #include "op_statfs.h" @@ -175,8 +176,6 @@ const char *image_filename; for (csp=rest_argv,rest_argc=0;csp && *csp;csp++) rest_argc++; - captive_options=NULL; /* already parsed by 'CAPTIVE_POPT_INCLUDE' */ - /* Override the (default) Captive options with mount(8) supplied "-o" argument. */ /* rest_argv[0] is the device now. */ /* rest_argv[1] is the mountpoint now. */ @@ -211,6 +210,9 @@ const char *cs=rest_argv[3]; g_error(_("image_iochannel failed open of: %s"),image_filename); return EXIT_FAILURE; } + + if (!options.captivemodid) + options.captivemodid=captive_captivemodid_load_default(FALSE); if (options.filesystem.type==CAPTIVE_OPTIONS_MODULE_TYPE_EMPTY) { const char *self_prefix="mount.captive-"; @@ -239,6 +241,9 @@ struct captive_options_module *options_module; options.load_module=g_list_append(options.load_module,options_module); } + /* It is still required for: captive_options_module_load() */ + captive_options=NULL; /* already parsed by 'CAPTIVE_POPT_INCLUDE' */ + if (GNOME_VFS_OK!=captive_vfs_new(&capfuse_captive_vfs_object,&options)) { g_error(_("captive_vfs_new() failed")); return EXIT_FAILURE; diff --git a/src/client/sandbox-server/Makefile.am b/src/client/sandbox-server/Makefile.am index f38f296..ac952a9 100644 --- a/src/client/sandbox-server/Makefile.am +++ b/src/client/sandbox-server/Makefile.am @@ -20,8 +20,8 @@ include $(top_srcdir)/Makefile-head.am captive_sandbox_server_SOURCES= \ main.c -captive_sandbox_server_CFLAGS=$(ORBIT_CFLAGS) $(LINC_CFLAGS) -captive_sandbox_server_LDADD =$(ORBIT_LIBS) $(LINC_LIBS) $(captive_library) $(INTLLIBS) +captive_sandbox_server_CFLAGS=$(ORBIT_CFLAGS) $(LINC_CFLAGS) $(GNOME_VFS_CFLAGS) $(LIBXML_CFLAGS) +captive_sandbox_server_LDADD =$(ORBIT_LIBS) $(LINC_LIBS) $(GNOME_VFS_LIBS) $(LIBXML_LIBS) $(captive_library) $(INTLLIBS) libexec_PROGRAMS=captive-sandbox-server libexecPROGRAMS_INSTALL=${INSTALL} -o root -g root -m 4755 EXTRA_DIST+=.gdbinit diff --git a/src/install/acquire/Makefile.am b/src/install/acquire/Makefile.am index 4e0f4bc..d306a28 100644 --- a/src/install/acquire/Makefile.am +++ b/src/install/acquire/Makefile.am @@ -99,7 +99,6 @@ captive_install_acquire_LDFLAGS=$(READLINE_LDFLAGS) captive_install_acquire_CFLAGS+=$(GNOMEUI_CFLAGS) captive_install_acquire_LDADD +=$(GNOMEUI_LIBS) -captive_install_acquire_CFLAGS+=-DSYSCONFDIR="$(sysconfdir)" captive_install_acquire_CFLAGS+=-DVARLIBCAPTIVEDIR="$(localstatedir)/lib/$(PACKAGE)" captive_install_acquire_LDADD+=../libcaptive-install/libcaptive-install.a diff --git a/src/install/acquire/cabinet.c b/src/install/acquire/cabinet.c index fd6263b..3ad56c7 100644 --- a/src/install/acquire/cabinet.c +++ b/src/install/acquire/cabinet.c @@ -400,7 +400,7 @@ gpointer file_buffer; GnomeVFSURI *uri_fi; int errint; - if (!captive_captivemodid_module_length_is_valid(fi->length)) + if (!captive_captivemodid_module_length_is_valid(captivemodid,fi->length)) continue; uri_fi=gnome_vfs_uri_append_file_name(acquire_cabinet->uri,fi->filename); diff --git a/src/install/acquire/main.c b/src/install/acquire/main.c index a8a2eba..260e821 100644 --- a/src/install/acquire/main.c +++ b/src/install/acquire/main.c @@ -43,15 +43,17 @@ #include #include +#include +CaptiveCaptivemodidObject *captivemodid; + int optarg_verbose; int optarg_dry; static int optarg_microsoft_com; static int optarg_scan_disks; static int optarg_scan_disks_quick; static int optarg_text; -static char *optarg_modid_path=G_STRINGIFY(SYSCONFDIR) "/w32-mod-id.captivemodid.xml"; static GList *optarg_scan_path_list; /* of (char *) */ static void acquire_popt_callback @@ -75,8 +77,6 @@ static const struct poptOption popt_table[]={ N_("Disable Gnome UI; --text must be first argument"),NULL), BUG_ACQUIRE_POPT('v',"verbose" ,POPT_ARG_NONE ,&optarg_verbose,0,N_("Display additional debug information"),NULL), BUG_ACQUIRE_POPT('n',"dry" ,POPT_ARG_NONE ,&optarg_dry ,0,N_("No modifications, no files written"),NULL), - BUG_ACQUIRE_POPT(0 ,"modid-path" ,POPT_ARG_STRING|POPT_ARGFLAG_SHOW_DEFAULT,&optarg_modid_path,0, - N_("Path to .captivemodid.xml database"),N_("path")), BUG_ACQUIRE_POPT(0 ,"scan-disks" ,POPT_ARG_NONE ,&optarg_scan_disks,0,N_("Scan all files on local disks"),NULL), BUG_ACQUIRE_POPT(0 ,"scan-disks-quick",POPT_ARG_NONE ,&optarg_scan_disks_quick,0, N_("Scan MS-Windows directories on local disks"),NULL), @@ -280,8 +280,7 @@ guint handler_id; && !ui_line_init()) g_error(_("No UI interface could be initialized")); - if (!captive_captivemodid_load(optarg_modid_path) && !captive_captivemodid_load("./w32-mod-id.captivemodid.xml")) - g_error(_("Unable to load modid database: %s"),optarg_modid_path); + captivemodid=captive_captivemodid_load_default(TRUE); mod_uri_load_base_reporting(gnome_vfs_uri_new("file://" G_STRINGIFY(VARLIBCAPTIVEDIR))); diff --git a/src/install/acquire/main.h b/src/install/acquire/main.h index 7c11693..ea221b7 100644 --- a/src/install/acquire/main.h +++ b/src/install/acquire/main.h @@ -23,10 +23,12 @@ #include #include +#include G_BEGIN_DECLS +extern CaptiveCaptivemodidObject *captivemodid; extern gboolean optarg_verbose; extern gboolean optarg_dry; extern void (*ui_interactive)(void); diff --git a/src/install/acquire/moduriload.c b/src/install/acquire/moduriload.c index 4500716..dbc86fe 100644 --- a/src/install/acquire/moduriload.c +++ b/src/install/acquire/moduriload.c @@ -109,10 +109,10 @@ int dest_fd; all_modules_found=FALSE; - best_priority=captive_captivemodid_module_type_best_priority_lookup(module->type); + best_priority=captive_captivemodid_module_type_best_priority_lookup(captivemodid,module->type); if (best_priority==G_MININT /* no longer seeking for such module */ || module_available->module->priority==best_priority) { - if (captive_captivemodid_module_type_best_priority_found(module->type)) { + if (captive_captivemodid_module_type_best_priority_found(captivemodid,module->type)) { /* Postpone (*acquire_module_all_modules_found_notify)() * after (*acquire_module_available_notify)(). */ @@ -139,7 +139,7 @@ struct captive_captivemodid_module *module; return; file_md5=captive_calc_md5(file_base,file_length); - if (!(module=captive_captivemodid_module_md5_lookup(file_md5))) + if (!(module=captive_captivemodid_module_md5_lookup(captivemodid,file_md5))) goto fail_free_file_md5; if (strcmp("cabinet",(const char *)module->type)) @@ -239,14 +239,14 @@ GnomeVFSHandle *handle; errvfsresult=GNOME_VFS_ERROR_WRONG_FORMAT; goto fail_file_info_local_clear; } - if (!captive_captivemodid_module_length_is_valid(file_info_local.size)) { + if (!captive_captivemodid_module_length_is_valid(captivemodid,file_info_local.size)) { errvfsresult=GNOME_VFS_ERROR_WRONG_FORMAT; goto fail_file_info_local_clear; } if (file_info_local.size<=MAX_FILE_LOAD_LENGTH) mod_uri_load_file_handle_to_memory(handle,&file_info_local,uri); else { -gint cabinet_used=captive_captivemodid_cabinet_length_to_used(file_info_local.size); +gint cabinet_used=captive_captivemodid_cabinet_length_to_used(captivemodid,file_info_local.size); mod_uri_load_file_handle_remote_cabinet(&handle,&file_info_local,uri,cabinet_used); } diff --git a/src/install/acquire/ui-line.c b/src/install/acquire/ui-line.c index 999a1ec..1177fb1 100644 --- a/src/install/acquire/ui-line.c +++ b/src/install/acquire/ui-line.c @@ -44,7 +44,8 @@ gint priority_best; g_return_if_fail(module_available!=NULL); g_return_if_fail(module_available->module!=NULL); - if (G_MININT==(priority_best=captive_captivemodid_module_type_best_priority_lookup(module_available->module->type))) + if (G_MININT==(priority_best=captive_captivemodid_module_type_best_priority_lookup( + captivemodid,module_available->module->type))) printf(_("Found best available \"%s\": %s\n"),module_available->module->type,module_available->module->id); else printf(_("Found although not best \"%s\" (pri=%d; best=%d): %s\n"), diff --git a/src/libcaptive/captivemodid/captivemodid.c b/src/libcaptive/captivemodid/captivemodid.c index 8aceea4..3344896 100644 --- a/src/libcaptive/captivemodid/captivemodid.c +++ b/src/libcaptive/captivemodid/captivemodid.c @@ -35,141 +35,172 @@ #include -gchar *captive_calc_md5(gconstpointer base,size_t length) +struct _CaptiveCaptivemodidObject { + GObject parent_instance; + + /* map: GINT_TO_POINTER(captive_captivemodid_module.length) -> !=NULL */ + /* No allocations needed. */ + GHashTable *module_valid_length_hash; + + /* map: (const xmlChar *)md5 -> (struct captive_captivemodid_module *) */ + /* 'key' is not allocated it is shared with: 'val'->md5 */ + /* 'val' is allocated, to be automatically freed by: captive_captivemodid_module_free() */ + GHashTable *module_md5_hash; + + /* map: (const xmlChar *)type -> (gpointer)GINT_TO_POINTER(priority) */ + /* We remove entry for module with already the best priority found, + * therefore captive_captivemodid_module_type_best_priority_lookup() will return + * 'G_MININT' afterwards. + * 'key' is not allocated - it is shared with: module_md5_hash */ + /* No allocations needed. */ + GHashTable *module_type_best_priority_hash; + + /* g_strdup()ped */ + gchar *pathname_loaded; + }; +struct _CaptiveCaptivemodidObjectClass { + GObjectClass parent_class; + }; + + +static gpointer captive_captivemodid_object_parent_class=NULL; + + +static void captive_captivemodid_object_finalize(CaptiveCaptivemodidObject *captive_captivemodid_object) { -unsigned char md5_bin[1+128/8]; /* 128 bits==16 bytes; '1+' for leading stub to prevent shorter output of BN_bn2hex() */ -BIGNUM *bignum; -char *hex; -gchar *r,*gs; + g_return_if_fail(captive_captivemodid_object!=NULL); - /* already done above */ - /* Calculate MD5 sum and convert it to hex string: */ - MD5(base,length,md5_bin+1); - md5_bin[0]=0xFF; /* stub to prevent shorter output of BN_bn2hex() */ - bignum=BN_bin2bn(md5_bin,1+128/8,NULL); - hex=BN_bn2hex(bignum); - g_assert(strlen(hex)==2*(1+128/8)); - r=g_strdup(hex+2); - OPENSSL_free(hex); - BN_free(bignum); + g_hash_table_destroy(captive_captivemodid_object->module_valid_length_hash); + g_hash_table_destroy(captive_captivemodid_object->module_md5_hash); + g_hash_table_destroy(captive_captivemodid_object->module_type_best_priority_hash); + g_free(captive_captivemodid_object->pathname_loaded); - g_assert(strlen(r)==32); - for (gs=r;*gs;gs++) { - g_assert(isxdigit(*gs)); - *gs=tolower(*gs); - g_assert(isxdigit(*gs)); - } - return r; + G_OBJECT_CLASS(captive_captivemodid_object_parent_class)->finalize((GObject *)captive_captivemodid_object); } -/* map: GINT_TO_POINTER(captive_captivemodid_module.length) -> !=NULL */ -static GHashTable *module_valid_length_hash; - -static void module_valid_length_hash_init(void) +static void captive_captivemodid_object_class_init(CaptiveCaptivemodidObjectClass *class) { - if (module_valid_length_hash) - return; - module_valid_length_hash=g_hash_table_new(g_direct_hash,g_direct_equal); +GObjectClass *gobject_class=G_OBJECT_CLASS(class); + + captive_captivemodid_object_parent_class=g_type_class_ref(g_type_parent(G_TYPE_FROM_CLASS(class))); + gobject_class->finalize=(void (*)(GObject *object))captive_captivemodid_object_finalize; } -/* map: (const xmlChar *)md5 -> (struct captive_captivemodid_module *) */ -static GHashTable *module_md5_hash; -static void module_md5_hash_init(void) +static void captive_captivemodid_module_free(struct captive_captivemodid_module *module) { - if (module_md5_hash) - return; - module_md5_hash=g_hash_table_new(g_str_hash,g_str_equal); + xmlFree((xmlChar *)module->type); + xmlFree((xmlChar *)module->md5); + xmlFree((xmlChar *)module->id); + g_free(module); } -/* map: (const xmlChar *)type -> (gpointer)GINT_TO_POINTER(priority) */ -/* We remove entry for module with already the best priority found, - * therefore captive_captivemodid_module_type_best_priority_lookup() will return - * 'G_MININT' afterwards. - */ -static GHashTable *module_type_best_priority_hash; +static void captive_captivemodid_object_init(CaptiveCaptivemodidObject *captive_captivemodid_object) +{ + captive_captivemodid_object->module_valid_length_hash=g_hash_table_new(g_direct_hash,g_direct_equal); + captive_captivemodid_object->module_md5_hash=g_hash_table_new_full(g_str_hash,g_str_equal, + NULL, /* key_destroy_func */ + (GDestroyNotify)captive_captivemodid_module_free); /* value_destroy_func */ + captive_captivemodid_object->module_type_best_priority_hash=g_hash_table_new(g_str_hash,g_str_equal); +} -static void module_type_best_priority_hash_init(void) + +GType captive_captivemodid_object_get_type(void) { - if (module_type_best_priority_hash) - return; - module_type_best_priority_hash=g_hash_table_new(g_str_hash,g_str_equal); +static GType captive_captivemodid_object_type=0; + + if (!captive_captivemodid_object_type) { +static const GTypeInfo captive_captivemodid_object_info={ + sizeof(CaptiveCaptivemodidObjectClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc)captive_captivemodid_object_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof(CaptiveCaptivemodidObject), + 5, /* n_preallocs */ + (GInstanceInitFunc)captive_captivemodid_object_init, + }; + + captive_captivemodid_object_type=g_type_register_static(G_TYPE_OBJECT, + "CaptiveCaptivemodidObject",&captive_captivemodid_object_info,0); + } + + return captive_captivemodid_object_type; } -static void captive_captivemodid_load_module(struct captive_captivemodid_module *module) + +static void captive_captivemodid_load_module + (CaptiveCaptivemodidObject *captivemodid,struct captive_captivemodid_module *module) { struct captive_captivemodid_module *module_md5_conflict; gpointer valid_length_value_gpointer; - module_md5_hash_init(); - if ((module_md5_conflict=g_hash_table_lookup(module_md5_hash,module->md5))) { + if ((module_md5_conflict=g_hash_table_lookup(captivemodid->module_md5_hash,module->md5))) { g_warning(_("Ignoring module \"%s\" as it has MD5 conflict with: %s"), module->id,module_md5_conflict->id); return; } - g_hash_table_insert(module_md5_hash,(/* de-const */ xmlChar *)module->md5,module); + g_hash_table_insert(captivemodid->module_md5_hash,(/* de-const */ xmlChar *)module->md5,module); - module_valid_length_hash_init(); - if (!g_hash_table_lookup_extended(module_valid_length_hash,GINT_TO_POINTER(module->length), + if (!g_hash_table_lookup_extended(captivemodid->module_valid_length_hash,GINT_TO_POINTER(module->length), NULL, /* orig_key */ &valid_length_value_gpointer)) /* value */ - g_hash_table_insert(module_valid_length_hash,GINT_TO_POINTER(module->length),GINT_TO_POINTER(module->cabinet_used)); + g_hash_table_insert(captivemodid->module_valid_length_hash, + GINT_TO_POINTER(module->length),GINT_TO_POINTER(module->cabinet_used)); else { /* Conflicting 'cabinet_used' values for single 'cabinet size'? */ if (valid_length_value_gpointer && GPOINTER_TO_INT(valid_length_value_gpointer)!=module->cabinet_used) - g_hash_table_insert(module_valid_length_hash,GINT_TO_POINTER(module->length),NULL); + g_hash_table_insert(captivemodid->module_valid_length_hash,GINT_TO_POINTER(module->length),NULL); } if (strcmp((const char *)module->type,"cabinet")) { - if (module->priority>captive_captivemodid_module_type_best_priority_lookup(module->type)) { - module_type_best_priority_hash_init(); - g_hash_table_insert(module_type_best_priority_hash, + if (module->priority>captive_captivemodid_module_type_best_priority_lookup(captivemodid,module->type)) { + g_hash_table_insert(captivemodid->module_type_best_priority_hash, (/* de-const */ xmlChar *)module->type,GINT_TO_POINTER(module->priority)); } } } -gboolean captive_captivemodid_module_length_is_valid(GnomeVFSFileSize file_size) +gboolean captive_captivemodid_module_length_is_valid(CaptiveCaptivemodidObject *captivemodid,GnomeVFSFileSize file_size) { gint file_size_gint; if ((GnomeVFSFileSize)(file_size_gint=file_size)!=file_size) /* Size too big to be valid. */ return FALSE; - module_valid_length_hash_init(); - return g_hash_table_lookup_extended(module_valid_length_hash,GINT_TO_POINTER(file_size_gint), + return g_hash_table_lookup_extended(captivemodid->module_valid_length_hash,GINT_TO_POINTER(file_size_gint), NULL, /* orig_key */ NULL); /* value */ } -gint captive_captivemodid_cabinet_length_to_used(gint cabinet_length) +gint captive_captivemodid_cabinet_length_to_used(CaptiveCaptivemodidObject *captivemodid,gint cabinet_length) { gpointer valid_length_value_gpointer; - if (!g_hash_table_lookup_extended(module_valid_length_hash,GINT_TO_POINTER(cabinet_length), + if (!g_hash_table_lookup_extended(captivemodid->module_valid_length_hash,GINT_TO_POINTER(cabinet_length), NULL, /* orig_key */ &valid_length_value_gpointer)) /* value */ return 0; return GPOINTER_TO_INT(valid_length_value_gpointer); } -struct captive_captivemodid_module *captive_captivemodid_module_md5_lookup(const gchar *file_md5) +struct captive_captivemodid_module *captive_captivemodid_module_md5_lookup + (CaptiveCaptivemodidObject *captivemodid,const gchar *file_md5) { g_return_val_if_fail(file_md5!=NULL,NULL); - module_md5_hash_init(); - return g_hash_table_lookup(module_md5_hash,file_md5); + return g_hash_table_lookup(captivemodid->module_md5_hash,file_md5); } -gint captive_captivemodid_module_type_best_priority_lookup(const xmlChar *module_type) +gint captive_captivemodid_module_type_best_priority_lookup(CaptiveCaptivemodidObject *captivemodid,const xmlChar *module_type) { gpointer r_gpointer; gboolean errbool; g_return_val_if_fail(module_type!=NULL,G_MININT); - module_type_best_priority_hash_init(); - errbool=g_hash_table_lookup_extended(module_type_best_priority_hash, + errbool=g_hash_table_lookup_extended(captivemodid->module_type_best_priority_hash, module_type, /* lookup_key */ NULL, /* orig_key */ &r_gpointer); /* value */ @@ -180,17 +211,17 @@ gboolean errbool; } /* Returns: TRUE if all modules were found. */ -gboolean captive_captivemodid_module_type_best_priority_found(const xmlChar *module_type) +gboolean captive_captivemodid_module_type_best_priority_found + (CaptiveCaptivemodidObject *captivemodid,const xmlChar *module_type) { gboolean errbool; g_return_val_if_fail(module_type!=NULL,FALSE); - module_type_best_priority_hash_init(); - errbool=g_hash_table_remove(module_type_best_priority_hash,module_type); + errbool=g_hash_table_remove(captivemodid->module_type_best_priority_hash,module_type); g_assert(errbool==TRUE); - return !g_hash_table_size(module_type_best_priority_hash); + return !g_hash_table_size(captivemodid->module_type_best_priority_hash); } static xmlChar *captive_captivemodid_load_module_xml_get_attr @@ -229,7 +260,8 @@ char *ends; return r; } -static void captive_captivemodid_load_module_xml(const gchar *captive_captivemodid_pathname,xmlTextReader *xml_reader) +static void captive_captivemodid_load_module_xml + (CaptiveCaptivemodidObject *captivemodid,const gchar *captive_captivemodid_pathname,xmlTextReader *xml_reader) { struct captive_captivemodid_module *module; xmlChar *cabinet_used_string; @@ -263,14 +295,11 @@ xmlChar *cabinet_used_string; if (G_MININT>=(module->priority=captive_captivemodid_load_module_xml_get_attr_l(captive_captivemodid_pathname,xml_reader,"priority", G_MININT+1,G_MAXINT-1))) goto fail_free_module; - captive_captivemodid_load_module(module); + captive_captivemodid_load_module(captivemodid,module); return; fail_free_module: - xmlFree((xmlChar *)module->type); - xmlFree((xmlChar *)module->md5); - xmlFree((xmlChar *)module->id); - g_free(module); + captive_captivemodid_module_free(module); } static void captive_captivemodid_load_foreach @@ -285,12 +314,19 @@ static void captive_captivemodid_load_foreach void (*captive_captivemodid_module_best_priority_notify)(const gchar *module_type); -gboolean captive_captivemodid_load(const gchar *captive_captivemodid_pathname) +CaptiveCaptivemodidObject *captive_captivemodid_load(const gchar *captive_captivemodid_pathname) { +CaptiveCaptivemodidObject *captivemodid; xmlTextReader *xml_reader; if (!(xml_reader=xmlNewTextReaderFilename(captive_captivemodid_pathname))) return FALSE; + + captivemodid=g_object_new( + CAPTIVE_CAPTIVEMODID_TYPE_OBJECT, /* object_type */ + NULL); /* first_property_name; FIXME: support properties */ + captivemodid->pathname_loaded=g_strdup(captive_captivemodid_pathname); + while (1==xmlTextReaderRead(xml_reader)) { switch (xmlTextReaderNodeType(xml_reader)) { @@ -313,7 +349,7 @@ const xmlChar *xml_name; /**/ if (!xmlStrcmp(xml_name,BAD_CAST "modid")) { /* root tag */ } else if (!xmlStrcmp(xml_name,BAD_CAST "module")) - captive_captivemodid_load_module_xml(captive_captivemodid_pathname,xml_reader); + captive_captivemodid_load_module_xml(captivemodid,captive_captivemodid_pathname,xml_reader); else g_warning(_("%s: Unknown ELEMENT node: %s"),captive_captivemodid_pathname,xml_name); xmlFree((xmlChar *)xml_name); } break; @@ -324,8 +360,59 @@ const xmlChar *xml_name; xmlFreeTextReader(xml_reader); if (captive_captivemodid_module_best_priority_notify) { - g_hash_table_foreach(module_type_best_priority_hash, - (GHFunc)captive_captivemodid_load_foreach,NULL); + g_hash_table_foreach(captivemodid->module_type_best_priority_hash, + (GHFunc)captive_captivemodid_load_foreach, + captivemodid); /* user_data */ } - return TRUE; + + return captivemodid; +} + +CaptiveCaptivemodidObject *captive_captivemodid_load_default(gboolean fatal) +{ +CaptiveCaptivemodidObject *captivemodid=NULL; +const gchar *pathname_default=G_STRINGIFY(SYSCONFDIR) "/w32-mod-id.captivemodid.xml"; +const gchar *msg; + + if ((captivemodid=captive_captivemodid_load(pathname_default))) + return captivemodid; + if ((captivemodid=captive_captivemodid_load("./w32-mod-id.captivemodid.xml"))) + return captivemodid; + msg=_("Unable to load modid database: %s"); + if (fatal) + g_error(msg,pathname_default); + g_warning(msg,pathname_default); + return NULL; +} + +const gchar *captive_captivemodid_get_pathname_loaded(CaptiveCaptivemodidObject *captivemodid) +{ + return captivemodid->pathname_loaded; +} + +gchar *captive_calc_md5(gconstpointer base,size_t length) +{ +unsigned char md5_bin[1+128/8]; /* 128 bits==16 bytes; '1+' for leading stub to prevent shorter output of BN_bn2hex() */ +BIGNUM *bignum; +char *hex; +gchar *r,*gs; + + /* already done above */ + /* Calculate MD5 sum and convert it to hex string: */ + MD5(base,length,md5_bin+1); + md5_bin[0]=0xFF; /* stub to prevent shorter output of BN_bn2hex() */ + bignum=BN_bin2bn(md5_bin,1+128/8,NULL); + hex=BN_bn2hex(bignum); + g_assert(strlen(hex)==2*(1+128/8)); + r=g_strdup(hex+2); + OPENSSL_free(hex); + BN_free(bignum); + + g_assert(strlen(r)==32); + for (gs=r;*gs;gs++) { + g_assert(isxdigit(*gs)); + *gs=tolower(*gs); + g_assert(isxdigit(*gs)); + } + return r; } diff --git a/src/libcaptive/client/options-module.c b/src/libcaptive/client/options-module.c index 8b83174..ba07eaa 100644 --- a/src/libcaptive/client/options-module.c +++ b/src/libcaptive/client/options-module.c @@ -35,6 +35,32 @@ #include +static void module_check_captivemodid(struct captive_options_module *options_module,const gchar *pathname_utf8) +{ + if (!captive_options->captivemodid) { + if (!captive_options->load_untested) + g_error(_( + "You do not have loaded any .captivemodid.xml database using: --modid-path\n" + "Unable to check MS-Windows module file validity. You should load the database first.\n" + "You may also force loading of the module although it may not be tested: --load-untested")); + g_warning(_("Loading possibly INCOMPATIBLE module as no database is present. Forced by: --load-untested: %s"), + pathname_utf8); + return; + } + if (captive_captivemodid_module_md5_lookup(captive_options->captivemodid,options_module->u.pe32.md5)) + return; + if (!captive_options->load_untested) + g_error(_( + "Attempted to load UNTESTED and possibly INCOMPATIBLE module: %s\n" + "You should get more recent identifications database: %s\n" + "Otherwise you may also force the loading by the option: --load-untested"), + pathname_utf8,captive_captivemodid_get_pathname_loaded(captive_options->captivemodid)); + g_warning(_( + "Loading UNTESTED and possibly INCOMPATIBLE module: %s\n" + "Although forced by --load-untested you really should get more recent modid database: %s\n"), + pathname_utf8,captive_captivemodid_get_pathname_loaded(captive_options->captivemodid)); +} + gboolean captive_options_module_load(struct captive_options_module *options_module,const gchar *pathname_utf8) { const guint8 magic_mscf[]={'M','S','C','F',0,0,0,0}; @@ -78,6 +104,7 @@ char *hex,*s; *s=tolower(*s); g_assert(isxdigit(*s)); } + module_check_captivemodid(options_module,pathname_utf8); } else if (options_module->u.pe32.length>=sizeof(magic_mscf) && !memcmp(options_module->u.pe32.base,magic_mscf,sizeof(magic_mscf))) { diff --git a/src/libcaptive/client/options.c b/src/libcaptive/client/options.c index ff2d6ed..703a84c 100644 --- a/src/libcaptive/client/options.c +++ b/src/libcaptive/client/options.c @@ -43,6 +43,8 @@ void captive_options_init(struct captive_options *options) options->load_module=NULL; options->sandbox=FALSE; options->syslog_facility=-1; + options->captivemodid=NULL; + options->load_untested=FALSE; } @@ -91,6 +93,9 @@ char **sp; if (src->bug_pathname) dest->bug_pathname=g_strdup(src->bug_pathname); + + if (dest->captivemodid) + g_object_ref(dest->captivemodid); } @@ -110,6 +115,9 @@ void captive_options_free(struct captive_options *options) g_free(options->sandbox_server_argv); g_free(options->sandbox_server_ior); g_free(options->bug_pathname); + + if (options->captivemodid) + g_object_unref(options->captivemodid); } @@ -137,6 +145,19 @@ gboolean errbool; captive_options->load_module=g_list_append(captive_options->load_module,options_module); } +static void arg_modid_path(void) +{ + if (captive_options->captivemodid) + g_object_unref(captive_options->captivemodid); + if (!(captive_options->captivemodid=captive_captivemodid_load(captive_popt_optarg))) + g_error(_("Unable to load modid database: %s"),captive_popt_optarg); +} + +static void arg_load_untested(void) +{ + captive_options->load_untested=TRUE; +} + static void arg_ro(void) { captive_options->rwmode=CAPTIVE_OPTION_RWMODE_RO; @@ -334,6 +355,8 @@ const struct poptOption captive_popt[]={ CAPTIVE_POPT_STRING("filesystem" ,N_("Pathname to .sys or .so filesystem module file"),N_("pathname")), CAPTIVE_POPT_STRING("load-module" ,N_("Pathname to any W32 module to load w/o initialization"),N_("pathname")), + CAPTIVE_POPT_STRING("modid-path" ,N_("Path to .captivemodid.xml database"),N_("path")), + CAPTIVE_POPT_NONE( "load-untested" ,N_("Force loading of W32 module not present in --modid-path database")), CAPTIVE_POPT_NONE( "ro" ,N_("Read/write mode: Any write access will be forbidden")), CAPTIVE_POPT_NONE( "blind" ,N_("Read/write mode: All writes are just simulated in memory (default)")), CAPTIVE_POPT_NONE( "rw" ,N_("Read/write mode: Write directly to the image file/device")), @@ -366,6 +389,8 @@ static const struct poptOption captive_popt_standalone[]={ static void (*const popt_func_table[])(void)={ arg_filesystem, arg_load_module, + arg_modid_path, + arg_load_untested, arg_ro, arg_blind, arg_rw, diff --git a/src/libcaptive/include/captive/captivemodid.h b/src/libcaptive/include/captive/captivemodid.h index 5a3847a..592c689 100644 --- a/src/libcaptive/include/captive/captivemodid.h +++ b/src/libcaptive/include/captive/captivemodid.h @@ -22,6 +22,7 @@ #include +#include #include #include /* for xmlChar */ #include @@ -29,6 +30,19 @@ G_BEGIN_DECLS +#define CAPTIVE_CAPTIVEMODID_TYPE_OBJECT (captive_captivemodid_object_get_type()) +#define CAPTIVE_CAPTIVEMODID_OBJECT(object) (G_TYPE_CHECK_INSTANCE_CAST((object),CAPTIVE_CAPTIVEMODID_TYPE_OBJECT,CaptiveCaptivemodidObject)) +#define CAPTIVE_CAPTIVEMODID_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),CAPTIVE_CAPTIVEMODID_TYPE_OBJECT,CaptiveCaptivemodidObjectClass)) +#define CAPTIVE_CAPTIVEMODID_IS_OBJECT(object) (G_TYPE_CHECK_INSTANCE_TYPE((object),CAPTIVE_CAPTIVEMODID_TYPE_OBJECT)) +#define CAPTIVE_CAPTIVEMODID_IS_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),CAPTIVE_CAPTIVEMODID_TYPE_OBJECT)) +#define CAPTIVE_CAPTIVEMODID_OBJECT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj),CAPTIVE_CAPTIVEMODID_TYPE_OBJECT,CaptiveCaptivemodidObjectClass)) +typedef struct _CaptiveCaptivemodidObject CaptiveCaptivemodidObject; +typedef struct _CaptiveCaptivemodidObjectClass CaptiveCaptivemodidObjectClass; + + +GType captive_captivemodid_object_get_type(void); + + struct captive_captivemodid_module { const xmlChar *type; gint length; @@ -40,13 +54,19 @@ struct captive_captivemodid_module { extern void (*captive_captivemodid_module_best_priority_notify)(const gchar *module_type); +CaptiveCaptivemodidObject *captive_captivemodid_load(const gchar *captive_captivemodid_pathname); +CaptiveCaptivemodidObject *captive_captivemodid_load_default(gboolean fatal); +const gchar *captive_captivemodid_get_pathname_loaded(CaptiveCaptivemodidObject *captivemodid); +gboolean captive_captivemodid_module_length_is_valid(CaptiveCaptivemodidObject *captivemodid,GnomeVFSFileSize file_size); +struct captive_captivemodid_module *captive_captivemodid_module_md5_lookup + (CaptiveCaptivemodidObject *captivemodid,const gchar *file_md5); +gint captive_captivemodid_module_type_best_priority_lookup + (CaptiveCaptivemodidObject *captivemodid,const xmlChar *module_type); +gboolean captive_captivemodid_module_type_best_priority_found + (CaptiveCaptivemodidObject *captivemodid,const xmlChar *module_type); +gint captive_captivemodid_cabinet_length_to_used(CaptiveCaptivemodidObject *captivemodid,gint cabinet_length); + gchar *captive_calc_md5(gconstpointer base,size_t length); -gboolean captive_captivemodid_module_length_is_valid(GnomeVFSFileSize file_size); -struct captive_captivemodid_module *captive_captivemodid_module_md5_lookup(const gchar *file_md5); -gint captive_captivemodid_module_type_best_priority_lookup(const xmlChar *module_type); -gboolean captive_captivemodid_module_type_best_priority_found(const xmlChar *module_type); -gboolean captive_captivemodid_load(const gchar *captive_captivemodid_pathname); -gint captive_captivemodid_cabinet_length_to_used(gint cabinet_length); G_END_DECLS diff --git a/src/libcaptive/include/captive/options.h b/src/libcaptive/include/captive/options.h index 02b4124..d6d97b0 100644 --- a/src/libcaptive/include/captive/options.h +++ b/src/libcaptive/include/captive/options.h @@ -26,6 +26,7 @@ #include #include #include "captive/options-module.h" +#include "captive/captivemodid.h" G_BEGIN_DECLS @@ -61,6 +62,8 @@ struct captive_options { gchar *sandbox_server_ior; gchar *bug_pathname; int syslog_facility; /* LOG_*; -1 if not used */ + CaptiveCaptivemodidObject *captivemodid; + gboolean load_untested; }; /** -- 1.8.3.1