[PATCH v5 13/16] vpn-provider: Add route support in vpn config file
--- vpn/vpn-provider.c | 99 +- vpn/vpn.h | 3 +- 2 files changed, 86 insertions(+), 16 deletions(-) diff --git a/vpn/vpn-provider.c b/vpn/vpn-provider.c index 6750d6b..f530348 100644 --- a/vpn/vpn-provider.c +++ b/vpn/vpn-provider.c @@ -237,13 +237,9 @@ static GSList *read_route_dict(GSList *routes, DBusMessageIter *dicts) if (family < 0) { DBG("Cannot get address family of %s (%d/%s)", network, family, gai_strerror(family)); - if (strstr(network, ":") != NULL) { - DBG("Guessing it is IPv6"); - family = AF_INET6; - } else { - DBG("Guessing it is IPv4"); - family = AF_INET; - } + + g_free(route); + return routes; } } else { switch (family) { @@ -308,7 +304,7 @@ static void set_user_networks(struct vpn_provider *provider, GSList *networks) if (__vpn_provider_append_user_route(provider, route->family, route->network, - route->netmask) != 0) + route->netmask, route->gateway) != 0) break; } } @@ -545,12 +541,15 @@ void __vpn_provider_append_properties(struct vpn_provider *provider, } int __vpn_provider_append_user_route(struct vpn_provider *provider, - int family, const char *network, const char *netmask) + int family, const char *network, + const char *netmask, const char *gateway) { struct vpn_route *route; - char *key = g_strdup_printf("%d/%s/%s", family, network, netmask); + char *key = g_strdup_printf("%d/%s/%s/%s", family, network, + netmask, gateway != NULL ? gateway : ""); - DBG("family %d network %s netmask %s", family, network, netmask); + DBG("family %d network %s netmask %s gw %s", family, network, + netmask, gateway); route = g_hash_table_lookup(provider->user_routes, key); if (route == NULL) { @@ -563,6 +562,7 @@ int __vpn_provider_append_user_route(struct vpn_provider *provider, route->family = family; route->network = g_strdup(network); route->netmask = g_strdup(netmask); + route->gateway = g_strdup(gateway); g_hash_table_replace(provider->user_routes, key, route); } else @@ -1795,7 +1795,75 @@ static const char *get_string(GHashTable *settings, const char *key) static GSList *parse_user_networks(const char *network_str) { - return NULL; + GSList *networks = NULL; + char **elems = g_strsplit(network_str, ",", 0); + int i = 0; + + if (elems == NULL) + return NULL; + + while (elems[i] != NULL) { + struct vpn_route *vpn_route; + char *network, *netmask, *gateway; + int family; + char **route; + + route = g_strsplit(elems[i], "/", 0); + if (route == NULL) + goto next; + + network = route[0]; + if (network == NULL || network[0] == '\0') + goto next; + + family = connman_inet_check_ipaddress(network); + if (family < 0) { + DBG("Cannot get address family of %s (%d/%s)", network, + family, gai_strerror(family)); + + goto next; + } + + switch (family) { + case AF_INET: + break; + case AF_INET6: + break; + default: + DBG("Unsupported address family %d", family); + goto next; + } + + netmask = route[1]; + if (netmask == NULL || netmask[0] == '\0') + goto next; + + gateway = route[2]; + + vpn_route = g_try_new0(struct vpn_route, 1); + if (vpn_route == NULL) { + g_strfreev(route); + break; + } + + vpn_route->family = family; + vpn_route->network = g_strdup(network); + vpn_route->netmask = g_strdup(netmask); + vpn_route->gateway = g_strdup(gateway); + + DBG("route %s/%s%s%s", network, netmask, + gateway ? " via " : "", gateway ? gateway : ""); + + networks = g_slist_prepend(networks, vpn_route); + + next:
[PATCH v5 12/16] vpn-provider: Remove unprovisioned providers at startup
Check if there are any providers that were provisioned but their .config file is removed. If such providers are found, then remove the provider files from file system. --- vpn/vpn-provider.c | 80 +- 1 file changed, 79 insertions(+), 1 deletion(-) diff --git a/vpn/vpn-provider.c b/vpn/vpn-provider.c index c80027d..6750d6b 100644 --- a/vpn/vpn-provider.c +++ b/vpn/vpn-provider.c @@ -81,6 +81,8 @@ struct vpn_provider { char **nameservers; int what_changed; guint notify_id; + char *config_file; + char *config_entry; }; static void free_route(gpointer data) @@ -809,6 +811,15 @@ static int vpn_provider_save(struct vpn_provider *provider) } } + if (provider->config_file != NULL && strlen(provider->config_file) > 0) + g_key_file_set_string(keyfile, provider->identifier, + "Config.file", provider->config_file); + + if (provider->config_entry != NULL && + strlen(provider->config_entry) > 0) + g_key_file_set_string(keyfile, provider->identifier, + "Config.ident", provider->config_entry); + if (provider->driver != NULL && provider->driver->save != NULL) provider->driver->save(provider, keyfile); @@ -922,6 +933,8 @@ static void provider_destruct(struct vpn_provider *provider) __vpn_ipconfig_unref(provider->ipconfig_ipv6); g_strfreev(provider->host_ip); + g_free(provider->config_file); + g_free(provider->config_entry); g_free(provider); } @@ -1833,6 +1846,9 @@ int __vpn_provider_create_from_config(GHashTable *settings, provider->name = g_strdup(name); provider->type = g_ascii_strdown(type, -1); + provider->config_file = g_strdup(config_ident); + provider->config_entry = g_strdup(config_entry); + if (provider_register(provider) == 0) vpn_provider_load(provider); @@ -2326,6 +2342,67 @@ static struct connman_agent_driver agent_driver = { .remove = agent_remove, }; +static void remove_unprovisioned_providers() +{ + gchar **providers; + GKeyFile *keyfile, *configkeyfile; + char *file, *section; + int i = 0; + + providers = __connman_storage_get_providers(); + if (providers == NULL) + return; + + for (; providers[i] != NULL; i++) { + char *group = providers[i] + sizeof("provider_") - 1; + file = section = NULL; + keyfile = configkeyfile = NULL; + + keyfile = __connman_storage_load_provider(group); + if (keyfile == NULL) + continue; + + file = g_key_file_get_string(keyfile, group, + "Config.file", NULL); + if (file == NULL) + goto next; + + section = g_key_file_get_string(keyfile, group, + "Config.ident", NULL); + if (section == NULL) + goto next; + + configkeyfile = __connman_storage_load_provider_config(file); + if (configkeyfile == NULL) { + /* +* Config file is missing, remove the provisioned +* service. +*/ + __connman_storage_remove_provider(group); + goto next; + } + + if (g_key_file_has_group(configkeyfile, section) == FALSE) + /* +* Config section is missing, remove the provisioned +* service. +*/ + __connman_storage_remove_provider(group); + + next: + if (keyfile != NULL) + g_key_file_free(keyfile); + + if (configkeyfile != NULL) + g_key_file_free(configkeyfile); + + g_free(section); + g_free(file); + } + + g_strfreev(providers); +} + int __vpn_provider_init(gboolean do_routes) { int err; @@ -2343,9 +2420,10 @@ int __vpn_provider_init(gboolean do_routes) connection = connman_dbus_get_connection(); + remove_unprovisioned_providers(); + provider_hash = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, unregister_provider); - return 0; } -- 1.7.11.4 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH v5 11/16] vpn-provider: Type string in provider needs to be in lower case
--- vpn/vpn-provider.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vpn/vpn-provider.c b/vpn/vpn-provider.c index f6753b9..c80027d 100644 --- a/vpn/vpn-provider.c +++ b/vpn/vpn-provider.c @@ -1929,7 +1929,7 @@ int vpn_provider_set_string(struct vpn_provider *provider, if (g_str_equal(key, "Type") == TRUE) { g_free(provider->type); - provider->type = g_strdup(value); + provider->type = g_ascii_strdown(value, -1); } else if (g_str_equal(key, "Name") == TRUE) { g_free(provider->name); provider->name = g_strdup(value); -- 1.7.11.4 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH v5 10/16] vpn-config: Provision providers from .config file
--- Makefile.am | 3 +- vpn/main.c | 4 + vpn/vpn-config.c | 598 +++ vpn/vpn.h| 3 + 4 files changed, 607 insertions(+), 1 deletion(-) create mode 100644 vpn/vpn-config.c diff --git a/Makefile.am b/Makefile.am index 2490f9e..3265d83 100644 --- a/Makefile.am +++ b/Makefile.am @@ -124,7 +124,8 @@ vpn_connman_vpnd_SOURCES = $(gdbus_sources) $(builtin_vpn_sources) \ vpn/vpn-provider.h vpn/vpn-rtnl.h \ vpn/vpn-ipconfig.c src/inet.c vpn/vpn-rtnl.c \ src/dbus.c src/storage.c src/ipaddress.c src/agent.c \ - vpn/vpn-agent.c vpn/vpn-agent.h + vpn/vpn-agent.c vpn/vpn-agent.h src/inotify.c \ + vpn/vpn-config.c vpn_connman_vpnd_LDADD = $(builtin_vpn_libadd) @GLIB_LIBS@ @DBUS_LIBS@ \ @GNUTLS_LIBS@ -lresolv -ldl diff --git a/vpn/main.c b/vpn/main.c index a17f522..8fd830c 100644 --- a/vpn/main.c +++ b/vpn/main.c @@ -308,6 +308,7 @@ int main(int argc, char *argv[]) else config_init(option_config); + __connman_inotify_init(); __connman_agent_init(); __vpn_provider_init(option_routes); __vpn_manager_init(); @@ -315,6 +316,7 @@ int main(int argc, char *argv[]) __vpn_rtnl_init(); __connman_task_init(); __connman_plugin_init(option_plugin, option_noplugin); + __vpn_config_init(); __vpn_rtnl_start(); @@ -325,6 +327,7 @@ int main(int argc, char *argv[]) g_source_remove(signal); + __vpn_config_cleanup(); __connman_plugin_cleanup(); __connman_task_cleanup(); __vpn_rtnl_cleanup(); @@ -332,6 +335,7 @@ int main(int argc, char *argv[]) __vpn_manager_cleanup(); __vpn_provider_cleanup(); __connman_agent_cleanup(); + __connman_inotify_cleanup(); __connman_dbus_cleanup(); __connman_log_cleanup(FALSE); diff --git a/vpn/vpn-config.c b/vpn/vpn-config.c new file mode 100644 index 000..1ece7e9 --- /dev/null +++ b/vpn/vpn-config.c @@ -0,0 +1,598 @@ +/* + * + * Connection Manager + * + * Copyright (C) 2012 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include + +#include +#include "../src/connman.h" + +#include "vpn.h" + +enum what { + REMOVE = 1, + ADD = 2, +}; + +struct vpn_config_provider { + char *provider_identifier; + char *ident; + char *name; + char *type; + char *host; + char *domain; + char *networks; + GHashTable *setting_strings; + + char *config_ident; /* file prefix */ + char *config_entry; /* entry name */ +}; + +struct vpn_config { + char *ident; + char *name; + char *description; + connman_bool_t protected; + GHashTable *provider_table; +}; + +static GHashTable *config_table = NULL; +static GSList *protected_providers = NULL; + +static connman_bool_t cleanup = FALSE; + +/* Definition of possible strings in the .config files */ +#define CONFIG_KEY_NAME"Name" +#define CONFIG_KEY_DESC"Description" +#define CONFIG_KEY_PROT"Protected" + +static const char *config_possible_keys[] = { + CONFIG_KEY_NAME, + CONFIG_KEY_DESC, + CONFIG_KEY_PROT, + NULL, +}; + +static void unregister_config(gpointer data) +{ + struct vpn_config *config = data; + + connman_info("Removing configuration %s", config->ident); + + g_hash_table_destroy(config->provider_table); + + g_free(config->description); + g_free(config->name); + g_free(config->ident); + g_free(config); +} + +static void unregister_provider(gpointer data) +{ + struct vpn_config_provider *config_provider = data; + struct vpn_provider *provider; + char *provider_id; + + if (cleanup == TRUE) + goto free_only; + + provider_id = config_provider->provider_identifier; + + connman_info("Removing provider configuration %s provider %s", + config_provider->ident, provider_id); + + protected
[PATCH v5 09/16] vpn-provider: Initial .config file support
--- vpn/vpn-provider.c | 152 +++-- vpn/vpn.h | 5 ++ 2 files changed, 140 insertions(+), 17 deletions(-) diff --git a/vpn/vpn-provider.c b/vpn/vpn-provider.c index 56a9c51..f6753b9 100644 --- a/vpn/vpn-provider.c +++ b/vpn/vpn-provider.c @@ -818,7 +818,7 @@ static int vpn_provider_save(struct vpn_provider *provider) return 0; } -static struct vpn_provider *vpn_provider_lookup(const char *identifier) +struct vpn_provider *__vpn_provider_lookup(const char *identifier) { struct vpn_provider *provider = NULL; @@ -840,7 +840,8 @@ static int provider_probe(struct vpn_provider *provider) { GSList *list; - DBG("provider %p name %s", provider, provider->name); + DBG("provider %p driver %p name %s", provider, provider->driver, + provider->name); if (provider->driver != NULL) return -EALREADY; @@ -1051,20 +1052,26 @@ int __vpn_provider_remove(const char *path) ident = get_ident(path); - provider = vpn_provider_lookup(ident); - if (provider != NULL) { - DBG("Removing VPN %s", provider->identifier); + provider = __vpn_provider_lookup(ident); + if (provider != NULL) + return __vpn_provider_delete(provider); - connection_removed_signal(provider); + return -ENXIO; +} - provider_unregister(provider); - g_hash_table_remove(provider_hash, provider->identifier); +int __vpn_provider_delete(struct vpn_provider *provider) +{ + DBG("Deleting VPN %s", provider->identifier); - __connman_storage_remove_provider(ident); - return 0; - } + connection_removed_signal(provider); - return -ENXIO; + provider_unregister(provider); + + __connman_storage_remove_provider(provider->identifier); + + g_hash_table_remove(provider_hash, provider->identifier); + + return 0; } static void append_ipv4(DBusMessageIter *iter, void *user_data) @@ -1561,7 +1568,7 @@ static struct vpn_provider *provider_create_from_keyfile(GKeyFile *keyfile, if (keyfile == NULL || ident == NULL) return NULL; - provider = vpn_provider_lookup(ident); + provider = __vpn_provider_lookup(ident); if (provider == NULL) { provider = vpn_provider_get(ident); if (provider == NULL) { @@ -1628,6 +1635,19 @@ static void provider_create_all_from_type(const char *provider_type) g_strfreev(providers); } +char *__vpn_provider_create_identifier(const char *host, const char *domain) +{ + char *ident; + + ident = g_strdup_printf("%s_%s", host, domain); + if (ident == NULL) + return NULL; + + provider_dbus_ident(ident); + + return ident; +} + int __vpn_provider_create(DBusMessage *msg) { struct vpn_provider *provider; @@ -1679,12 +1699,10 @@ int __vpn_provider_create(DBusMessage *msg) if (type == NULL || name == NULL) return -EOPNOTSUPP; - ident = g_strdup_printf("%s_%s", host, domain); - provider_dbus_ident(ident); - + ident = __vpn_provider_create_identifier(host, domain); DBG("ident %s", ident); - provider = vpn_provider_lookup(ident); + provider = __vpn_provider_lookup(ident); if (provider == NULL) { provider = vpn_provider_get(ident); if (provider == NULL) { @@ -1755,6 +1773,106 @@ int __vpn_provider_create(DBusMessage *msg) return 0; } +static const char *get_string(GHashTable *settings, const char *key) +{ + DBG("settings %p key %s", settings, key); + + return g_hash_table_lookup(settings, key); +} + +static GSList *parse_user_networks(const char *network_str) +{ + return NULL; +} + +int __vpn_provider_create_from_config(GHashTable *settings, + const char *config_ident, + const char *config_entry) +{ + struct vpn_provider *provider; + const char *type, *name, *host, *domain, *networks_str; + GSList *networks; + char *ident = NULL; + GHashTableIter hash; + gpointer value, key; + int err; + + type = get_string(settings, "Type"); + name = get_string(settings, "Name"); + host = get_string(settings, "Host"); + domain = get_string(settings, "Domain"); + networks_str = get_string(settings, "Networks"); + networks = parse_user_networks(networks_str); + + if (host == NULL || domain == NULL) { + err = -EINVAL; + goto fail; + } + + DBG("type %s name %s networks %s", type, name, networks_str); + + if (type == NULL || name == NULL) { + err = -EOPNOTSUPP; + goto fail; + } + + ident = __vpn_provider_create_identifier(host, domain)
[PATCH v5 08/16] storage: Add function to load provider configuration file
--- Makefile.am | 4 src/connman.h | 1 + src/storage.c | 16 3 files changed, 21 insertions(+) diff --git a/Makefile.am b/Makefile.am index 26081d8..2490f9e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -152,6 +152,7 @@ plugindir = $(libdir)/connman/plugins scriptdir = $(libdir)/connman/scripts storagedir = $(localstatedir)/lib/connman +vpn_storagedir = $(localstatedir)/lib/connman-vpn configdir = ${sysconfdir}/connman @@ -176,6 +177,7 @@ AM_CFLAGS = @DBUS_CFLAGS@ @GLIB_CFLAGS@ @XTABLES_CFLAGS@ \ -DPLUGINDIR=\""$(build_plugindir)"\" \ -DSCRIPTDIR=\""$(build_scriptdir)"\" \ -DSTORAGEDIR=\""$(storagedir)\"" \ + -DVPN_STORAGEDIR=\""$(vpn_storagedir)\"" \ -DCONFIGDIR=\""$(configdir)\"" if VPN @@ -191,6 +193,7 @@ src_connmand_CFLAGS = @DBUS_CFLAGS@ @GLIB_CFLAGS@ @XTABLES_CFLAGS@ \ -DPLUGINDIR=\""$(build_plugindir)"\" \ -DSCRIPTDIR=\""$(build_scriptdir)"\" \ -DSTORAGEDIR=\""$(storagedir)\"" \ + -DVPN_STORAGEDIR=\""$(vpn_storagedir)\"" \ -DCONFIGDIR=\""$(configdir)\"" \ -I$(builddir)/src @@ -205,6 +208,7 @@ vpn_connman_vpnd_CFLAGS = @DBUS_CFLAGS@ @GLIB_CFLAGS@ \ -DPLUGINDIR=\""$(build_vpn_plugindir)"\" \ -DSCRIPTDIR=\""$(build_scriptdir)"\" \ -DSTORAGEDIR=\""$(storagedir)\"" \ + -DVPN_STORAGEDIR=\""$(vpn_storagedir)\"" \ -DCONFIGDIR=\""$(configdir)\"" \ -I$(builddir)/vpn diff --git a/src/connman.h b/src/connman.h index 95e5c8a..49eafd3 100644 --- a/src/connman.h +++ b/src/connman.h @@ -206,6 +206,7 @@ int __connman_storage_save_global(GKeyFile *keyfile); void __connman_storage_delete_global(void); GKeyFile *__connman_storage_load_config(const char *ident); +GKeyFile *__connman_storage_load_provider_config(const char *ident); GKeyFile *__connman_storage_open_service(const char *ident); int __connman_storage_save_service(GKeyFile *keyfile, const char *ident); diff --git a/src/storage.c b/src/storage.c index 47822da..1ceafb9 100644 --- a/src/storage.c +++ b/src/storage.c @@ -147,6 +147,22 @@ GKeyFile *__connman_storage_load_config(const char *ident) return keyfile; } +GKeyFile *__connman_storage_load_provider_config(const char *ident) +{ + gchar *pathname; + GKeyFile *keyfile = NULL; + + pathname = g_strdup_printf("%s/%s.config", VPN_STORAGEDIR, ident); + if (pathname == NULL) + return NULL; + + keyfile = storage_load(pathname); + + g_free(pathname); + + return keyfile; +} + GKeyFile *__connman_storage_open_service(const char *service_id) { gchar *pathname; -- 1.7.11.4 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH v5 07/16] doc: VPN config file specification
--- doc/vpn-config-format.txt | 215 ++ 1 file changed, 215 insertions(+) create mode 100644 doc/vpn-config-format.txt diff --git a/doc/vpn-config-format.txt b/doc/vpn-config-format.txt new file mode 100644 index 000..d6afcb5 --- /dev/null +++ b/doc/vpn-config-format.txt @@ -0,0 +1,215 @@ +Connman configuration file format for VPN +* + +Connman VPN uses configuration files to provision existing providers. +vpnd will be looking for its configuration files at STORAGEDIR/vpn +which by default points to /var/lib/connman/vpn. Configuration file names +must not include other characters than letters or numbers and must have +a .config suffix. Those configuration files are text files with a simple +format and we typically have one file per provisioned network. + +If the config file is removed, then vpnd tries to remove the +provisioned service. If individual service entry inside config is removed, +then the corresponding provisioned service is removed. If service +entry is changed, then corresponding service is removed and then +immediately re-provisioned. + + +Global entry [global] += + +These files can have an optional global entry describing the actual file. +The 2 allowed fields for that entry are: +- Name: Name of the network. +- Description: Description of the network. + + +Provider entry [provider_*] +=== + +Each provisioned provider must start with the [provider_*] tag. +Replace * with an identifier unique to the config file. + +Allowed fields: +- Type: Provider type. Value of OpenConnect, OpenVPN, VPNC, L2TP or PPTP + +VPN related parameters (M = mandatory, O = optional): +- Name: A user defined name for the VPN (M) +- Host: VPN server IP address (M) +- Domain: Domain name for the VPN service (M) +- Networks: The networks behind the VPN link can be defined here. This can + be missing if all traffic should go via VPN tunnel. If there are more + than one network, then separate them by comma. Format of the entry + is network/netmask/gateway. The gateway can be left out. (O) + Example: 192.168.100.0/24/10.1.0.1,192.168.200.0/255.255.255.0/10.1.0.2 + For IPv6 addresses only prefix length is accepted like this 2001:db8::1/64 + +OpenConnect VPN supports following options (see openconnect(8) for details): + Option nameOpenConnect option Description + OpenConnect.ServerCert --servercert Accept server's SSL certificate + only if its fingerprint matches + this value (SHA1) (M) + OpenConnect.CACert --cafile Cert file for server + verification (M) + VPN.MTU--mtuRequest MTU from server as the + MTU of the tunnel (O) + +OpenVPN VPN supports following options (see openvpn(8) for details): + Option nameOpenVPN option Description + OpenVPN.CACert --ca Certificate authority file (M) + OpenVPN.Cert --cert Local peer's signed certificate (M) + OpenVPN.Key--keyLocal peer's private key (M) + OpenVPN.MTU--mtuMTU of the tunnel (O) + OpenVPN.NSCertType --ns-cert-type Peer certificate type, value of + either server or client (O) + OpenVPN.Proto --proto Use protocol (O) + OpenVPN.Port --port TCP/UDP port number (O) + OpenVPN.AuthUserPass --auth-user-pass Authenticate with server using + username/password (O) + OpenVPN.AskPass--askpassGet certificate password from file (O) + OpenVPN.AuthNoCache--auth-nocache Don't cache --askpass or + --auth-user-pass value (O) + OpenVPN.TLSRemote --tls-remote Accept connections only from a host + with X509 name or common name equal + to name parameter (O) + OpenVPN.TLSAuthsub-option of --tls-remote (O) + OpenVPN.TLSAuthDir sub-option of --tls-remote (O) + OpenVPN.Cipher --cipher Encrypt packets with cipher algorithm + given as parameter (O) + OpenVPN.Auth --auth Authenticate packets with HMAC using + message digest algorithm alg (O) + OpenVPN.CompLZO--comp-lzo Use fast LZO compression. Value can + be "yes", "no", or "adaptive". Default + is adaptive (O) + OpenVPN.RemoteCertTls --remote-cert-tls Require that peer certificate was + signed based on RFC3280 TLS rules. +
[PATCH v5 06/16] pptp: Use PPPD prefix for pppd specific options
For backward compatibility purposes, support also the PPTP prefix for PPPD options. --- vpn/plugins/pptp.c | 62 ++ 1 file changed, 44 insertions(+), 18 deletions(-) diff --git a/vpn/plugins/pptp.c b/vpn/plugins/pptp.c index 7269629..daa6ca3 100644 --- a/vpn/plugins/pptp.c +++ b/vpn/plugins/pptp.c @@ -63,21 +63,21 @@ struct { int type; } pptp_options[] = { { "PPTP.User", "user", NULL, OPT_STRING }, - { "PPTP.EchoFailure", "lcp-echo-failure", "0", OPT_STRING }, - { "PPTP.EchoInterval", "lcp-echo-interval", "0", OPT_STRING }, - { "PPTP.Debug", "debug", NULL, OPT_STRING }, - { "PPTP.RefuseEAP", "refuse-eap", NULL, OPT_BOOL }, - { "PPTP.RefusePAP", "refuse-pap", NULL, OPT_BOOL }, - { "PPTP.RefuseCHAP", "refuse-chap", NULL, OPT_BOOL }, - { "PPTP.RefuseMSCHAP", "refuse-mschap", NULL, OPT_BOOL }, - { "PPTP.RefuseMSCHAP2", "refuse-mschapv2", NULL, OPT_BOOL }, - { "PPTP.NoBSDComp", "nobsdcomp", NULL, OPT_BOOL }, - { "PPTP.NoDeflate", "nodeflate", NULL, OPT_BOOL }, - { "PPTP.RequirMPPE", "require-mppe", NULL, OPT_BOOL }, - { "PPTP.RequirMPPE40", "require-mppe-40", NULL, OPT_BOOL }, - { "PPTP.RequirMPPE128", "require-mppe-128", NULL, OPT_BOOL }, - { "PPTP.RequirMPPEStateful", "mppe-stateful", NULL, OPT_BOOL }, - { "PPTP.NoVJ", "no-vj-comp", NULL, OPT_BOOL }, + { "PPPD.EchoFailure", "lcp-echo-failure", "0", OPT_STRING }, + { "PPPD.EchoInterval", "lcp-echo-interval", "0", OPT_STRING }, + { "PPPD.Debug", "debug", NULL, OPT_STRING }, + { "PPPD.RefuseEAP", "refuse-eap", NULL, OPT_BOOL }, + { "PPPD.RefusePAP", "refuse-pap", NULL, OPT_BOOL }, + { "PPPD.RefuseCHAP", "refuse-chap", NULL, OPT_BOOL }, + { "PPPD.RefuseMSCHAP", "refuse-mschap", NULL, OPT_BOOL }, + { "PPPD.RefuseMSCHAP2", "refuse-mschapv2", NULL, OPT_BOOL }, + { "PPPD.NoBSDComp", "nobsdcomp", NULL, OPT_BOOL }, + { "PPPD.NoDeflate", "nodeflate", NULL, OPT_BOOL }, + { "PPPD.RequirMPPE", "require-mppe", NULL, OPT_BOOL }, + { "PPPD.RequirMPPE40", "require-mppe-40", NULL, OPT_BOOL }, + { "PPPD.RequirMPPE128", "require-mppe-128", NULL, OPT_BOOL }, + { "PPPD.RequirMPPEStateful", "mppe-stateful", NULL, OPT_BOOL }, + { "PPPD.NoVJ", "no-vj-comp", NULL, OPT_BOOL }, }; static DBusConnection *connection; @@ -218,14 +218,40 @@ static int pptp_notify(DBusMessage *msg, struct vpn_provider *provider) static int pptp_save(struct vpn_provider *provider, GKeyFile *keyfile) { const char *option; + connman_bool_t pptp_option, pppd_option; int i; for (i = 0; i < (int)ARRAY_SIZE(pptp_options); i++) { - if (strncmp(pptp_options[i].cm_opt, "PPTP.", 5) == 0) { + pptp_option = pppd_option = FALSE; + + if (strncmp(pptp_options[i].cm_opt, "PPTP.", 5) == 0) + pptp_option = TRUE; + + if (strncmp(pptp_options[i].cm_opt, "PPPD.", 5) == 0) + pppd_option = TRUE; + + if (pptp_option == TRUE || pppd_option == TRUE) { option = vpn_provider_get_string(provider, pptp_options[i].cm_opt); - if (option == NULL) - continue; + if (option == NULL) { + /* +* Check if the option prefix is PPTP as the +* PPPD options were using PPTP prefix earlier. +*/ + char *pptp_str; + + if (pppd_option == FALSE) + continue; + + pptp_str = g_strdup_printf("PPTP.%s", + &pptp_options[i].cm_opt[5]); + option = vpn_provider_get_string(provider, + pptp_str); + g_free(pptp_str); + + if (option == NULL) + continue; + } g_key_file_set_string(keyfile, vpn_provider_get_save_group(provider), -- 1.7.11.4 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH v5 05/16] l2tp: Use PPPD prefix for pppd specific options
For backward compatibility purposes, support also the L2TP prefix for PPPD options. --- vpn/plugins/l2tp.c | 68 +- 1 file changed, 47 insertions(+), 21 deletions(-) diff --git a/vpn/plugins/l2tp.c b/vpn/plugins/l2tp.c index 2355357..e0b2b04 100644 --- a/vpn/plugins/l2tp.c +++ b/vpn/plugins/l2tp.c @@ -98,23 +98,23 @@ struct { { "L2TP.Rand Source", "rand source", OPT_L2G, NULL, OPT_STRING }, { "L2TP.IPsecSaref", "ipsec saref", OPT_L2G, NULL, OPT_STRING }, { "L2TP.Port", "port", OPT_L2G, NULL, OPT_STRING }, - { "L2TP.EchoFailure", "lcp-echo-failure", OPT_PPPD, "0", OPT_STRING }, - { "L2TP.EchoInterval", "lcp-echo-interval", OPT_PPPD, "0", OPT_STRING }, - { "L2TP.Debug", "debug", OPT_PPPD, NULL, OPT_STRING }, - { "L2TP.RefuseEAP", "refuse-eap", OPT_PPPD, NULL, OPT_BOOL }, - { "L2TP.RefusePAP", "refuse-pap", OPT_PPPD, NULL, OPT_BOOL }, - { "L2TP.RefuseCHAP", "refuse-chap", OPT_PPPD, NULL, OPT_BOOL }, - { "L2TP.RefuseMSCHAP", "refuse-mschap", OPT_PPPD, NULL, OPT_BOOL }, - { "L2TP.RefuseMSCHAP2", "refuse-mschapv2", OPT_PPPD, NULL, OPT_BOOL }, - { "L2TP.NoBSDComp", "nobsdcomp", OPT_PPPD, NULL, OPT_BOOL }, - { "L2TP.NoPcomp", "nopcomp", OPT_PPPD, NULL, OPT_BOOL }, - { "L2TP.UseAccomp", "accomp", OPT_PPPD, NULL, OPT_BOOL }, - { "L2TP.NoDeflate", "nodeflate", OPT_PPPD, NULL, OPT_BOOL }, - { "L2TP.ReqMPPE", "require-mppe", OPT_PPPD, NULL, OPT_BOOL }, - { "L2TP.ReqMPPE40", "require-mppe-40", OPT_PPPD, NULL, OPT_BOOL }, - { "L2TP.ReqMPPE128", "require-mppe-128", OPT_PPPD, NULL, OPT_BOOL }, - { "L2TP.ReqMPPEStateful", "mppe-stateful", OPT_PPPD, NULL, OPT_BOOL }, - { "L2TP.NoVJ", "no-vj-comp", OPT_PPPD, NULL, OPT_BOOL }, + { "PPPD.EchoFailure", "lcp-echo-failure", OPT_PPPD, "0", OPT_STRING }, + { "PPPD.EchoInterval", "lcp-echo-interval", OPT_PPPD, "0", OPT_STRING }, + { "PPPD.Debug", "debug", OPT_PPPD, NULL, OPT_STRING }, + { "PPPD.RefuseEAP", "refuse-eap", OPT_PPPD, NULL, OPT_BOOL }, + { "PPPD.RefusePAP", "refuse-pap", OPT_PPPD, NULL, OPT_BOOL }, + { "PPPD.RefuseCHAP", "refuse-chap", OPT_PPPD, NULL, OPT_BOOL }, + { "PPPD.RefuseMSCHAP", "refuse-mschap", OPT_PPPD, NULL, OPT_BOOL }, + { "PPPD.RefuseMSCHAP2", "refuse-mschapv2", OPT_PPPD, NULL, OPT_BOOL }, + { "PPPD.NoBSDComp", "nobsdcomp", OPT_PPPD, NULL, OPT_BOOL }, + { "PPPD.NoPcomp", "nopcomp", OPT_PPPD, NULL, OPT_BOOL }, + { "PPPD.UseAccomp", "accomp", OPT_PPPD, NULL, OPT_BOOL }, + { "PPPD.NoDeflate", "nodeflate", OPT_PPPD, NULL, OPT_BOOL }, + { "PPPD.ReqMPPE", "require-mppe", OPT_PPPD, NULL, OPT_BOOL }, + { "PPPD.ReqMPPE40", "require-mppe-40", OPT_PPPD, NULL, OPT_BOOL }, + { "PPPD.ReqMPPE128", "require-mppe-128", OPT_PPPD, NULL, OPT_BOOL }, + { "PPPD.ReqMPPEStateful", "mppe-stateful", OPT_PPPD, NULL, OPT_BOOL }, + { "PPPD.NoVJ", "no-vj-comp", OPT_PPPD, NULL, OPT_BOOL }, }; static DBusConnection *connection; @@ -259,14 +259,40 @@ static int l2tp_notify(DBusMessage *msg, struct vpn_provider *provider) static int l2tp_save(struct vpn_provider *provider, GKeyFile *keyfile) { const char *option; + connman_bool_t l2tp_option, pppd_option; int i; for (i = 0; i < (int)ARRAY_SIZE(pppd_options); i++) { - if (strncmp(pppd_options[i].cm_opt, "L2TP.", 5) == 0) { + l2tp_option = pppd_option = FALSE; + + if (strncmp(pppd_options[i].cm_opt, "L2TP.", 5) == 0) + l2tp_option = TRUE; + + if (strncmp(pppd_options[i].cm_opt, "PPPD.", 5) == 0) + pppd_option = TRUE; + + if (l2tp_option == TRUE || pppd_option == TRUE) { option = vpn_provider_get_string(provider, - pppd_options[i].cm_opt); - if (option == NULL) - continue; + pppd_options[i].cm_opt); + if (option == NULL) { + /* +* Check if the option prefix is L2TP as the +* PPPD options were using L2TP prefix earlier. +*/ + char *l2tp_str; + + if (pppd_option == FALSE) + continue; + + l2tp_str = g_strdup_printf("L2TP.%s", + &pppd_options[i].cm_opt[5]); + option = vpn_provider_get_string(provider, + l2tp_str); + g_free(l2tp_str); + + if (option == NULL) +
[PATCH v5 03/16] l2tp: Fixed the nodeflate pppd option name
--- vpn/plugins/l2tp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vpn/plugins/l2tp.c b/vpn/plugins/l2tp.c index 15f5128..dce0e21 100644 --- a/vpn/plugins/l2tp.c +++ b/vpn/plugins/l2tp.c @@ -107,7 +107,7 @@ struct { { "L2TP.NoBSDComp", "nobsdcomp", OPT_PPPD, NULL, OPT_BOOL }, { "L2TP.NoPcomp", "nopcomp", OPT_PPPD, NULL, OPT_BOOL }, { "L2TP.UseAccomp", "accomp", OPT_PPPD, NULL, OPT_BOOL }, - { "L2TP.NoDeflate", "nodeflatey", OPT_PPPD, NULL, OPT_BOOL }, + { "L2TP.NoDeflate", "nodeflate", OPT_PPPD, NULL, OPT_BOOL }, { "L2TP.ReqMPPE", "require-mppe", OPT_PPPD, NULL, OPT_BOOL }, { "L2TP.ReqMPPE40", "require-mppe-40", OPT_PPPD, NULL, OPT_BOOL }, { "L2TP.ReqMPPE128", "require-mppe-128", OPT_PPPD, NULL, OPT_BOOL }, -- 1.7.11.4 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH v5 04/16] l2tp: Added rx and tx bps pppd options
--- vpn/plugins/l2tp.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/vpn/plugins/l2tp.c b/vpn/plugins/l2tp.c index dce0e21..2355357 100644 --- a/vpn/plugins/l2tp.c +++ b/vpn/plugins/l2tp.c @@ -76,6 +76,8 @@ struct { } pppd_options[] = { { "L2TP.User", "name", OPT_ALL, NULL, OPT_STRING }, { "L2TP.BPS", "bps", OPT_L2, NULL, OPT_STRING }, + { "L2TP.TXBPS", "tx bps", OPT_L2, NULL, OPT_STRING }, + { "L2TP.RXBPS", "rx bps", OPT_L2, NULL, OPT_STRING }, { "L2TP.LengthBit", "length bit", OPT_L2, NULL, OPT_STRING }, { "L2TP.Challenge", "challenge", OPT_L2, NULL, OPT_STRING }, { "L2TP.DefaultRoute", "defaultroute", OPT_L2, NULL, OPT_STRING }, -- 1.7.11.4 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH v5 15/16] TODO: Add note about removal of L2TP and PPTP prefix for PPP options
--- TODO | 10 ++ 1 file changed, 10 insertions(+) diff --git a/TODO b/TODO index b81a41d..dfb018c 100644 --- a/TODO +++ b/TODO @@ -189,6 +189,16 @@ VPN Complexity: C4 Owner: Jukka Rissanen +- L2TP & PPTP compatibility prefix removal + + Priority: Medium + Complexity: C1 + When: connman 2.0 + + The VPN config file provisioning patchset contains code that makes + PPP options to be marked by "PPPD." prefix. The code supports also + old "L2TP." and "PPTP." prefix for PPP options. Remove the compatibility + code and only allow "PPPD." prefix for PPP options. Tools = -- 1.7.11.4 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH v5 16/16] main: Create VPN_STORAGEDIR when starting up
Eventually all VPN directories from STORAGEDIR is to be migrated into VPN_STORAGEDIR --- vpn/main.c | 10 ++ 1 file changed, 10 insertions(+) diff --git a/vpn/main.c b/vpn/main.c index 8fd830c..d72fa74 100644 --- a/vpn/main.c +++ b/vpn/main.c @@ -273,12 +273,22 @@ int main(int argc, char *argv[]) perror("Failed to create state directory"); } + /* +* At some point the VPN stuff is migrated into VPN_STORAGEDIR +* and this mkdir() call can be removed. +*/ if (mkdir(STORAGEDIR, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) < 0) { if (errno != EEXIST) perror("Failed to create storage directory"); } + if (mkdir(VPN_STORAGEDIR, S_IRUSR | S_IWUSR | S_IXUSR | + S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) < 0) { + if (errno != EEXIST) + perror("Failed to create VPN storage directory"); + } + umask(0077); main_loop = g_main_loop_new(NULL, FALSE); -- 1.7.11.4 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH v5 02/16] config: Read only wifi config
--- include/provision.h | 2 +- plugins/wifi.c | 2 +- src/config.c| 6 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/include/provision.h b/include/provision.h index f154d4f..d6d7c72 100644 --- a/include/provision.h +++ b/include/provision.h @@ -42,7 +42,7 @@ struct connman_config_entry { connman_bool_t hidden; }; -struct connman_config_entry **connman_config_get_entries(void); +struct connman_config_entry **connman_config_get_entries(const char *type); void connman_config_free_entries(struct connman_config_entry **entries); #ifdef __cplusplus diff --git a/plugins/wifi.c b/plugins/wifi.c index 1e9d28c..4b097fc 100644 --- a/plugins/wifi.c +++ b/plugins/wifi.c @@ -424,7 +424,7 @@ static int get_hidden_connections(int max_ssids, /* * Check if there are any hidden AP that needs to be provisioned. */ - entries = connman_config_get_entries(); + entries = connman_config_get_entries("wifi"); for (i = 0; entries && entries[i]; i++) { int len; diff --git a/src/config.c b/src/config.c index 686d8ce..6321663 100644 --- a/src/config.c +++ b/src/config.c @@ -842,7 +842,7 @@ int __connman_config_provision_service_ident(struct connman_service *service, return ret; } -struct connman_config_entry **connman_config_get_entries(void) +struct connman_config_entry **connman_config_get_entries(const char *type) { GHashTableIter iter_file, iter_config; gpointer value, key; @@ -866,6 +866,10 @@ struct connman_config_entry **connman_config_get_entries(void) &value) == TRUE) { struct connman_config_service *config = value; + if (type != NULL && + g_strcmp0(config->type, type) != 0) + continue; + entries[i] = g_try_new0(struct connman_config_entry, 1); if (entries[i] == NULL) -- 1.7.11.4 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH v5 14/16] vpn-provider: Add extra whitespace
--- vpn/vpn-provider.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vpn/vpn-provider.c b/vpn/vpn-provider.c index f530348..36db938 100644 --- a/vpn/vpn-provider.c +++ b/vpn/vpn-provider.c @@ -300,7 +300,7 @@ static void set_user_networks(struct vpn_provider *provider, GSList *networks) GSList *list; for (list = networks; list != NULL; list = g_slist_next(list)) { - struct vpn_route *route= list->data; + struct vpn_route *route = list->data; if (__vpn_provider_append_user_route(provider, route->family, route->network, -- 1.7.11.4 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH v5 00/16] VPN provisioning support
Hi, v5 - ignore route if address family cannot be determined in patch 13 v4 - VPN config files are now in VPN_STORAGEDIR which is by default /var/lib/connman-vpn v3: - rebase against current head v2: - Split the patchset into smaller chunks as requested by Wagi - Use the new functions in inotify.c - Documentation clarifications in patch 7 - Added TODO entry to remove the compatibility functions in L2TP and PPTP VPN plugins v1: This patchset adds support for provisioning VPN services from a .config file. The VPN provisioining works the same way as the wifi service provisioning. User can create a config file in /var/lib/connman/vpn directory and information in that file is used to create a provider in connman-vpnd. The VPN config is only read by connman-vpnd process. Cheers, Jukka Jukka Rissanen (16): config: Remove obsolete definition config: Read only wifi config l2tp: Fixed the nodeflate pppd option name l2tp: Added rx and tx bps pppd options l2tp: Use PPPD prefix for pppd specific options pptp: Use PPPD prefix for pppd specific options doc: VPN config file specification storage: Add function to load provider configuration file vpn-provider: Initial .config file support vpn-config: Provision providers from .config file vpn-provider: Type string in provider needs to be in lower case vpn-provider: Remove unprovisioned providers at startup vpn-provider: Add route support in vpn config file vpn-provider: Add extra whitespace TODO: Add note about removal of L2TP and PPTP prefix for PPP options main: Create VPN_STORAGEDIR when starting up Makefile.am | 7 +- TODO | 10 + doc/vpn-config-format.txt | 215 + include/provision.h | 2 +- plugins/wifi.c| 2 +- src/config.c | 8 +- src/connman.h | 1 + src/storage.c | 16 ++ vpn/main.c| 14 ++ vpn/plugins/l2tp.c| 70 -- vpn/plugins/pptp.c| 62 +++-- vpn/vpn-config.c | 598 ++ vpn/vpn-provider.c| 327 ++--- vpn/vpn.h | 11 +- 14 files changed, 1266 insertions(+), 77 deletions(-) create mode 100644 doc/vpn-config-format.txt create mode 100644 vpn/vpn-config.c -- 1.7.11.4 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH v5 01/16] config: Remove obsolete definition
--- src/config.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/config.c b/src/config.c index 6a5b12c..686d8ce 100644 --- a/src/config.c +++ b/src/config.c @@ -68,8 +68,6 @@ static GSList *protected_services = NULL; static connman_bool_t cleanup = FALSE; -#define INTERNAL_CONFIG_PREFIX "__internal" - /* Definition of possible strings in the .config files */ #define CONFIG_KEY_NAME"Name" #define CONFIG_KEY_DESC"Description" -- 1.7.11.4 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
Re: [PATCH 3/8] vpn-provider: Setting VPN properties will send PropertyChanged signal
On Fri, 2013-02-15 at 12:23 +0200, Jukka Rissanen wrote: > Hi Tomasz, > > On 15.02.2013 10:49, Tomasz Bursztyka wrote: > > Hi Jukka, > > > >> enum { > >> -USER_ROUTES_CHANGED = 0x01, > >> +USER_ROUTES_CHANGED = 0x01, > >> SERVER_ROUTES_CHANGED = 0x02, > >> +TYPE_CHANGED = 0x04, > >> +NAME_CHANGED = 0x08, > >> +HOST_CHANGED = 0x10, > >> +DOMAIN_CHANGED= 0x20, > >> +SETTINGS_CHANGED = 0x40, > >> }; > > > > VPN_PROVIDER_ as a prefix for all the keys maybe? > > I am not sure about that one, I like the shorter version ;) > The enums are local to the file anyway. > > Patrik, what is the verdict :) I think the code should call provider_property_changed() directly for all the independent properties at least. It seems that also the existing USER_ROUTES_CHANGED can be updated immediately. The only two places where get_user_networks() is called to fetch new values is in set_property() where the old value will be removed and __vpn_provider_create() where a new value is created. In any case an equal number of property change messages are sent over D-Bus with no difference whether 100ms is waited or whether the update is sent immediately. For SERVER_ROUTES_CHANGED it seems that the server can push new routes at will, but appending new ones to already existing ones must be handled by the code already. Thus the question is whether those server route updates almost always come in many separate messages from the external vpn application to create the need for having extra code waiting 100ms before sending updates. It seems we could take the simpler code path here also by sending a property change each and every time a server route is appended, but I don't know what the average number of server routes per vpn is in real life. Any ideas/number of routes? Cheers, Patrik ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
Re: [PATCH v4 13/16] vpn-provider: Add route support in vpn config file
Hi, On Fri, 2013-02-15 at 12:19 +0200, Jukka Rissanen wrote: > + family = connman_inet_check_ipaddress(network); > + if (family < 0) { > + DBG("Cannot get address family of %s (%d/%s)", > network, > + family, gai_strerror(family)); > + if (strstr(network, ":") != NULL) { > + DBG("Guessing it is IPv6"); > + family = AF_INET6; > + } else { > + DBG("Guessing it is IPv4"); > + family = AF_INET; > + } > + } Here we should fail if connman_inet_check_ipaddress() returns something else than AF_INET6 or AF_INET. The function returns < 0 if it's not a numeric address. Cheers, Patrik ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
Re: [PATCH] iptables: Cannot flush all rules without API to set them
On Mon, 2013-02-18 at 10:40 +0200, Patrik Flykt wrote: > Currently there exists no API where iptables rules can be set. The > flush > code does not change the default chain policy at the moment, so any > pre-existing iptables rules setting default policy to reject and > relying > on individual iptables rules allowing packets going through will > prevent > all IP communication. > > For the time being disable iptables flush on init. Thus please be > careful > with iptables rules. Applied. Patrik ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
Re: [PATCH] iptables: Cannot flush all rules without API to set them
Hi Patrik, On 18.02.2013 09:40, Patrik Flykt wrote: Currently there exists no API where iptables rules can be set. The flush code does not change the default chain policy at the moment, so any pre-existing iptables rules setting default policy to reject and relying on individual iptables rules allowing packets going through will prevent all IP communication. For the time being disable iptables flush on init. Thus please be careful with iptables rules. Ack. So we need to start talking about how such an API looks like. What kind of iptables rules do you have in mind? Simple things like iptables -A INPUT -p tcp --dport http -j ACCEPT iptables -A INPUT -p tcp --dport ssh -j ACCEPT Would that be something we could express as (a first shot into the dark, probably too simple) Service API: Properties array{string} OpenPorts [readwrite] [experimental] A list of ports which are are accessible from remote hosts. If the global FirewallPolicy setting is set to disabled then this Property is ignored. The entries can be either well known names, such as "ssh" or "http" or port numbers. It is also possible to provide a range of ports, e.g. "2900-3000". And then the glogal setting in main.conf # The global firewall policy. The default value is disabled which means # all ports are open by default. If FirewallPolicy is set to enabled # no port will be accessible from a remote host. # The default value is disabled # FirewallPolicy = disabled cheers, daniel ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH v1 20/20] session: Reorder shutdown sequence
From: Daniel Wagner The core wants to call the destroy function from the plugin. Therefore we need to move __connman_session_cleanup() before the __connman_plugin_cleanup(). We also need to take care not to access the session_hash in remove_policy() function since that table has already been destroyed. --- src/main.c| 2 +- src/session.c | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main.c b/src/main.c index e21d056..0532abe 100644 --- a/src/main.c +++ b/src/main.c @@ -675,11 +675,11 @@ int main(int argc, char *argv[]) __connman_wpad_cleanup(); __connman_dhcpv6_cleanup(); __connman_dhcp_cleanup(); + __connman_session_cleanup(); __connman_plugin_cleanup(); __connman_provider_cleanup(); __connman_connection_cleanup(); __connman_timeserver_cleanup(); - __connman_session_cleanup(); __connman_detect_cleanup(); __connman_proxy_cleanup(); __connman_task_cleanup(); diff --git a/src/session.c b/src/session.c index 365c71c..ce7aa18 100644 --- a/src/session.c +++ b/src/session.c @@ -359,6 +359,9 @@ static void remove_policy(struct connman_session_policy *policy) gpointer key, value; struct connman_session *session; + if (session_hash == NULL) + return; + DBG("policy %p name %s", policy, policy->name); g_hash_table_iter_init(&iter, session_hash); -- 1.8.1.3.566.gaa39828 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH v1 19/20] session_policy_local: Do not free policy on load error
From: Daniel Wagner When we open the policy file and try to parse we might run into an error. Instead of freeing the policy we just need to reset it to the defaults and then try to apply the new settings. We should reallyt not unref the policy on the error case because the policy lifetime is attached to the lifetime of the file not on the result of the parsing. --- plugins/session_policy_local.c | 17 + 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/plugins/session_policy_local.c b/plugins/session_policy_local.c index 1658412..d65da82 100644 --- a/plugins/session_policy_local.c +++ b/plugins/session_policy_local.c @@ -398,6 +398,8 @@ static int load_policy(struct policy_data *policy) char *str, **tokens; int i, err = 0; + connman_session_set_default_config(config); + pathname = g_strdup_printf("%s/%s", POLICYDIR, policy->filename); err = load_keyfile(pathname, &keyfile); @@ -420,8 +422,6 @@ static int load_policy(struct policy_data *policy) if (str != NULL) { config->roaming_policy = connman_session_parse_roaming_policy(str); g_free(str); - } else { - config->roaming_policy = CONNMAN_SESSION_ROAMING_POLICY_DEFAULT; } str = g_key_file_get_string(keyfile, "Default", "ConnectionType", @@ -429,20 +429,18 @@ static int load_policy(struct policy_data *policy) if (str != NULL) { config->type = connman_session_parse_connection_type(str); g_free(str); - } else { - config->type = CONNMAN_SESSION_TYPE_ANY; } config->ecall = g_key_file_get_boolean(keyfile, "Default", "EmergencyCall", NULL); - g_slist_free(config->allowed_bearers); - config->allowed_bearers = NULL; - str = g_key_file_get_string(keyfile, "Default", "AllowedBearers", NULL); if (str != NULL) { + g_slist_free(config->allowed_bearers); + config->allowed_bearers = NULL; + tokens = g_strsplit(str, " ", 0); for (i = 0; tokens[i] != NULL; i++) { @@ -454,9 +452,6 @@ static int load_policy(struct policy_data *policy) g_free(str); g_strfreev(tokens); - } else { - config->allowed_bearers = g_slist_append(NULL, - GINT_TO_POINTER(CONNMAN_SERVICE_TYPE_UNKNOWN)); } g_key_file_free(keyfile); @@ -525,7 +520,6 @@ static void notify_handler(struct inotify_event *event, if (err < 0) { connman_warn("Loading policy file '%s' failed with %s", filename, strerror(-err)); - policy_unref(policy); return; } @@ -543,7 +537,6 @@ static void notify_handler(struct inotify_event *event, if (err < 0) { connman_warn("Loading policy file '%s' failed with %s", filename, strerror(-err)); - remove_policy(policy); return; } } -- 1.8.1.3.566.gaa39828 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH v1 18/20] session_policy_local: Add some more debug infos
From: Daniel Wagner --- plugins/session_policy_local.c | 24 ++-- 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/plugins/session_policy_local.c b/plugins/session_policy_local.c index aeb4bbf..1658412 100644 --- a/plugins/session_policy_local.c +++ b/plugins/session_policy_local.c @@ -75,6 +75,8 @@ static void free_policy(gpointer user_data) { struct policy_data *policy = user_data; + DBG("policy %p", policy); + if (policy->config != NULL) g_slist_free(policy->config->allowed_bearers); @@ -126,6 +128,8 @@ static struct policy_data *create_policy(void) policy = g_new0(struct policy_data, 1); policy->refcount = 1; + DBG("policy %p", policy); + policy->config = connman_session_create_default_config(); policy_list = g_slist_prepend(policy_list, policy); @@ -461,10 +465,15 @@ static int load_policy(struct policy_data *policy) return err; } -static void update_session(struct connman_session *session) +static void update_session(struct policy_data *policy) { - if (connman_session_config_update(session) < 0) - connman_session_destroy(session); + DBG("policy %p session %p", policy, policy->session); + + if (policy->session == NULL) + return; + + if (connman_session_config_update(policy->session) < 0) + connman_session_destroy(policy->session); } static void remove_policy(struct policy_data *policy) @@ -482,7 +491,7 @@ static void remove_policy(struct policy_data *policy) return; connman_session_set_default_config(policy->config); - update_session(policy->session); + update_session(policy); } static void notify_handler(struct inotify_event *event, @@ -546,8 +555,7 @@ static void notify_handler(struct inotify_event *event, return; } - if (policy->session != NULL) - update_session(policy->session); + update_session(policy); } static void read_policies(void) @@ -586,6 +594,8 @@ static int session_policy_local_init(void) { int err; + DBG(""); + /* If the dir doesn't exist, create it */ if (g_file_test(POLICYDIR, G_FILE_TEST_IS_DIR) == FALSE) { if (mkdir(POLICYDIR, MODE) < 0) { @@ -634,6 +644,8 @@ err: static void session_policy_local_exit(void) { + DBG(""); + g_hash_table_destroy(session_hash); g_hash_table_destroy(file_hash); -- 1.8.1.3.566.gaa39828 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH v1 17/20] session_policy_local: Retrieve UID from session user
From: Daniel Wagner When the session core ask to create a configuration, then we first ask the D-Bus server which UID the session belongs to. If possible we also ask for the SELinux context. Then we try to figure out which file containts the configuration for UID/SElinux identification. The SELinux identification has higher priority than UID. It is possible to run a mixed configuration but not really recommended. There might be dragons. --- plugins/session_policy_local.c | 93 ++ 1 file changed, 85 insertions(+), 8 deletions(-) diff --git a/plugins/session_policy_local.c b/plugins/session_policy_local.c index c28b856..aeb4bbf 100644 --- a/plugins/session_policy_local.c +++ b/plugins/session_policy_local.c @@ -27,6 +27,8 @@ #include #include #include +#include +#include #include @@ -52,12 +54,18 @@ static GSList *policy_list; struct create_data { struct connman_session *session; + char *user; + uid_t uid; + gid_t gid; }; struct policy_data { int refcount; char *filename; char *lsm_ctx; /* The Linux Security Module Context */ + char *user; + uid_t uid; + gid_t gid; struct connman_session *session; struct connman_session_config *config; @@ -72,6 +80,7 @@ static void free_policy(gpointer user_data) g_free(policy->filename); g_free(policy->lsm_ctx); + g_free(policy->user); g_free(policy->config); g_free(policy); } @@ -152,7 +161,8 @@ static struct policy_data *find_policy_by_file(const char *filename) for (list = policy_list; list != NULL; list = list->next) { policy = list->data; - if (g_strcmp0(policy->lsm_ctx, filename) != 0) + if (g_strcmp0(policy->lsm_ctx, filename) != 0 && + g_strcmp0(policy->user, filename) != 0) continue; return policy; @@ -161,7 +171,8 @@ static struct policy_data *find_policy_by_file(const char *filename) return NULL; } -static struct policy_data *find_policy_by_session(const char *lsm_ctx) +static struct policy_data *find_policy_by_session(const char *lsm_ctx, + const char *user) { GSList *list; struct policy_data *policy; @@ -169,7 +180,8 @@ static struct policy_data *find_policy_by_session(const char *lsm_ctx) for (list = policy_list; list != NULL; list = list->next) { policy = list->data; - if (g_strcmp0(policy->filename, lsm_ctx) != 0) + if (g_strcmp0(policy->filename, lsm_ctx) != 0 && + g_strcmp0(policy->filename, user) != 0) continue; return policy; @@ -203,13 +215,16 @@ static void selinux_context_reply(int error, goto done; } - policy = find_policy_by_session(ident); + policy = find_policy_by_session(ident, data->user); if (policy == NULL) policy = create_policy(); else policy_ref(policy); policy->lsm_ctx = g_strdup(ident); + policy->user = data->user; + policy->uid = data->uid; + policy->gid = data->gid; policy->session = data->session; g_hash_table_replace(session_hash, data->session, policy); @@ -224,6 +239,69 @@ done: g_free(ctx); } +static void get_uid_reply(int error, unsigned int uid, void *user_data) +{ + struct cb_data *cbd = user_data; + connman_session_config_cb_t cb = cbd->cb; + struct create_data *data = cbd->data; + struct policy_data *policy; + const char *owner; + struct passwd *pwd; + struct connman_session_config *config = NULL; + + DBG("session %p uid %d", data->session, uid); + + if (error < 0) + goto done; + + errno = 0; + pwd = getpwuid((uid_t)uid); + if (pwd == NULL) { + if (errno != 0) + error = -errno; + else + error = -EINVAL; + goto done; + } + + data->user = g_strdup(pwd->pw_name); + data->uid = pwd->pw_uid; + data->gid = pwd->pw_gid; + + owner = connman_session_get_owner(data->session); + + error = connman_dbus_get_selinux_context(connection, owner, + selinux_context_reply, cbd); + if (error == 0) { + /* +* We are able to ask for a SELinux context. Let's defer the +* creation of the session config until we get the answer +* from D-Bus. +*/ + return; + } + + policy = find_policy_by_session(NULL, data->user); + if (policy == NULL) + policy = create_policy(); + else + policy_ref(policy); + +
[PATCH v1 16/20] dbus: Add connman_dbus_get_connnection_unix_user()
From: Daniel Wagner --- include/dbus.h | 9 +++ src/dbus.c | 84 ++ 2 files changed, 93 insertions(+) diff --git a/include/dbus.h b/include/dbus.h index 07b44ab..cb4d34c 100644 --- a/include/dbus.h +++ b/include/dbus.h @@ -171,6 +171,15 @@ static inline void connman_dbus_dict_append_fixed_array(DBusMessageIter *dict, dbus_bool_t connman_dbus_validate_ident(const char *ident); char *connman_dbus_encode_string(const char *value); +typedef void (* connman_dbus_get_connection_unix_user_cb_t) (int error, + unsigned int uid, + void *user_data); + +int connman_dbus_get_connection_unix_user(DBusConnection *connection, + const char *bus_name, + connman_dbus_get_connection_unix_user_cb_t cb, + void *user_data); + typedef void (* connman_dbus_get_context_cb_t) (int error, const unsigned char *context, void *user_data); diff --git a/src/dbus.c b/src/dbus.c index 7c69b87..63d189e 100644 --- a/src/dbus.c +++ b/src/dbus.c @@ -406,6 +406,90 @@ dbus_bool_t __connman_dbus_append_objpath_dict_array(DBusMessage *msg, return TRUE; } +static void get_connection_unix_user_reply(DBusPendingCall *call, void *user_data) +{ + struct cb_data *cbd = user_data; + connman_dbus_get_connection_unix_user_cb_t cb = cbd->cb; + DBusMessageIter iter; + DBusMessage *reply; + unsigned char *context = NULL; + int err = 0; + unsigned int uid; + + reply = dbus_pending_call_steal_reply(call); + + if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR) { + DBG("Failed to retrieve SELinux context"); + err = -EIO; + goto done; + } + + if (dbus_message_has_signature(reply, "u") == FALSE) { + DBG("Message signature is wrong"); + err = -EINVAL; + goto done; + } + + dbus_message_iter_init(reply, &iter); + dbus_message_iter_get_basic(&iter, &uid); + +done: + (*cb)(err, uid, cbd->user_data); + + dbus_message_unref(reply); + + dbus_pending_call_unref(call); +} + +int connman_dbus_get_connection_unix_user(DBusConnection *connection, + const char *bus_name, + connman_dbus_get_connection_unix_user_cb_t cb, + void *user_data) +{ + struct cb_data *cbd = cb_data_new(cb, user_data); + DBusPendingCall *call; + DBusMessage *msg = NULL; + int err; + + msg = dbus_message_new_method_call(DBUS_SERVICE_DBUS, DBUS_PATH_DBUS, + DBUS_INTERFACE_DBUS, + "GetConnectionUnixUser"); + if (msg == NULL) { + DBG("Can't allocate new message"); + err = -ENOMEM; + goto err; + } + + dbus_message_append_args(msg, DBUS_TYPE_STRING, &bus_name, + DBUS_TYPE_INVALID); + + if (dbus_connection_send_with_reply(connection, msg, + &call, -1) == FALSE) { + DBG("Failed to execute method call"); + err = -EINVAL; + goto err; + } + + if (call == NULL) { + DBG("D-Bus connection not available"); + err = -EINVAL; + goto err; + } + + dbus_pending_call_set_notify(call, get_connection_unix_user_reply, + cbd, g_free); + + dbus_message_unref(msg); + + return 0; + +err: + dbus_message_unref(msg); + g_free(cbd); + + return err; +} + static unsigned char *parse_context(DBusMessage *msg) { DBusMessageIter iter, array; -- 1.8.1.3.566.gaa39828 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH v1 15/20] dbus: Use callback helpers
From: Daniel Wagner Use the global callback helpers instead using the local version. --- include/dbus.h | 7 --- plugins/session_policy_local.c | 10 +- src/dbus.c | 30 +++--- 3 files changed, 16 insertions(+), 31 deletions(-) diff --git a/include/dbus.h b/include/dbus.h index c00488e..07b44ab 100644 --- a/include/dbus.h +++ b/include/dbus.h @@ -171,12 +171,13 @@ static inline void connman_dbus_dict_append_fixed_array(DBusMessageIter *dict, dbus_bool_t connman_dbus_validate_ident(const char *ident); char *connman_dbus_encode_string(const char *value); -typedef void (* connman_dbus_get_context_cb_t) (const unsigned char *context, - void *user_data, int err); +typedef void (* connman_dbus_get_context_cb_t) (int error, + const unsigned char *context, + void *user_data); int connman_dbus_get_selinux_context(DBusConnection *connection, const char *service, - connman_dbus_get_context_cb_t func, + connman_dbus_get_context_cb_t cb, void *user_data); #ifdef __cplusplus diff --git a/plugins/session_policy_local.c b/plugins/session_policy_local.c index 9366cb0..c28b856 100644 --- a/plugins/session_policy_local.c +++ b/plugins/session_policy_local.c @@ -178,8 +178,8 @@ static struct policy_data *find_policy_by_session(const char *lsm_ctx) return NULL; } -static void selinux_context_reply(const unsigned char *context, void *user_data, - int err) +static void selinux_context_reply(int error, + const unsigned char *context, void *user_data) { struct cb_data *cbd = user_data; connman_session_config_cb_t cb = cbd->cb; @@ -190,7 +190,7 @@ static void selinux_context_reply(const unsigned char *context, void *user_data, DBG("session %p", data->session); - if (err < 0) + if (error < 0) goto done; ctx = g_strdup((const gchar*)context); @@ -199,7 +199,7 @@ static void selinux_context_reply(const unsigned char *context, void *user_data, ident = parse_selinux_type(ctx); if (ident == NULL) { - err = -EINVAL; + error = -EINVAL; goto done; } @@ -216,7 +216,7 @@ static void selinux_context_reply(const unsigned char *context, void *user_data, config = policy->config; done: - (*cb)(err, data->session, config, cbd->user_data); + (*cb)(error, data->session, config, cbd->user_data); g_free(cbd); g_free(data); diff --git a/src/dbus.c b/src/dbus.c index 70af617..7c69b87 100644 --- a/src/dbus.c +++ b/src/dbus.c @@ -406,11 +406,6 @@ dbus_bool_t __connman_dbus_append_objpath_dict_array(DBusMessage *msg, return TRUE; } -struct selinux_data { - connman_dbus_get_context_cb_t func; - void *user_data; -}; - static unsigned char *parse_context(DBusMessage *msg) { DBusMessageIter iter, array; @@ -448,7 +443,8 @@ static unsigned char *parse_context(DBusMessage *msg) static void selinux_get_context_reply(DBusPendingCall *call, void *user_data) { - struct selinux_data *data = user_data; + struct cb_data *cbd = user_data; + connman_dbus_get_context_cb_t cb = cbd->cb; DBusMessage *reply; unsigned char *context = NULL; int err = 0; @@ -470,7 +466,7 @@ static void selinux_get_context_reply(DBusPendingCall *call, void *user_data) context = parse_context(reply); done: - (*data->func)(context, data->user_data, err); + (*cb)(err, context, cbd->user_data); g_free(context); @@ -481,23 +477,14 @@ done: int connman_dbus_get_selinux_context(DBusConnection *connection, const char *service, - connman_dbus_get_context_cb_t func, + connman_dbus_get_context_cb_t cb, void *user_data) { - struct selinux_data *data; + struct cb_data *cbd = cb_data_new(cb, user_data); DBusPendingCall *call; DBusMessage *msg = NULL; int err; - if (func == NULL) - return -EINVAL; - - data = g_try_new0(struct selinux_data, 1); - if (data == NULL) { - DBG("Can't allocate data structure"); - return -ENOMEM; - } - msg = dbus_message_new_method_call(DBUS_SERVICE_DBUS, DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS, "GetConnectionSELinuxSecurityContext"); @@ -523,11 +510,8 @@ int connman_dbus_get_selinux_context(DBusConnection *connection, goto err; } -
[PATCH v1 14/20] session_policy_local: Use callback helpers
From: Daniel Wagner Use the generic callback helpers to encapsulate struct create_data. In a later patch we will add some more data elemets to struct create_data. That is the reason why it is not remove here. --- plugins/session_policy_local.c | 16 +--- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/plugins/session_policy_local.c b/plugins/session_policy_local.c index 0ffa512..9366cb0 100644 --- a/plugins/session_policy_local.c +++ b/plugins/session_policy_local.c @@ -52,8 +52,6 @@ static GSList *policy_list; struct create_data { struct connman_session *session; - connman_session_config_cb_t cb; - void *user_data; }; struct policy_data { @@ -183,7 +181,9 @@ static struct policy_data *find_policy_by_session(const char *lsm_ctx) static void selinux_context_reply(const unsigned char *context, void *user_data, int err) { - struct create_data *data = user_data; + struct cb_data *cbd = user_data; + connman_session_config_cb_t cb = cbd->cb; + struct create_data *data = cbd->data; struct policy_data *policy; struct connman_session_config *config = NULL; char *ident = NULL, *ctx = NULL; @@ -216,8 +216,9 @@ static void selinux_context_reply(const unsigned char *context, void *user_data, config = policy->config; done: - (*data->cb)(err, data->session, config, data->user_data); + (*cb)(err, data->session, config, cbd->user_data); + g_free(cbd); g_free(data); g_free(ident); g_free(ctx); @@ -227,6 +228,7 @@ static int policy_local_create(struct connman_session *session, connman_session_config_cb_t cb, void *user_data) { + struct cb_data *cbd = cb_data_new(cb, user_data); struct create_data *data; const char *owner; int err; @@ -234,19 +236,19 @@ static int policy_local_create(struct connman_session *session, DBG("session %p", session); data = g_new0(struct create_data, 1); + cbd->data = data; data->session = session; - data->cb = cb; - data->user_data = user_data; owner = connman_session_get_owner(session); err = connman_dbus_get_selinux_context(connection, owner, selinux_context_reply, - data); + cbd); if (err < 0) { connman_error("Could not get SELinux context"); g_free(data); + g_free(cbd); return err; } -- 1.8.1.3.566.gaa39828 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH v1 13/20] session: Add "_t" postfix to callback typedef
From: Daniel Wagner Be more consistent with the rest. Also shorten the a bit to verbose name of the callback function. --- include/session.h | 8 plugins/session_policy_local.c | 8 src/session.c | 10 +- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/include/session.h b/include/session.h index cf32e48..62c303c 100644 --- a/include/session.h +++ b/include/session.h @@ -59,16 +59,16 @@ struct connman_session_config { GSList *allowed_bearers; }; -typedef int (* connman_session_config_cb) (struct connman_session *session, +typedef int (* connman_session_config_cb_t) (int error, + struct connman_session *session, struct connman_session_config *config, - void *user_data, int err); + void *user_data); struct connman_session_policy { const char *name; int priority; int (*create)(struct connman_session *session, - connman_session_config_cb callback, - void *user_data); + connman_session_config_cb_t cb, void *user_data); void (*destroy)(struct connman_session *session); }; diff --git a/plugins/session_policy_local.c b/plugins/session_policy_local.c index 55264ed..0ffa512 100644 --- a/plugins/session_policy_local.c +++ b/plugins/session_policy_local.c @@ -52,7 +52,7 @@ static GSList *policy_list; struct create_data { struct connman_session *session; - connman_session_config_cb callback; + connman_session_config_cb_t cb; void *user_data; }; @@ -216,7 +216,7 @@ static void selinux_context_reply(const unsigned char *context, void *user_data, config = policy->config; done: - (*data->callback)(data->session, config, data->user_data, err); + (*data->cb)(err, data->session, config, data->user_data); g_free(data); g_free(ident); @@ -224,7 +224,7 @@ done: } static int policy_local_create(struct connman_session *session, - connman_session_config_cb callback, + connman_session_config_cb_t cb, void *user_data) { struct create_data *data; @@ -236,7 +236,7 @@ static int policy_local_create(struct connman_session *session, data = g_new0(struct create_data, 1); data->session = session; - data->callback = callback; + data->cb = cb; data->user_data = user_data; owner = connman_session_get_owner(session); diff --git a/src/session.c b/src/session.c index b7b0a1f..365c71c 100644 --- a/src/session.c +++ b/src/session.c @@ -313,7 +313,7 @@ static void cleanup_user_config(struct user_config *user_config) } static int create_policy_config(struct connman_session *session, - connman_session_config_cb callback, + connman_session_config_cb_t cb, struct user_config *user_config) { struct connman_session_config *config; @@ -326,10 +326,10 @@ static int create_policy_config(struct connman_session *session, return -ENOMEM; } - return callback(session, config, user_config, 0); + return cb(0, session, config, user_config); } - return (*session->policy->create)(session, callback, user_config); + return (*session->policy->create)(session, cb, user_config); } static void probe_policy(struct connman_session_policy *policy) @@ -1616,9 +1616,9 @@ static const GDBusMethodTable session_methods[] = { { }, }; -static int session_create_cb(struct connman_session *session, +static int session_create_cb(int err, struct connman_session *session, struct connman_session_config *config, - void *user_data, int err) + void *user_data) { DBusMessage *reply; struct user_config *user_config = user_data; -- 1.8.1.3.566.gaa39828 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH v1 11/20] test-session: Add unit test for session_policy_local
From: Daniel Wagner Use the UID as identification. --- unit/test-session.c | 156 1 file changed, 156 insertions(+) diff --git a/unit/test-session.c b/unit/test-session.c index d6da8d7..4041e88 100644 --- a/unit/test-session.c +++ b/unit/test-session.c @@ -24,11 +24,16 @@ #endif #include +#include +#include +#include #include #include "test-connman.h" +#define POLICYDIR STORAGEDIR "/session_policy_local" + enum test_session_state { TEST_SESSION_STATE_0 = 0, TEST_SESSION_STATE_1 = 1, @@ -495,6 +500,154 @@ static gboolean test_session_connect_free_ride(gpointer data) return FALSE; } +static void policy_save(GKeyFile *keyfile, char *pathname) +{ + gchar *data = NULL; + gsize length = 0; + GError *error = NULL; + + data = g_key_file_to_data(keyfile, &length, NULL); + + if(!g_file_set_contents(pathname, data, length, &error)) { + DBG("Failed to store information: %s", error->message); + g_error_free(error); + g_assert(0); + } + + g_free(data); +} + +static void policy_allowed_bearers(const char *allowed_bearers) +{ + struct passwd *pwd; + uid_t uid; + char *pathname; + GKeyFile *keyfile; + + LOG("update to '%s'", allowed_bearers); + + uid = getuid(); + pwd = getpwuid(uid); + g_assert(pwd != NULL); + + pathname = g_strdup_printf("%s/%s", POLICYDIR, pwd->pw_name); + keyfile = g_key_file_new(); + g_key_file_set_string(keyfile, "Default", "AllowedBearers", + allowed_bearers); + + policy_save(keyfile, pathname); + + g_free(pathname); + g_key_file_free(keyfile); +} + +static void policy_remove_file(void) +{ + struct passwd *pwd; + uid_t uid; + char *pathname; + + uid = getuid(); + pwd = getpwuid(uid); + g_assert(pwd != NULL); + + pathname = g_strdup_printf("%s/%s", POLICYDIR, pwd->pw_name); + unlink(pathname); + g_free(pathname); +} + +static void test_session_policy_notify(struct test_session *session) +{ + enum test_session_state state = get_session_state(session); + enum test_session_state next_state = state; + DBusMessage *msg; + + LOG("state %d session %p %s state %d", state, session, + session->notify_path, session->info->state); + + switch (state) { + case TEST_SESSION_STATE_0: + if (session->info->state == CONNMAN_SESSION_STATE_DISCONNECTED) + next_state = TEST_SESSION_STATE_1; + break; + case TEST_SESSION_STATE_1: + if (session->info->state >= CONNMAN_SESSION_STATE_CONNECTED) + next_state = TEST_SESSION_STATE_2; + break; + case TEST_SESSION_STATE_2: + if (session->info->state == CONNMAN_SESSION_STATE_DISCONNECTED) + next_state = TEST_SESSION_STATE_3; + default: + break; + } + + if (state == next_state) + return; + + set_session_state(session, next_state); + + LOG("next_state %d", next_state); + + switch (next_state) { + case TEST_SESSION_STATE_1: + policy_allowed_bearers("ethernet"); + + msg = session_connect(session->connection, session); + g_assert(msg != NULL); + dbus_message_unref(msg); + return; + case TEST_SESSION_STATE_2: + policy_allowed_bearers(""); + return; + case TEST_SESSION_STATE_3: + policy_remove_file(); + util_session_cleanup(session); + util_idle_call(session->fix, util_quit_loop, + util_session_destroy); + return; + default: + return; + } +} + +static gboolean test_session_policy(gpointer data) +{ + struct test_fix *fix = data; + struct test_session *session; + + /* +* +---+ +* | START | +* +---+ +* | +* | write policy AllowedBearers = ethernet +* v +* +---+ +* | FOO-CONNECTED | +* +---+ +* | +* | write policy AllowedBearers = +* v +* +---+ +* |END| +* +---+ +*/ + + util_session_create(fix, 1); + session = fix->session; + + session->notify_path = g_strdup("/foo"); + session->notify = test_session_policy_notify; + + util_session_init(session); + + set_session_state(session, TEST_SESSION_STATE_0); + + policy_allowed_bearers(""); + + return FALSE; +} + static connman_bool_t is_online(struct test_fix *fix) { if (g_strcmp0(fix->ma
[PATCH v1 12/20] connman: Add callback helpers
From: Daniel Wagner There is a common pattern when writing a callback function. Let's add a few helper for this. This is shamelessly stolen from oFono. --- include/types.h | 19 +++ 1 file changed, 19 insertions(+) diff --git a/include/types.h b/include/types.h index 0f671ec..051151a 100644 --- a/include/types.h +++ b/include/types.h @@ -22,6 +22,8 @@ #ifndef __CONNMAN_TYPES_H #define __CONNMAN_TYPES_H +#include + #ifdef __cplusplus extern "C" { #endif @@ -38,6 +40,23 @@ typedef int connman_bool_t; typedef unsigned char connman_uint8_t; typedef unsigned short connman_uint16_t; +struct cb_data { + void *cb; + void *user_data; + void *data; +}; + +static inline struct cb_data *cb_data_new(void *cb, void *user_data) +{ + struct cb_data *ret; + + ret = g_new0(struct cb_data, 1); + ret->cb = cb; + ret->user_data = user_data; + + return ret; +} + #ifdef __cplusplus } #endif -- 1.8.1.3.566.gaa39828 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH v1 10/20] session_policy_local: Split LSM context ident from filename
From: Daniel Wagner Separate the id which associates the file and the session. find_policy_by_file() and find_policy_by_lsm() contain the logic which associates the configuration file with a session. --- plugins/session_policy_local.c | 66 -- 1 file changed, 44 insertions(+), 22 deletions(-) diff --git a/plugins/session_policy_local.c b/plugins/session_policy_local.c index a46f1b3..55264ed 100644 --- a/plugins/session_policy_local.c +++ b/plugins/session_policy_local.c @@ -59,6 +59,7 @@ struct create_data { struct policy_data { int refcount; char *filename; + char *lsm_ctx; /* The Linux Security Module Context */ struct connman_session *session; struct connman_session_config *config; @@ -72,6 +73,7 @@ static void free_policy(gpointer user_data) g_slist_free(policy->config->allowed_bearers); g_free(policy->filename); + g_free(policy->lsm_ctx); g_free(policy->config); g_free(policy); } @@ -144,6 +146,40 @@ static void policy_unref(struct policy_data *policy) free_policy(policy); }; +static struct policy_data *find_policy_by_file(const char *filename) +{ + GSList *list; + struct policy_data *policy; + + for (list = policy_list; list != NULL; list = list->next) { + policy = list->data; + + if (g_strcmp0(policy->lsm_ctx, filename) != 0) + continue; + + return policy; + } + + return NULL; +} + +static struct policy_data *find_policy_by_session(const char *lsm_ctx) +{ + GSList *list; + struct policy_data *policy; + + for (list = policy_list; list != NULL; list = list->next) { + policy = list->data; + + if (g_strcmp0(policy->filename, lsm_ctx) != 0) + continue; + + return policy; + } + + return NULL; +} + static void selinux_context_reply(const unsigned char *context, void *user_data, int err) { @@ -167,12 +203,13 @@ static void selinux_context_reply(const unsigned char *context, void *user_data, goto done; } - policy = g_hash_table_lookup(file_hash, ident); - if (policy == NULL) { + policy = find_policy_by_session(ident); + if (policy == NULL) policy = create_policy(); - policy->filename = g_strdup(ident); - } else + else policy_ref(policy); + + policy->lsm_ctx = g_strdup(ident); policy->session = data->session; g_hash_table_replace(session_hash, data->session, policy); @@ -227,6 +264,8 @@ static void policy_local_destroy(struct connman_session *session) return; g_hash_table_remove(session_hash, session); + g_free(policy->lsm_ctx); + policy->lsm_ctx = NULL; policy->session = NULL; policy_unref(policy); } @@ -367,23 +406,6 @@ static void remove_policy(struct policy_data *policy) update_session(policy->session); } -static struct policy_data *find_policy(const char *filename) -{ - GSList *list; - struct policy_data *policy; - - for (list = policy_list; list != NULL; list = list->next) { - policy = list->data; - - if (g_strcmp0(policy->filename, filename) != 0) - continue; - - return policy; - } - - return NULL; -} - static void notify_handler(struct inotify_event *event, const char *filename) { @@ -402,7 +424,7 @@ static void notify_handler(struct inotify_event *event, /* policy != NULL can happen if the file is overwritten */ if (policy == NULL) { - policy = find_policy(filename); + policy = find_policy_by_file(filename); if (policy == NULL) policy = create_policy(); else -- 1.8.1.3.566.gaa39828 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH v1 09/20] session_policy_local: Rename ident to filename
From: Daniel Wagner ident is not shared anymore between the session policy and the file policy. Let's make this clear be renaming this member. --- plugins/session_policy_local.c | 44 +- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/plugins/session_policy_local.c b/plugins/session_policy_local.c index 90c6f1a..a46f1b3 100644 --- a/plugins/session_policy_local.c +++ b/plugins/session_policy_local.c @@ -58,7 +58,7 @@ struct create_data { struct policy_data { int refcount; - char *ident; + char *filename; struct connman_session *session; struct connman_session_config *config; @@ -71,7 +71,7 @@ static void free_policy(gpointer user_data) if (policy->config != NULL) g_slist_free(policy->config->allowed_bearers); - g_free(policy->ident); + g_free(policy->filename); g_free(policy->config); g_free(policy); } @@ -126,7 +126,7 @@ static struct policy_data *create_policy(void) static struct policy_data *policy_ref(struct policy_data *policy) { - DBG("%p %s ref %d", policy, policy->ident, policy->refcount + 1); + DBG("%p %s ref %d", policy, policy->filename, policy->refcount + 1); __sync_fetch_and_add(&policy->refcount, 1); @@ -135,7 +135,7 @@ static struct policy_data *policy_ref(struct policy_data *policy) static void policy_unref(struct policy_data *policy) { - DBG(" %p %s ref %d", policy, policy->ident, policy->refcount - 1); + DBG(" %p %s ref %d", policy, policy->filename, policy->refcount - 1); if (__sync_fetch_and_sub(&policy->refcount, 1) != 1) return; @@ -170,7 +170,7 @@ static void selinux_context_reply(const unsigned char *context, void *user_data, policy = g_hash_table_lookup(file_hash, ident); if (policy == NULL) { policy = create_policy(); - policy->ident = g_strdup(ident); + policy->filename = g_strdup(ident); } else policy_ref(policy); policy->session = data->session; @@ -276,7 +276,7 @@ static int load_policy(struct policy_data *policy) char *str, **tokens; int i, err = 0; - pathname = g_strdup_printf("%s/%s", POLICYDIR, policy->ident); + pathname = g_strdup_printf("%s/%s", POLICYDIR, policy->filename); err = load_keyfile(pathname, &keyfile); if (err < 0) { @@ -357,7 +357,7 @@ static void remove_policy(struct policy_data *policy) if (policy->session != NULL) update = TRUE; - g_hash_table_remove(file_hash, policy->ident); + g_hash_table_remove(file_hash, policy->filename); policy_unref(policy); if (update == FALSE) @@ -367,7 +367,7 @@ static void remove_policy(struct policy_data *policy) update_session(policy->session); } -static struct policy_data *find_policy(const char *ident) +static struct policy_data *find_policy(const char *filename) { GSList *list; struct policy_data *policy; @@ -375,7 +375,7 @@ static struct policy_data *find_policy(const char *ident) for (list = policy_list; list != NULL; list = list->next) { policy = list->data; - if (g_strcmp0(policy->ident, ident) != 0) + if (g_strcmp0(policy->filename, filename) != 0) continue; return policy; @@ -385,61 +385,61 @@ static struct policy_data *find_policy(const char *ident) } static void notify_handler(struct inotify_event *event, -const char *ident) +const char *filename) { struct policy_data *policy; int err; - DBG("event %x file %s", event->mask, ident); + DBG("event %x file %s", event->mask, filename); - if (ident == NULL) + if (filename == NULL) return; - policy = g_hash_table_lookup(file_hash, ident); + policy = g_hash_table_lookup(file_hash, filename); if (event->mask & (IN_CREATE | IN_MOVED_TO)) { - connman_info("Policy added for '%s'", ident); + connman_info("Policy added for '%s'", filename); /* policy != NULL can happen if the file is overwritten */ if (policy == NULL) { - policy = find_policy(ident); + policy = find_policy(filename); if (policy == NULL) policy = create_policy(); else policy_ref(policy); - policy->ident = g_strdup(ident); + policy->filename = g_strdup(filename); } err = load_policy(policy); if (err < 0) { connman_warn("Loading policy file '%s' failed with %s", -
[PATCH v1 08/20] session_policy_local: Rename policy_hash to file_hash
From: Daniel Wagner Which reflects the new usage of the hash much better. --- plugins/session_policy_local.c | 20 ++-- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/plugins/session_policy_local.c b/plugins/session_policy_local.c index b0c049f..90c6f1a 100644 --- a/plugins/session_policy_local.c +++ b/plugins/session_policy_local.c @@ -46,7 +46,7 @@ static DBusConnection *connection; -static GHashTable *policy_hash; +static GHashTable *file_hash; static GHashTable *session_hash; static GSList *policy_list; @@ -167,7 +167,7 @@ static void selinux_context_reply(const unsigned char *context, void *user_data, goto done; } - policy = g_hash_table_lookup(policy_hash, ident); + policy = g_hash_table_lookup(file_hash, ident); if (policy == NULL) { policy = create_policy(); policy->ident = g_strdup(ident); @@ -357,7 +357,7 @@ static void remove_policy(struct policy_data *policy) if (policy->session != NULL) update = TRUE; - g_hash_table_remove(policy_hash, policy->ident); + g_hash_table_remove(file_hash, policy->ident); policy_unref(policy); if (update == FALSE) @@ -395,7 +395,7 @@ static void notify_handler(struct inotify_event *event, if (ident == NULL) return; - policy = g_hash_table_lookup(policy_hash, ident); + policy = g_hash_table_lookup(file_hash, ident); if (event->mask & (IN_CREATE | IN_MOVED_TO)) { connman_info("Policy added for '%s'", ident); @@ -419,7 +419,7 @@ static void notify_handler(struct inotify_event *event, return; } - g_hash_table_replace(policy_hash, + g_hash_table_replace(file_hash, g_strdup(ident), policy); } @@ -473,7 +473,7 @@ static void read_policies(void) continue; } - g_hash_table_replace(policy_hash, g_strdup(file), + g_hash_table_replace(file_hash, g_strdup(file), policy); } @@ -499,7 +499,7 @@ static int session_policy_local_init(void) session_hash = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, NULL); - policy_hash = g_hash_table_new_full(g_str_hash, g_str_equal, + file_hash = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL); err = connman_inotify_register(POLICYDIR, notify_handler); @@ -521,8 +521,8 @@ err_notify: err: if (session_hash != NULL) g_hash_table_destroy(session_hash); - if (policy_hash != NULL) - g_hash_table_destroy(policy_hash); + if (file_hash != NULL) + g_hash_table_destroy(file_hash); connman_session_policy_unregister(&session_policy_local); @@ -534,7 +534,7 @@ err: static void session_policy_local_exit(void) { g_hash_table_destroy(session_hash); - g_hash_table_destroy(policy_hash); + g_hash_table_destroy(file_hash); g_slist_free_full(policy_list, free_policy); -- 1.8.1.3.566.gaa39828 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH v1 07/20] session_policy_local: Load policy from file
From: Daniel Wagner We forgot to load the configuration when a new file is added during runtime. --- plugins/session_policy_local.c | 8 1 file changed, 8 insertions(+) diff --git a/plugins/session_policy_local.c b/plugins/session_policy_local.c index b20084d..b0c049f 100644 --- a/plugins/session_policy_local.c +++ b/plugins/session_policy_local.c @@ -411,6 +411,14 @@ static void notify_handler(struct inotify_event *event, policy->ident = g_strdup(ident); } + err = load_policy(policy); + if (err < 0) { + connman_warn("Loading policy file '%s' failed with %s", + ident, strerror(-err)); + policy_unref(policy); + return; + } + g_hash_table_replace(policy_hash, g_strdup(ident), policy); } -- 1.8.1.3.566.gaa39828 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH v1 06/20] session_policy_local: Use policy_hash only to track the policy files
From: Daniel Wagner Let's move the owner ship to the policy_list. The policy_hash is only used to lookup the policy data structure. This patch removes the requirement that the 'ident' is key to lookup the policy data. Now we are able to define set of rules how we want associate the file with a session. --- plugins/session_policy_local.c | 63 +- 1 file changed, 44 insertions(+), 19 deletions(-) diff --git a/plugins/session_policy_local.c b/plugins/session_policy_local.c index b0317bb..b20084d 100644 --- a/plugins/session_policy_local.c +++ b/plugins/session_policy_local.c @@ -110,22 +110,17 @@ static char *parse_selinux_type(const char *context) return ident; } -static struct policy_data *create_policy(const char *ident) +static struct policy_data *create_policy(void) { struct policy_data *policy; - DBG("ident %s", ident); - policy = g_new0(struct policy_data, 1); policy->refcount = 1; policy->config = connman_session_create_default_config(); - policy->ident = g_strdup(ident); policy_list = g_slist_prepend(policy_list, policy); - g_hash_table_replace(policy_hash, policy->ident, policy); - return policy; } @@ -146,9 +141,6 @@ static void policy_unref(struct policy_data *policy) return; policy_list = g_slist_remove(policy_list, policy); - - g_hash_table_remove(policy_hash, policy->ident); - free_policy(policy); }; @@ -176,11 +168,12 @@ static void selinux_context_reply(const unsigned char *context, void *user_data, } policy = g_hash_table_lookup(policy_hash, ident); - if (policy != NULL) { - policy_ref(policy); - policy->session = data->session; + if (policy == NULL) { + policy = create_policy(); + policy->ident = g_strdup(ident); } else - policy = create_policy(ident); + policy_ref(policy); + policy->session = data->session; g_hash_table_replace(session_hash, data->session, policy); config = policy->config; @@ -364,6 +357,7 @@ static void remove_policy(struct policy_data *policy) if (policy->session != NULL) update = TRUE; + g_hash_table_remove(policy_hash, policy->ident); policy_unref(policy); if (update == FALSE) @@ -373,12 +367,31 @@ static void remove_policy(struct policy_data *policy) update_session(policy->session); } +static struct policy_data *find_policy(const char *ident) +{ + GSList *list; + struct policy_data *policy; + + for (list = policy_list; list != NULL; list = list->next) { + policy = list->data; + + if (g_strcmp0(policy->ident, ident) != 0) + continue; + + return policy; + } + + return NULL; +} + static void notify_handler(struct inotify_event *event, const char *ident) { struct policy_data *policy; int err; + DBG("event %x file %s", event->mask, ident); + if (ident == NULL) return; @@ -387,10 +400,19 @@ static void notify_handler(struct inotify_event *event, if (event->mask & (IN_CREATE | IN_MOVED_TO)) { connman_info("Policy added for '%s'", ident); - if (policy != NULL) - policy_ref(policy); - else - policy = create_policy(ident); + /* policy != NULL can happen if the file is overwritten */ + if (policy == NULL) { + policy = find_policy(ident); + if (policy == NULL) + policy = create_policy(); + else + policy_ref(policy); + + policy->ident = g_strdup(ident); + } + + g_hash_table_replace(policy_hash, + g_strdup(ident), policy); } if (policy == NULL) @@ -433,7 +455,8 @@ static void read_policies(void) while ((file = g_dir_read_name(dir)) != NULL) { struct policy_data *policy; - policy = create_policy(file); + policy = create_policy(); + policy->ident = g_strdup(file); err = load_policy(policy); if (err < 0) { connman_warn("Loading policy file '%s' failed with %s", @@ -442,6 +465,8 @@ static void read_policies(void) continue; } + g_hash_table_replace(policy_hash, g_strdup(file), + policy); } g_dir_close(dir); @@ -467,7 +492,7 @@ static int se
[PATCH v1 05/20] session_policy_local: Print warning if loading of policy fails
From: Daniel Wagner Also continue reading the rest of the policy files when starting up. This makes the startup behavior consistent with the runtime behavior. --- plugins/session_policy_local.c | 25 +++-- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/plugins/session_policy_local.c b/plugins/session_policy_local.c index 8968d14..b0317bb 100644 --- a/plugins/session_policy_local.c +++ b/plugins/session_policy_local.c @@ -377,6 +377,7 @@ static void notify_handler(struct inotify_event *event, const char *ident) { struct policy_data *policy; + int err; if (ident == NULL) return; @@ -398,7 +399,10 @@ static void notify_handler(struct inotify_event *event, if (event->mask & IN_MODIFY) { connman_info("Policy modifed for '%s'", ident); - if (load_policy(policy) < 0) { + err = load_policy(policy); + if (err < 0) { + connman_warn("Loading policy file '%s' failed with %s", + ident, strerror(-err)); remove_policy(policy); return; } @@ -415,10 +419,10 @@ static void notify_handler(struct inotify_event *event, update_session(policy->session); } -static int read_policies(void) +static void read_policies(void) { GDir *dir; - int err = 0; + int err; DBG(""); @@ -431,14 +435,17 @@ static int read_policies(void) policy = create_policy(file); err = load_policy(policy); - if (err < 0) - break; + if (err < 0) { + connman_warn("Loading policy file '%s' failed with %s", + file, strerror(-err)); + policy_unref(policy); + continue; + } + } g_dir_close(dir); } - - return err; } static int session_policy_local_init(void) @@ -466,9 +473,7 @@ static int session_policy_local_init(void) if (err < 0) goto err; - err = read_policies(); - if (err < 0) - goto err_notify; + read_policies(); err = connman_session_policy_register(&session_policy_local); if (err < 0) -- 1.8.1.3.566.gaa39828 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH v1 03/20] session_policy_local: Do not handle small allocation
From: Daniel Wagner Let's remove the small allocations error path because glib will abort on memory exhausting anyway. Basically we remove dead code. --- plugins/session_policy_local.c | 39 --- 1 file changed, 4 insertions(+), 35 deletions(-) diff --git a/plugins/session_policy_local.c b/plugins/session_policy_local.c index 90396cf..1e3abfb 100644 --- a/plugins/session_policy_local.c +++ b/plugins/session_policy_local.c @@ -115,12 +115,10 @@ static struct policy_data *create_policy(const char *ident) DBG("ident %s", ident); - policy = g_try_new0(struct policy_data, 1); - if (policy == NULL) - return NULL; + policy = g_new0(struct policy_data, 1); + policy->refcount = 1; policy->config = connman_session_create_default_config(); - policy->refcount = 1; policy->ident = g_strdup(ident); g_hash_table_replace(policy_hash, policy->ident, policy); @@ -161,10 +159,6 @@ static void selinux_context_reply(const unsigned char *context, void *user_data, goto done; ctx = g_strdup((const gchar*)context); - if (ctx == NULL) { - err = -ENOMEM; - goto done; - } DBG("SELinux context %s", ctx); @@ -178,13 +172,8 @@ static void selinux_context_reply(const unsigned char *context, void *user_data, if (policy != NULL) { policy_ref(policy); policy->session = data->session; - } else { + } else policy = create_policy(ident); - if (policy == NULL) { - err = -ENOMEM; - goto done; - } - } g_hash_table_replace(session_hash, data->session, policy); config = policy->config; @@ -207,9 +196,7 @@ static int policy_local_create(struct connman_session *session, DBG("session %p", session); - data = g_try_new0(struct create_data, 1); - if (data == NULL) - return -ENOMEM; + data = g_new0(struct create_data, 1); data->session = session; data->callback = callback; @@ -290,8 +277,6 @@ static int load_policy(struct policy_data *policy) int i, err = 0; pathname = g_strdup_printf("%s/%s", POLICYDIR, policy->ident); - if(pathname == NULL) - return -ENOMEM; err = load_keyfile(pathname, &keyfile); if (err < 0) { @@ -350,8 +335,6 @@ static int load_policy(struct policy_data *policy) } else { config->allowed_bearers = g_slist_append(NULL, GINT_TO_POINTER(CONNMAN_SERVICE_TYPE_UNKNOWN)); - if (config->allowed_bearers == NULL) - err = -ENOMEM; } g_key_file_free(keyfile); @@ -440,11 +423,6 @@ static int read_policies(void) struct policy_data *policy; policy = create_policy(file); - if (policy == NULL) { - err = -ENOMEM; - break; - } - err = load_policy(policy); if (err < 0) break; @@ -474,17 +452,8 @@ static int session_policy_local_init(void) session_hash = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, NULL); - if (session_hash == NULL) { - err = -ENOMEM; - goto err; - } - policy_hash = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, cleanup_policy); - if (policy_hash == NULL) { - err = -ENOMEM; - goto err; - } err = connman_inotify_register(POLICYDIR, notify_handler); if (err < 0) -- 1.8.1.3.566.gaa39828 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH v1 04/20] session_policy_local: Track policy data structure in a separate list
From: Daniel Wagner We want to make the lifetime of the policy data structure independent of the policy_hash table. --- plugins/session_policy_local.c | 13 +++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/plugins/session_policy_local.c b/plugins/session_policy_local.c index 1e3abfb..8968d14 100644 --- a/plugins/session_policy_local.c +++ b/plugins/session_policy_local.c @@ -48,6 +48,7 @@ static DBusConnection *connection; static GHashTable *policy_hash; static GHashTable *session_hash; +static GSList *policy_list; struct create_data { struct connman_session *session; @@ -63,7 +64,7 @@ struct policy_data { struct connman_session_config *config; }; -static void cleanup_policy(gpointer user_data) +static void free_policy(gpointer user_data) { struct policy_data *policy = user_data; @@ -121,6 +122,8 @@ static struct policy_data *create_policy(const char *ident) policy->config = connman_session_create_default_config(); policy->ident = g_strdup(ident); + policy_list = g_slist_prepend(policy_list, policy); + g_hash_table_replace(policy_hash, policy->ident, policy); return policy; @@ -142,7 +145,11 @@ static void policy_unref(struct policy_data *policy) if (__sync_fetch_and_sub(&policy->refcount, 1) != 1) return; + policy_list = g_slist_remove(policy_list, policy); + g_hash_table_remove(policy_hash, policy->ident); + + free_policy(policy); }; static void selinux_context_reply(const unsigned char *context, void *user_data, @@ -453,7 +460,7 @@ static int session_policy_local_init(void) session_hash = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, NULL); policy_hash = g_hash_table_new_full(g_str_hash, g_str_equal, - NULL, cleanup_policy); + NULL, NULL); err = connman_inotify_register(POLICYDIR, notify_handler); if (err < 0) @@ -491,6 +498,8 @@ static void session_policy_local_exit(void) g_hash_table_destroy(session_hash); g_hash_table_destroy(policy_hash); + g_slist_free_full(policy_list, free_policy); + connman_session_policy_unregister(&session_policy_local); dbus_connection_unref(connection); -- 1.8.1.3.566.gaa39828 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH v1 02/20] session: Do not fail when creating default policy configuration
From: Daniel Wagner Do not handle the small alloc failures because glib will abort when memory is tight anyway. --- include/session.h | 2 +- plugins/session_policy_local.c | 12 +--- src/session.c | 16 +++- 3 files changed, 5 insertions(+), 25 deletions(-) diff --git a/include/session.h b/include/session.h index 47d36c5..cf32e48 100644 --- a/include/session.h +++ b/include/session.h @@ -78,7 +78,7 @@ void connman_session_policy_unregister(struct connman_session_policy *config); int connman_session_config_update(struct connman_session *session); void connman_session_destroy(struct connman_session *session); -int connman_session_set_default_config(struct connman_session_config *config); +void connman_session_set_default_config(struct connman_session_config *config); struct connman_session_config *connman_session_create_default_config(void); enum connman_session_roaming_policy connman_session_parse_roaming_policy(const char *policy); diff --git a/plugins/session_policy_local.c b/plugins/session_policy_local.c index d3e51a2..90396cf 100644 --- a/plugins/session_policy_local.c +++ b/plugins/session_policy_local.c @@ -120,11 +120,6 @@ static struct policy_data *create_policy(const char *ident) return NULL; policy->config = connman_session_create_default_config(); - if (policy->config == NULL) { - g_free(policy); - return NULL; - } - policy->refcount = 1; policy->ident = g_strdup(ident); @@ -384,12 +379,7 @@ static void remove_policy(struct policy_data *policy) if (update == FALSE) return; - err = connman_session_set_default_config(policy->config); - if (err < 0) { - connman_session_destroy(policy->session); - return; - } - + connman_session_set_default_config(policy->config); update_session(policy->session); } diff --git a/src/session.c b/src/session.c index 6916458..b7b0a1f 100644 --- a/src/session.c +++ b/src/session.c @@ -407,7 +407,7 @@ void connman_session_policy_unregister(struct connman_session_policy *policy) remove_policy(policy); } -int connman_session_set_default_config(struct connman_session_config *config) +void connman_session_set_default_config(struct connman_session_config *config) { config->priority = FALSE; config->roaming_policy = CONNMAN_SESSION_ROAMING_POLICY_DEFAULT; @@ -417,24 +417,14 @@ int connman_session_set_default_config(struct connman_session_config *config) g_slist_free(config->allowed_bearers); config->allowed_bearers = g_slist_prepend(NULL, GINT_TO_POINTER(CONNMAN_SERVICE_TYPE_UNKNOWN)); - if (config->allowed_bearers == NULL) - return -ENOMEM; - - return 0; } struct connman_session_config *connman_session_create_default_config(void) { struct connman_session_config *config; - config = g_try_new0(struct connman_session_config, 1); - if (config == NULL) - return NULL; - - if (connman_session_set_default_config(config) < 0) { - g_free(config); - return NULL; - } + config = g_new0(struct connman_session_config, 1); + connman_session_set_default_config(config); return config; } -- 1.8.1.3.566.gaa39828 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH v1 01/20] session_policy_local: Refactor SELinux context parser
From: Daniel Wagner selinux_context_reply() should handle the 'type' conversion of data it gets from D-Bus. --- plugins/session_policy_local.c | 30 +++--- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/plugins/session_policy_local.c b/plugins/session_policy_local.c index 5a8f6b8..d3e51a2 100644 --- a/plugins/session_policy_local.c +++ b/plugins/session_policy_local.c @@ -75,9 +75,9 @@ static void cleanup_policy(gpointer user_data) g_free(policy); } -static char *parse_ident(const unsigned char *context) +static char *parse_selinux_type(const char *context) { - char *str, *ident, **tokens; + char *ident, **tokens; /* * SELinux combines Role-Based Access Control (RBAC), Type @@ -97,23 +97,14 @@ static char *parse_ident(const unsigned char *context) * as haifux_t. */ - str = g_strdup((const gchar*)context); - if (str == NULL) + tokens = g_strsplit(context, ":", 0); + if (tokens == NULL) return NULL; - DBG("SELinux context %s", str); - - tokens = g_strsplit(str, ":", 0); - if (tokens == NULL) { - g_free(str); - return NULL; - } - /* Use the SELinux type as identification token. */ ident = g_strdup(tokens[2]); g_strfreev(tokens); - g_free(str); return ident; } @@ -167,14 +158,22 @@ static void selinux_context_reply(const unsigned char *context, void *user_data, struct create_data *data = user_data; struct policy_data *policy; struct connman_session_config *config = NULL; - char *ident = NULL; + char *ident = NULL, *ctx = NULL; DBG("session %p", data->session); if (err < 0) goto done; - ident = parse_ident(context); + ctx = g_strdup((const gchar*)context); + if (ctx == NULL) { + err = -ENOMEM; + goto done; + } + + DBG("SELinux context %s", ctx); + + ident = parse_selinux_type(ctx); if (ident == NULL) { err = -EINVAL; goto done; @@ -200,6 +199,7 @@ done: g_free(data); g_free(ident); + g_free(ctx); } static int policy_local_create(struct connman_session *session, -- 1.8.1.3.566.gaa39828 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH v1 00/20] Add UID support to session policies
From: Daniel Wagner Hi, This version containts several small bug fixes. Though it also unreviels a nasty use after free bug in the session core. Note this bug is not introduced by this series. Changes v1: - fixed shutdown sequence (double free) - fixed memory leaks - handle loading/parsing errors v0: - initial version cheers, daniel original cover letter: here is the initial series to allow UID matching on policy files. The first part of the series are preparation patches and some small cleanups. I need first to split the ownership of the connman_session_policy data from the policy_hash table. In the end we can rename the policy_hash to file_hash. That means we have one hash for the sessions and one for the files. The ownership is transfered to a new policy list. I think overall that should make the code also better readable. With introducing a unit test for the UID support the second part starts. A few patches are needed to add the cb_data helpers and consequently fixing up the some parts which can make use of it. The very last patch gives you finally the UID matching. There are still a few broken in this version, so this is not ready to be applied. Daniel Wagner (20): session_policy_local: Refactor SELinux context parser session: Do not fail when creating default policy configuration session_policy_local: Do not handle small allocation session_policy_local: Track policy data structure in a separate list session_policy_local: Print warning if loading of policy fails session_policy_local: Use policy_hash only to track the policy files session_policy_local: Load policy from file session_policy_local: Rename policy_hash to file_hash session_policy_local: Rename ident to filename session_policy_local: Split LSM context ident from filename test-session: Add unit test for session_policy_local connman: Add callback helpers session: Add "_t" postfix to callback typedef session_policy_local: Use callback helpers dbus: Use callback helpers dbus: Add connman_dbus_get_connnection_unix_user() session_policy_local: Retrieve UID from session user session_policy_local: Add some more debug infos session_policy_local: Do not free policy on load error session: Reorder shutdown sequence include/dbus.h | 16 +- include/session.h | 10 +- include/types.h| 19 +++ plugins/session_policy_local.c | 372 +++-- src/dbus.c | 112 ++--- src/main.c | 2 +- src/session.c | 29 ++-- unit/test-session.c| 156 + 8 files changed, 537 insertions(+), 179 deletions(-) -- 1.8.1.3.566.gaa39828 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
Re: [PATCH 2/2] gresolv: Optimize the response parser
On Fri, 2013-02-15 at 12:30 +0200, Tomasz Bursztyka wrote: > It will check first if the response belongs to a query, > before interpreting any of its content (rcode, count...). Applied, thanks! Patrik ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
Re: [PATCH (RFC) 1/2] gresolv: Do not remove a query on failure if other results are pending
On Fri, 2013-02-15 at 12:30 +0200, Tomasz Bursztyka wrote: > Fixes BMC#25973 > > In the case one of the resolving failed, the query is removed and > destroyed from the queue. So the responses of the requests sent to > the other namerservers - which might be successful - will thus be > lost since they cannot be matched anymore to their initial request. Applied, thanks! Patrik ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
Re: [PATCH] gsupplicant: Return zero for max scan SSID parameter
On Thu, 2013-02-14 at 23:37 +0200, patrik.fl...@linux.intel.com wrote: > From: Patrik Flykt > > A driver can return a valid max scan SSID value of zero. Thus no fast > scans can be done, so the code falls back to a simple scan instead. > > A value of zero is properly handled in plugins/wifi.c. An active scan > for a hidden SSID adds only the SSID parameter to the wpa_supplicant > D-Bus method call, which wpa_supplicant then handles properly. > > Some drivers also report a max scan SSID value of one. In some of the > cases that value is bogus, the driver will not be able to do a fast > scan anyway. In addition, it is questionable why only one SSID can be > fast scanned as the feature would not differ much from an active scan > for a hidden network. Thus we set the limit to two, i.e. zero or one > is treated as zero, two or more is reported as is. > > Thanks to Grant Erickson and Tomasz Bursztyka for finding and > pinpointing this issue. > > Fixes BMC#25971 I start to get a Monty Pythonesq feeling about counting now... Applied. Patrik ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH] iptables: Cannot flush all rules without API to set them
Currently there exists no API where iptables rules can be set. The flush code does not change the default chain policy at the moment, so any pre-existing iptables rules setting default policy to reject and relying on individual iptables rules allowing packets going through will prevent all IP communication. For the time being disable iptables flush on init. Thus please be careful with iptables rules. --- src/iptables.c | 12 ++-- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/src/iptables.c b/src/iptables.c index 83612b9..8fa3687 100644 --- a/src/iptables.c +++ b/src/iptables.c @@ -36,6 +36,7 @@ #include "connman.h" +void flush_table(const char *name); /* * Some comments on how the iptables API works (some of them from the @@ -2243,7 +2244,7 @@ static int flush_table_cb(struct ipt_entry *entry, int builtin, return 0; } -static void flush_table(const char *name) +void flush_table(const char *name) { GSList *chains = NULL, *list; struct connman_iptables *table; @@ -2269,13 +2270,6 @@ static void flush_table(const char *name) g_slist_free_full(chains, g_free); } -static void flush_all_chains(void) -{ - flush_table("filter"); - flush_table("mangle"); - flush_table("nat"); -} - int __connman_iptables_init(void) { DBG(""); @@ -2288,8 +2282,6 @@ int __connman_iptables_init(void) xtables_init_all(&iptables_globals, NFPROTO_IPV4); - flush_all_chains(); - return 0; } -- 1.7.10.4 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
Re: Pre-configuring an ethernet interface
On 18.02.2013 09:58, Patrik Flykt wrote: On Thu, 2013-02-14 at 13:38 +0100, Simon Busch wrote: I have a similar case where something like this is needed. Anyone already working on getting this implemented? AFAIK not at the moment. I have a few things to do before I have a chance to look at this. Patches are always welcome. I started to work on it, patches coming soon. Cheers, Jukka ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman