diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c index 7e2a5b44f..bbc720ed2 100644 --- a/wpa_supplicant/config.c +++ b/wpa_supplicant/config.c @@ -15,6 +15,7 @@ #include "includes.h" #include "common.h" +#include "utils/uuid.h" #include "crypto/sha1.h" #include "rsn_supp/wpa.h" #include "eap_peer/eap.h" @@ -2165,3 +2166,234 @@ void wpa_config_debug_dump_networks(struct wpa_config *config) } } #endif /* CONFIG_NO_STDOUT_DEBUG */ + + +struct global_parse_data { + char *name; + int (*parser)(const struct global_parse_data *data, + struct wpa_config *config, int line, const char *value); + void *param1, *param2, *param3; +}; + + +static int wpa_global_config_parse_int(const struct global_parse_data *data, + struct wpa_config *config, int line, + const char *pos) +{ + int *dst; + dst = (int *) (((u8 *) config) + (long) data->param1); + *dst = atoi(pos); + wpa_printf(MSG_DEBUG, "%s=%d", data->name, *dst); + + if (data->param2 && *dst < (long) data->param2) { + wpa_printf(MSG_ERROR, "Line %d: too small %s (value=%d " + "min_value=%ld)", line, data->name, *dst, + (long) data->param2); + *dst = (long) data->param2; + return -1; + } + + if (data->param3 && *dst > (long) data->param3) { + wpa_printf(MSG_ERROR, "Line %d: too large %s (value=%d " + "max_value=%ld)", line, data->name, *dst, + (long) data->param3); + *dst = (long) data->param3; + return -1; + } + + return 0; +} + + +static int wpa_global_config_parse_str(const struct global_parse_data *data, + struct wpa_config *config, int line, + const char *pos) +{ + size_t len; + char **dst, *tmp; + + len = os_strlen(pos); + if (data->param2 && len < (size_t) data->param2) { + wpa_printf(MSG_ERROR, "Line %d: too short %s (len=%lu " + "min_len=%ld)", line, data->name, + (unsigned long) len, (long) data->param2); + return -1; + } + + if (data->param3 && len > (size_t) data->param3) { + wpa_printf(MSG_ERROR, "Line %d: too long %s (len=%lu " + "max_len=%ld)", line, data->name, + (unsigned long) len, (long) data->param3); + return -1; + } + + tmp = os_strdup(pos); + if (tmp == NULL) + return -1; + + dst = (char **) (((u8 *) config) + (long) data->param1); + os_free(*dst); + *dst = tmp; + wpa_printf(MSG_DEBUG, "%s='%s'", data->name, *dst); + + return 0; +} + + +static int wpa_config_process_country(const struct global_parse_data *data, + struct wpa_config *config, int line, + const char *pos) +{ + if (!pos[0] || !pos[1]) { + wpa_printf(MSG_DEBUG, "Invalid country set"); + return -1; + } + config->country[0] = pos[0]; + config->country[1] = pos[1]; + wpa_printf(MSG_DEBUG, "country='%c%c'", + config->country[0], config->country[1]); + return 0; +} + + +static int wpa_config_process_load_dynamic_eap( + const struct global_parse_data *data, struct wpa_config *config, + int line, const char *so) +{ + int ret; + wpa_printf(MSG_DEBUG, "load_dynamic_eap=%s", so); + ret = eap_peer_method_load(so); + if (ret == -2) { + wpa_printf(MSG_DEBUG, "This EAP type was already loaded - not " + "reloading."); + } else if (ret) { + wpa_printf(MSG_ERROR, "Line %d: Failed to load dynamic EAP " + "method '%s'.", line, so); + return -1; + } + + return 0; +} + + +#ifdef CONFIG_WPS + +static int wpa_config_process_uuid(const struct global_parse_data *data, + struct wpa_config *config, int line, + const char *pos) +{ + char buf[40]; + if (uuid_str2bin(pos, config->uuid)) { + wpa_printf(MSG_ERROR, "Line %d: invalid UUID", line); + return -1; + } + uuid_bin2str(config->uuid, buf, sizeof(buf)); + wpa_printf(MSG_DEBUG, "uuid=%s", buf); + return 0; +} + + +static int wpa_config_process_os_version(const struct global_parse_data *data, + struct wpa_config *config, int line, + const char *pos) +{ + if (hexstr2bin(pos, config->os_version, 4)) { + wpa_printf(MSG_ERROR, "Line %d: invalid os_version", line); + return -1; + } + wpa_printf(MSG_DEBUG, "os_version=%08x", + WPA_GET_BE32(config->os_version)); + return 0; +} + +#endif /* CONFIG_WPS */ + + +#ifdef OFFSET +#undef OFFSET +#endif /* OFFSET */ +/* OFFSET: Get offset of a variable within the wpa_config structure */ +#define OFFSET(v) ((void *) &((struct wpa_config *) 0)->v) + +#define FUNC(f) #f, wpa_config_process_ ## f, OFFSET(f), NULL, NULL +#define FUNC_NO_VAR(f) #f, wpa_config_process_ ## f, NULL, NULL, NULL +#define _INT(f) #f, wpa_global_config_parse_int, OFFSET(f) +#define INT(f) _INT(f), NULL, NULL +#define INT_RANGE(f, min, max) _INT(f), (void *) min, (void *) max +#define _STR(f) #f, wpa_global_config_parse_str, OFFSET(f) +#define STR(f) _STR(f), NULL, NULL +#define STR_RANGE(f, min, max) _STR(f), (void *) min, (void *) max + +static const struct global_parse_data global_fields[] = { +#ifdef CONFIG_CTRL_IFACE + { STR(ctrl_interface) }, + { STR(ctrl_interface_group) } /* deprecated */, +#endif /* CONFIG_CTRL_IFACE */ + { INT_RANGE(eapol_version, 1, 2) }, + { INT(ap_scan) }, + { INT(fast_reauth) }, + { STR(opensc_engine_path) }, + { STR(pkcs11_engine_path) }, + { STR(pkcs11_module_path) }, + { STR(driver_param) }, + { INT(dot11RSNAConfigPMKLifetime) }, + { INT(dot11RSNAConfigPMKReauthThreshold) }, + { INT(dot11RSNAConfigSATimeout) }, +#ifndef CONFIG_NO_CONFIG_WRITE + { INT(update_config) }, +#endif /* CONFIG_NO_CONFIG_WRITE */ + { FUNC_NO_VAR(load_dynamic_eap) }, +#ifdef CONFIG_WPS + { FUNC(uuid) }, + { STR_RANGE(device_name, 0, 32) }, + { STR_RANGE(manufacturer, 0, 64) }, + { STR_RANGE(model_name, 0, 32) }, + { STR_RANGE(model_number, 0, 32) }, + { STR_RANGE(serial_number, 0, 32) }, + { STR(device_type) }, + { FUNC(os_version) }, + { STR(config_methods) }, + { INT_RANGE(wps_cred_processing, 0, 2) }, +#endif /* CONFIG_WPS */ + { FUNC(country) }, + { INT(bss_max_count) }, + { INT_RANGE(filter_ssids, 0, 1) } +}; + +#undef FUNC +#undef _INT +#undef INT +#undef INT_RANGE +#undef _STR +#undef STR +#undef STR_RANGE +#define NUM_GLOBAL_FIELDS (sizeof(global_fields) / sizeof(global_fields[0])) + + +int wpa_config_process_global(struct wpa_config *config, char *pos, int line) +{ + size_t i; + int ret = 0; + + for (i = 0; i < NUM_GLOBAL_FIELDS; i++) { + const struct global_parse_data *field = &global_fields[i]; + size_t flen = os_strlen(field->name); + if (os_strncmp(pos, field->name, flen) != 0 || + pos[flen] != '=') + continue; + + if (field->parser(field, config, line, pos + flen + 1)) { + wpa_printf(MSG_ERROR, "Line %d: failed to " + "parse '%s'.", line, pos); + ret = -1; + } + break; + } + if (i == NUM_GLOBAL_FIELDS) { + wpa_printf(MSG_ERROR, "Line %d: unknown global field '%s'.", + line, pos); + ret = -1; + } + + return ret; +} diff --git a/wpa_supplicant/config.h b/wpa_supplicant/config.h index bd01b8840..a75524ccc 100644 --- a/wpa_supplicant/config.h +++ b/wpa_supplicant/config.h @@ -384,6 +384,10 @@ void wpa_config_debug_dump_networks(struct wpa_config *config); #endif /* CONFIG_NO_STDOUT_DEBUG */ +/* Prototypes for common functions from config.c */ +int wpa_config_process_global(struct wpa_config *config, char *pos, int line); + + /* Prototypes for backend specific functions from the selected config_*.c */ /** diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c index 5f0704576..07dc19723 100644 --- a/wpa_supplicant/config_file.c +++ b/wpa_supplicant/config_file.c @@ -22,7 +22,6 @@ #include "config.h" #include "base64.h" #include "uuid.h" -#include "eap_peer/eap_methods.h" /** @@ -270,238 +269,6 @@ static int wpa_config_process_blob(struct wpa_config *config, FILE *f, #endif /* CONFIG_NO_CONFIG_BLOBS */ -struct global_parse_data { - char *name; - int (*parser)(const struct global_parse_data *data, - struct wpa_config *config, int line, const char *value); - void *param1, *param2, *param3; -}; - - -static int wpa_config_parse_int(const struct global_parse_data *data, - struct wpa_config *config, int line, - const char *pos) -{ - int *dst; - dst = (int *) (((u8 *) config) + (long) data->param1); - *dst = atoi(pos); - wpa_printf(MSG_DEBUG, "%s=%d", data->name, *dst); - - if (data->param2 && *dst < (long) data->param2) { - wpa_printf(MSG_ERROR, "Line %d: too small %s (value=%d " - "min_value=%ld)", line, data->name, *dst, - (long) data->param2); - *dst = (long) data->param2; - return -1; - } - - if (data->param3 && *dst > (long) data->param3) { - wpa_printf(MSG_ERROR, "Line %d: too large %s (value=%d " - "max_value=%ld)", line, data->name, *dst, - (long) data->param3); - *dst = (long) data->param3; - return -1; - } - - return 0; -} - - -static int wpa_config_parse_str(const struct global_parse_data *data, - struct wpa_config *config, int line, - const char *pos) -{ - size_t len; - char **dst, *tmp; - - len = os_strlen(pos); - if (data->param2 && len < (size_t) data->param2) { - wpa_printf(MSG_ERROR, "Line %d: too short %s (len=%lu " - "min_len=%ld)", line, data->name, - (unsigned long) len, (long) data->param2); - return -1; - } - - if (data->param3 && len > (size_t) data->param3) { - wpa_printf(MSG_ERROR, "Line %d: too long %s (len=%lu " - "max_len=%ld)", line, data->name, - (unsigned long) len, (long) data->param3); - return -1; - } - - tmp = os_strdup(pos); - if (tmp == NULL) - return -1; - - dst = (char **) (((u8 *) config) + (long) data->param1); - os_free(*dst); - *dst = tmp; - wpa_printf(MSG_DEBUG, "%s='%s'", data->name, *dst); - - return 0; -} - - -static int wpa_config_process_country(const struct global_parse_data *data, - struct wpa_config *config, int line, - const char *pos) -{ - if (!pos[0] || !pos[1]) { - wpa_printf(MSG_DEBUG, "Invalid country set"); - return -1; - } - config->country[0] = pos[0]; - config->country[1] = pos[1]; - wpa_printf(MSG_DEBUG, "country='%c%c'", - config->country[0], config->country[1]); - return 0; -} - - -static int wpa_config_process_load_dynamic_eap( - const struct global_parse_data *data, struct wpa_config *config, - int line, const char *so) -{ - int ret; - wpa_printf(MSG_DEBUG, "load_dynamic_eap=%s", so); - ret = eap_peer_method_load(so); - if (ret == -2) { - wpa_printf(MSG_DEBUG, "This EAP type was already loaded - not " - "reloading."); - } else if (ret) { - wpa_printf(MSG_ERROR, "Line %d: Failed to load dynamic EAP " - "method '%s'.", line, so); - return -1; - } - - return 0; -} - - -#ifdef CONFIG_WPS - -static int wpa_config_process_uuid(const struct global_parse_data *data, - struct wpa_config *config, int line, - const char *pos) -{ - char buf[40]; - if (uuid_str2bin(pos, config->uuid)) { - wpa_printf(MSG_ERROR, "Line %d: invalid UUID", line); - return -1; - } - uuid_bin2str(config->uuid, buf, sizeof(buf)); - wpa_printf(MSG_DEBUG, "uuid=%s", buf); - return 0; -} - - -static int wpa_config_process_os_version(const struct global_parse_data *data, - struct wpa_config *config, int line, - const char *pos) -{ - if (hexstr2bin(pos, config->os_version, 4)) { - wpa_printf(MSG_ERROR, "Line %d: invalid os_version", line); - return -1; - } - wpa_printf(MSG_DEBUG, "os_version=%08x", - WPA_GET_BE32(config->os_version)); - return 0; -} - -#endif /* CONFIG_WPS */ - - -#ifdef OFFSET -#undef OFFSET -#endif /* OFFSET */ -/* OFFSET: Get offset of a variable within the wpa_config structure */ -#define OFFSET(v) ((void *) &((struct wpa_config *) 0)->v) - -#define FUNC(f) #f, wpa_config_process_ ## f, OFFSET(f), NULL, NULL -#define FUNC_NO_VAR(f) #f, wpa_config_process_ ## f, NULL, NULL, NULL -#define _INT(f) #f, wpa_config_parse_int, OFFSET(f) -#define INT(f) _INT(f), NULL, NULL -#define INT_RANGE(f, min, max) _INT(f), (void *) min, (void *) max -#define _STR(f) #f, wpa_config_parse_str, OFFSET(f) -#define STR(f) _STR(f), NULL, NULL -#define STR_RANGE(f, min, max) _STR(f), (void *) min, (void *) max - -static const struct global_parse_data global_fields[] = { -#ifdef CONFIG_CTRL_IFACE - { STR(ctrl_interface) }, - { STR(ctrl_interface_group) } /* deprecated */, -#endif /* CONFIG_CTRL_IFACE */ - { INT_RANGE(eapol_version, 1, 2) }, - { INT(ap_scan) }, - { INT(fast_reauth) }, - { STR(opensc_engine_path) }, - { STR(pkcs11_engine_path) }, - { STR(pkcs11_module_path) }, - { STR(driver_param) }, - { INT(dot11RSNAConfigPMKLifetime) }, - { INT(dot11RSNAConfigPMKReauthThreshold) }, - { INT(dot11RSNAConfigSATimeout) }, -#ifndef CONFIG_NO_CONFIG_WRITE - { INT(update_config) }, -#endif /* CONFIG_NO_CONFIG_WRITE */ - { FUNC_NO_VAR(load_dynamic_eap) }, -#ifdef CONFIG_WPS - { FUNC(uuid) }, - { STR_RANGE(device_name, 0, 32) }, - { STR_RANGE(manufacturer, 0, 64) }, - { STR_RANGE(model_name, 0, 32) }, - { STR_RANGE(model_number, 0, 32) }, - { STR_RANGE(serial_number, 0, 32) }, - { STR(device_type) }, - { FUNC(os_version) }, - { STR(config_methods) }, - { INT_RANGE(wps_cred_processing, 0, 2) }, -#endif /* CONFIG_WPS */ - { FUNC(country) }, - { INT(bss_max_count) }, - { INT_RANGE(filter_ssids, 0, 1) } -}; - -#undef FUNC -#undef _INT -#undef INT -#undef INT_RANGE -#undef _STR -#undef STR -#undef STR_RANGE -#define NUM_GLOBAL_FIELDS (sizeof(global_fields) / sizeof(global_fields[0])) - - -static int wpa_config_process_global(struct wpa_config *config, char *pos, - int line) -{ - size_t i; - int ret = 0; - - for (i = 0; i < NUM_GLOBAL_FIELDS; i++) { - const struct global_parse_data *field = &global_fields[i]; - size_t flen = os_strlen(field->name); - if (os_strncmp(pos, field->name, flen) != 0 || - pos[flen] != '=') - continue; - - if (field->parser(field, config, line, pos + flen + 1)) { - wpa_printf(MSG_ERROR, "Line %d: failed to " - "parse '%s'.", line, pos); - ret = -1; - } - break; - } - if (i == NUM_GLOBAL_FIELDS) { - wpa_printf(MSG_ERROR, "Line %d: unknown global field '%s'.", - line, pos); - ret = -1; - } - - return ret; -} - - struct wpa_config * wpa_config_read(const char *name) { FILE *f;