diff options
Diffstat (limited to 'libnm-core/nm-vpn-editor-plugin.c')
-rw-r--r-- | libnm-core/nm-vpn-editor-plugin.c | 139 |
1 files changed, 135 insertions, 4 deletions
diff --git a/libnm-core/nm-vpn-editor-plugin.c b/libnm-core/nm-vpn-editor-plugin.c index 5bf72b0cdd..5a2bfa49a0 100644 --- a/libnm-core/nm-vpn-editor-plugin.c +++ b/libnm-core/nm-vpn-editor-plugin.c @@ -403,21 +403,152 @@ nm_vpn_editor_plugin_set_editor_library_path (NMVpnEditorPlugin *self, } /** + * nm_vpn_editor_plugin_get_editor_load: + * @self: the #NMVpnEditorPlugin instance + * @editor_library_path: (allow-none): the library path to load. If %NULL, + * fallback to nm_vpn_editor_plugin_get_editor_library_path(). + * @connection: the #NMConnection instance passed to the factory method. + * @do_file_checks: if %TRUE, check that the file is valid and has proper + * permissions before loading the library. Otherwise, the path is passed + * directly to dlopen. + * @check_owner: if positive, only allow plugins owned by this owner. + * This argument is ignored if @do_file_checks is %FALSE. + * @check_file: (allow-none): a predicate to test whether the file is valid + * before loading the shared library. This argument is ignored if @do_file_checks + * is %FALSE. + * @user_data: the user-data for @check_file callback. + * @load_data: the data passed to the factory method. Currently %NMVpnEditorLoadData + * is an opaque type that contains no fields. In the future we might extend this + * structure to pass additional arguments to the factory method. + * @error: %GError with the error reason + * + * This loads the shared library from @editor_library_path, optionally performs some checks + * on the file before dlopen(), looks up the factory method "nm_vpn_editor_factory" + * and calls it to create an NMVpnEditor instance. + * + * Returns: (transfer-full): a #NMVpnEditor instance of %NULL in case of error. + * + * Since: 1.4 + **/ +NMVpnEditor * +nm_vpn_editor_plugin_get_editor_load (NMVpnEditorPlugin *self, + const char *editor_library_path, + NMConnection *connection, + gboolean do_file_checks, + int check_owner, + NMUtilsCheckFilePredicate check_file, + gpointer user_data, + NMVpnEditorLoadData *load_data, + GError **error) +{ + GModule *module = NULL; + NMVpnEditorFactory factory = NULL; + NMVpnEditor *editor = NULL; + gs_free char *editor_library_path_free = NULL; + + g_return_val_if_fail (NM_IS_VPN_EDITOR_PLUGIN (self), NULL); + + if (!editor_library_path) { + editor_library_path_free = nm_vpn_editor_plugin_get_editor_library_path (self, TRUE); + editor_library_path = editor_library_path_free; + } else if (do_file_checks) { + editor_library_path_free = _get_editor_library_path_validate_and_absolute (editor_library_path); + editor_library_path = editor_library_path_free; + } + + if (!editor_library_path) { + g_set_error_literal (error, + NM_VPN_PLUGIN_ERROR, + NM_VPN_PLUGIN_ERROR_FAILED, + _("Cannot create VPN editor due to missing editor-library-path")); + return NULL; + } + + if (do_file_checks) { + if (!_nm_utils_check_module_file (editor_library_path, + check_owner, + check_file, + user_data, + error)) + return NULL; + } + + module = g_module_open (editor_library_path, G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL); + if (!module) { + g_set_error (error, + NM_VPN_PLUGIN_ERROR, + NM_VPN_PLUGIN_ERROR_FAILED, + _("cannot load plugin %s"), editor_library_path); + return NULL; + } + + if (g_module_symbol (module, "nm_vpn_editor_factory", (gpointer) &factory)) { + gs_free_error GError *factory_error = NULL; + + editor = factory (self, + connection, + load_data, + &factory_error); + + g_assert (!editor || G_IS_OBJECT (editor)); + + if (editor) { + g_object_set_data_full (G_OBJECT (editor), "gmodule", module, + (GDestroyNotify) g_module_close); + } else { + if (factory_error) { + g_propagate_error (error, factory_error); + factory_error = NULL; + } else { + g_set_error (error, + NM_VPN_PLUGIN_ERROR, + NM_VPN_PLUGIN_ERROR_FAILED, + _("unknown error initializing editor plugin %s"), editor_library_path); + } + g_module_close (module); + } + } else { + g_set_error (error, + NM_VPN_PLUGIN_ERROR, + NM_VPN_PLUGIN_ERROR_FAILED, + _("failed to load nm_vpn_editor_factory() from %s (%s)"), + g_module_name (module), g_module_error ()); + g_module_close (module); + } + + return editor; +} + +/** * nm_vpn_editor_plugin_get_editor: - * @plugin: the #NMVpnEditorPlugin + * @self: the #NMVpnEditorPlugin * @connection: the #NMConnection to be edited * @error: on return, an error or %NULL * * Returns: (transfer full): a new #NMVpnEditor or %NULL on error */ NMVpnEditor * -nm_vpn_editor_plugin_get_editor (NMVpnEditorPlugin *plugin, +nm_vpn_editor_plugin_get_editor (NMVpnEditorPlugin *self, NMConnection *connection, GError **error) { - g_return_val_if_fail (NM_IS_VPN_EDITOR_PLUGIN (plugin), NULL); + NMVpnEditorPluginInterface *interface; + + g_return_val_if_fail (NM_IS_VPN_EDITOR_PLUGIN (self), NULL); - return NM_VPN_EDITOR_PLUGIN_GET_INTERFACE (plugin)->get_editor (plugin, connection, error); + interface = NM_VPN_EDITOR_PLUGIN_GET_INTERFACE (self); + if (interface->get_editor) + return interface->get_editor (self, connection, error); + + return nm_vpn_editor_plugin_get_editor_load (self, + NULL, + connection, + TRUE, + getuid (), + NULL, + NULL, + NULL, + error); } NMVpnEditorPluginCapability |