WPS: Add configurable option for processing credentials externally

The wps_cred_process option can be used to configure wpa_supplicant to
send received Credential attributes for external processing over
ctrl_iface and dbus. This allows external programs to update their
configuration when WPS is used to provision new networks.
This commit is contained in:
Jouni Malinen 2009-01-18 12:27:12 +02:00
parent eca6e0a9a5
commit 476621644c
7 changed files with 121 additions and 1 deletions

View file

@ -312,6 +312,17 @@ struct wpa_config {
* in * in
*/ */
char country[2]; char country[2];
/**
* wps_cred_processing - Credential processing
*
* 0 = process received credentials internally
* 1 = do not process received credentials; just pass them over
* ctrl_iface to external program(s)
* 2 = process received credentials internally and pass them over
* ctrl_iface to external program(s)
*/
int wps_cred_processing;
}; };

View file

@ -456,6 +456,7 @@ static const struct global_parse_data global_fields[] = {
{ STR_RANGE(serial_number, 0, 32) }, { STR_RANGE(serial_number, 0, 32) },
{ STR(device_type) }, { STR(device_type) },
{ FUNC(os_version) }, { FUNC(os_version) },
{ INT_RANGE(wps_cred_processing, 0, 2) },
#endif /* CONFIG_WPS */ #endif /* CONFIG_WPS */
{ FUNC(country) } { FUNC(country) }
}; };
@ -881,6 +882,9 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config)
if (WPA_GET_BE32(config->os_version)) if (WPA_GET_BE32(config->os_version))
fprintf(f, "os_version=%08x\n", fprintf(f, "os_version=%08x\n",
WPA_GET_BE32(config->os_version)); WPA_GET_BE32(config->os_version));
if (config->wps_cred_processing)
fprintf(f, "wps_cred_processing=%d\n",
config->wps_cred_processing);
#endif /* CONFIG_WPS */ #endif /* CONFIG_WPS */
if (config->country[0] && config->country[1]) { if (config->country[0] && config->country[1]) {
fprintf(f, "country=%c%c\n", fprintf(f, "country=%c%c\n",

View file

@ -251,6 +251,8 @@ static int wpa_config_read_global(struct wpa_config *config, HKEY hk)
hk, TEXT("device_type")); hk, TEXT("device_type"));
if (wpa_config_read_global_os_version(config, hk)) if (wpa_config_read_global_os_version(config, hk))
errors++; errors++;
wpa_config_read_reg_dword(hk, TEXT("wps_cred_processing"),
&config->wps_cred_processing);
#endif /* CONFIG_WPS */ #endif /* CONFIG_WPS */
return errors ? -1 : 0; return errors ? -1 : 0;
@ -573,6 +575,8 @@ static int wpa_config_write_global(struct wpa_config *config, HKEY hk)
WPA_GET_BE32(config->os_version)); WPA_GET_BE32(config->os_version));
wpa_config_write_reg_string(hk, "os_version", vbuf); wpa_config_write_reg_string(hk, "os_version", vbuf);
} }
wpa_config_write_reg_dword(hk, TEXT("wps_cred_processing"),
config->wps_cred_processing, 0);
#endif /* CONFIG_WPS */ #endif /* CONFIG_WPS */
return 0; return 0;

View file

@ -18,6 +18,7 @@
#include "eloop.h" #include "eloop.h"
#include "config.h" #include "config.h"
#include "wpa_supplicant_i.h" #include "wpa_supplicant_i.h"
#include "wps/wps.h"
#include "ctrl_iface_dbus.h" #include "ctrl_iface_dbus.h"
#include "ctrl_iface_dbus_handlers.h" #include "ctrl_iface_dbus_handlers.h"
@ -738,6 +739,63 @@ out:
} }
#ifdef CONFIG_WPS
void wpa_supplicant_dbus_notify_wps_cred(struct wpa_supplicant *wpa_s,
const struct wps_credential *cred)
{
struct ctrl_iface_dbus_priv *iface;
DBusMessage *_signal = NULL;
const char *path;
/* Do nothing if the control interface is not turned on */
if (wpa_s->global == NULL)
return;
iface = wpa_s->global->dbus_ctrl_iface;
if (iface == NULL)
return;
path = wpa_supplicant_get_dbus_path(wpa_s);
if (path == NULL) {
perror("wpa_supplicant_dbus_notify_wps_cred[dbus]: "
"interface didn't have a dbus path");
wpa_printf(MSG_ERROR,
"wpa_supplicant_dbus_notify_wps_cred[dbus]: "
"interface didn't have a dbus path; can't send "
"signal.");
return;
}
_signal = dbus_message_new_signal(path, WPAS_DBUS_IFACE_INTERFACE,
"WpsCred");
if (_signal == NULL) {
perror("wpa_supplicant_dbus_notify_wps_cred[dbus]: "
"couldn't create dbus signal; likely out of memory");
wpa_printf(MSG_ERROR,
"wpa_supplicant_dbus_notify_wps_cred[dbus]: "
"couldn't create dbus signal; likely out of "
"memory.");
return;
}
if (!dbus_message_append_args(_signal,
DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
&cred->cred_attr, cred->cred_attr_len,
DBUS_TYPE_INVALID)) {
perror("wpa_supplicant_dbus_notify_wps_cred[dbus]: "
"not enough memory to construct signal.");
wpa_printf(MSG_ERROR,
"wpa_supplicant_dbus_notify_wps_cred[dbus]: "
"not enough memory to construct signal.");
goto out;
}
dbus_connection_send(iface->con, _signal, NULL);
out:
dbus_message_unref(_signal);
}
#endif /* CONFIG_WPS */
/** /**
* integrate_with_eloop - Register our mainloop integration with dbus * integrate_with_eloop - Register our mainloop integration with dbus
* @connection: connection to the system message bus * @connection: connection to the system message bus

View file

@ -15,6 +15,8 @@
#ifndef CTRL_IFACE_DBUS_H #ifndef CTRL_IFACE_DBUS_H
#define CTRL_IFACE_DBUS_H #define CTRL_IFACE_DBUS_H
struct wps_credential;
#ifdef CONFIG_CTRL_IFACE_DBUS #ifdef CONFIG_CTRL_IFACE_DBUS
#ifndef SIGPOLL #ifndef SIGPOLL
@ -84,6 +86,8 @@ void wpa_supplicant_dbus_notify_scan_results(struct wpa_supplicant *wpa_s);
void wpa_supplicant_dbus_notify_state_change(struct wpa_supplicant *wpa_s, void wpa_supplicant_dbus_notify_state_change(struct wpa_supplicant *wpa_s,
wpa_states new_state, wpa_states new_state,
wpa_states old_state); wpa_states old_state);
void wpa_supplicant_dbus_notify_wps_cred(struct wpa_supplicant *wpa_s,
const struct wps_credential *cred);
char * wpas_dbus_decompose_object_path(const char *path, char **network, char * wpas_dbus_decompose_object_path(const char *path, char **network,
char **bssid); char **bssid);
@ -129,6 +133,12 @@ wpa_supplicant_dbus_notify_state_change(struct wpa_supplicant *wpa_s,
{ {
} }
static inline void
wpa_supplicant_dbus_notify_wps_cred(struct wpa_supplicant *wpa_s,
const struct wps_credential *cred)
{
}
static inline int static inline int
wpas_dbus_register_iface(struct wpa_supplicant *wpa_s) wpas_dbus_register_iface(struct wpa_supplicant *wpa_s)
{ {

View file

@ -190,6 +190,13 @@ fast_reauth=1
# 4-octet operating system version number (hex string) # 4-octet operating system version number (hex string)
#os_version=01020300 #os_version=01020300
# Credential processing
# 0 = process received credentials internally (default)
# 1 = do not process received credentials; just pass them over ctrl_iface to
# external program(s)
# 2 = process received credentials internally and pass them over ctrl_iface
# to external program(s)
#wps_cred_processing=0
# network block # network block
# #

View file

@ -23,6 +23,7 @@
#include "eloop.h" #include "eloop.h"
#include "uuid.h" #include "uuid.h"
#include "wpa_ctrl.h" #include "wpa_ctrl.h"
#include "ctrl_iface_dbus.h"
#include "eap_common/eap_wsc_common.h" #include "eap_common/eap_wsc_common.h"
#include "wps_supplicant.h" #include "wps_supplicant.h"
@ -46,6 +47,15 @@ int wpas_wps_eapol_cb(struct wpa_supplicant *wpa_s)
return 1; return 1;
} }
if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS && wpa_s->current_ssid) {
wpa_printf(MSG_DEBUG, "WPS: Registration completed - waiting "
"for external credential processing");
wpas_clear_wps(wpa_s);
wpa_supplicant_deauthenticate(wpa_s,
WLAN_REASON_DEAUTH_LEAVING);
return 1;
}
return 0; return 0;
} }
@ -56,11 +66,27 @@ static int wpa_supplicant_wps_cred(void *ctx,
struct wpa_supplicant *wpa_s = ctx; struct wpa_supplicant *wpa_s = ctx;
struct wpa_ssid *ssid = wpa_s->current_ssid; struct wpa_ssid *ssid = wpa_s->current_ssid;
if ((wpa_s->conf->wps_cred_processing == 1 ||
wpa_s->conf->wps_cred_processing == 2) && cred->cred_attr) {
size_t blen = cred->cred_attr_len * 2 + 1;
char *buf = os_malloc(blen);
if (buf) {
wpa_snprintf_hex(buf, blen,
cred->cred_attr, cred->cred_attr_len);
wpa_msg(wpa_s, MSG_INFO, "%s%s",
WPS_EVENT_CRED_RECEIVED, buf);
os_free(buf);
}
wpa_supplicant_dbus_notify_wps_cred(wpa_s, cred);
} else
wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_CRED_RECEIVED); wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_CRED_RECEIVED);
wpa_hexdump_key(MSG_DEBUG, "WPS: Received Credential attribute", wpa_hexdump_key(MSG_DEBUG, "WPS: Received Credential attribute",
cred->cred_attr, cred->cred_attr_len); cred->cred_attr, cred->cred_attr_len);
if (wpa_s->conf->wps_cred_processing == 1)
return 0;
if (cred->auth_type != WPS_AUTH_OPEN && if (cred->auth_type != WPS_AUTH_OPEN &&
cred->auth_type != WPS_AUTH_SHARED && cred->auth_type != WPS_AUTH_SHARED &&
cred->auth_type != WPS_AUTH_WPAPSK && cred->auth_type != WPS_AUTH_WPAPSK &&