WPA_Supplicant slave mode patch
- From: Tim Warberg <twarberg gmail com>
- To: networkmanager-list gnome org
- Subject: WPA_Supplicant slave mode patch
- Date: Sat, 11 Jun 2005 15:16:43 +0200
Hi,
Had some spare time (didn't feel like reading) and "finished" up
wpa_supplicant changes. Added a slave mode where config can be
changed dynamically through socket.
I've added a "network" command to socket interface. Takes 1 argument,
a string of network options (same options as in config file) separated
by ; and ended by ;;. Example:
"network ssid="something";proto=WPA;key_mgmt=WPA-PSK;pairwise=TKIP;group=TKIP;psk="verysecretpassphrase";;"
Also added a way to chance ap_scan(See config file) behavior: "set AP_MODE # "
where # is mode number.
If we don't want any other wireless scanning, ap_scan must be 0. In
this mode wpa_supplicant won't do any WPA association and must be done
by NM. See association function in each of the wpa_supplicant drivers.
Slave mode is activated by wpa_supplicant option -S
Only testet with WPA-PSK connection at my parents. I'll test WPA
EAP-TLS when I'm back home.
Todo:
non hardcoded ctrl socket file path
--
Tim Warberg
Email: twarberg at gmail.com
diff -ruN wpa_supplicant-0.3.8/config.c wpa_supplicant-0.3.8_slave/config.c
--- wpa_supplicant-0.3.8/config.c 2005-02-05 05:19:10.000000000 +0100
+++ wpa_supplicant-0.3.8_slave/config.c 2005-06-11 13:23:07.000000000 +0200
@@ -820,6 +820,145 @@
return 0;
}
+struct wpa_ssid * wpa_ssid_from_iface(char * cmd) {
+ struct wpa_ssid *ssid;
+ int errors = 0, i, end = 0, chr;
+ char *pos, *pos2;
+
+ ssid = (struct wpa_ssid *) malloc(sizeof(*ssid));
+ if (ssid == NULL)
+ return NULL;
+ memset(ssid, 0, sizeof(*ssid));
+ ssid->id = 0;
+
+ ssid->proto = WPA_PROTO_WPA | WPA_PROTO_RSN;
+ ssid->pairwise_cipher = WPA_CIPHER_CCMP | WPA_CIPHER_TKIP;
+ ssid->group_cipher = WPA_CIPHER_CCMP | WPA_CIPHER_TKIP |
+ WPA_CIPHER_WEP104 | WPA_CIPHER_WEP40;
+ ssid->key_mgmt = WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_IEEE8021X;
+ ssid->eapol_flags = EAPOL_FLAG_REQUIRE_KEY_UNICAST |
+ EAPOL_FLAG_REQUIRE_KEY_BROADCAST;
+ ssid->eap_workaround = (unsigned int) -1;
+
+ pos = malloc(strlen(cmd));
+
+ while (TRUE) {
+ if (strcmp(cmd, ";") == 0) {
+ end = 1;
+ break;
+ }
+
+ chr = 0;
+ memset(pos, 0, strlen(cmd));
+
+ while((strlen(cmd) > 0) && (strncmp(cmd, ";", 1) != 0)) {
+ pos[chr] = *cmd;
+ chr++;
+ cmd++;
+ }
+ *cmd++ = '\0';
+
+ pos2 = strchr(pos, '=');
+ if (pos2 == NULL) {
+ wpa_printf(MSG_ERROR, "Char %d: Invalid SSID line "
+ "'%s'.", *cmd, pos);
+ errors++;
+ continue;
+ }
+
+ *pos2++ = '\0';
+ if (*pos2 == '"') {
+ if (strchr(pos2 + 1, '"') == NULL) {
+ wpa_printf(MSG_ERROR, "Char %d: invalid "
+ "quotation '%s'.", *cmd, pos2);
+ errors++;
+ continue;
+ }
+ }
+
+ for (i = 0; i < NUM_SSID_FIELDS; i++) {
+ struct parse_data *field = &ssid_fields[i];
+ if (strcmp(pos, field->name) != 0)
+ continue;
+
+ field->ssid = ssid;
+ if (field->parser(field, *cmd, pos2)) {
+ wpa_printf(MSG_ERROR, "Char %d: failed to "
+ "parse %s '%s'.", *cmd, pos, pos2);
+ errors++;
+ }
+ break;
+ }
+ if (i == NUM_SSID_FIELDS) {
+ wpa_printf(MSG_ERROR, "Unknown network field "
+ "'%s'.", pos);
+ errors++;
+ }
+ }
+
+ if (!end) {
+ wpa_printf(MSG_ERROR, "Network block was not "
+ "terminated properly.");
+ errors++;
+ }
+
+ if (ssid->passphrase) {
+ if (ssid->psk_set) {
+ wpa_printf(MSG_ERROR, "Both PSK and "
+ "passphrase configured.");
+ errors++;
+ }
+ pbkdf2_sha1(ssid->passphrase,
+ (char *) ssid->ssid, ssid->ssid_len, 4096,
+ ssid->psk, PMK_LEN);
+ wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
+ ssid->psk, PMK_LEN);
+ ssid->psk_set = 1;
+ }
+
+ if ((ssid->key_mgmt & WPA_KEY_MGMT_PSK) && !ssid->psk_set) {
+ wpa_printf(MSG_ERROR, "Char %d: WPA-PSK accepted for key "
+ "management, but no PSK configured.", *cmd);
+ errors++;
+ }
+
+ if ((ssid->group_cipher & WPA_CIPHER_CCMP) &&
+ !(ssid->pairwise_cipher & WPA_CIPHER_CCMP)) {
+ /* Group cipher cannot be stronger than the pairwise cipher. */
+ wpa_printf(MSG_DEBUG, "Char %d: removed CCMP from group cipher"
+ " list since it was not allowed for pairwise "
+ "cipher", *cmd);
+ ssid->group_cipher &= ~WPA_CIPHER_CCMP;
+ }
+
+ if (errors) {
+ free(ssid);
+ ssid = NULL;
+ return NULL;
+ }
+
+ return ssid;
+}
+
+struct wpa_config * wpa_config_slave(void)
+{
+ struct wpa_config *config;
+ config = malloc(sizeof(*config));
+ if (config == NULL)
+ return NULL;
+ memset(config, 0, sizeof(*config));
+ config->eapol_version = 1;
+ config->ap_scan = 0;
+ config->fast_reauth = 1;
+ free(config->ctrl_interface);
+ config->ctrl_interface = "/var/run/wpa_supplicant";
+ wpa_printf(MSG_DEBUG, "ctrl_interface='%s'",
+ config->ctrl_interface);
+ config->ctrl_interface_gid = 0;
+ config->ctrl_interface_gid_set = 1;
+
+ return config;
+}
struct wpa_config * wpa_config_read(const char *config_file)
{
diff -ruN wpa_supplicant-0.3.8/config.h wpa_supplicant-0.3.8_slave/config.h
--- wpa_supplicant-0.3.8/config.h 2005-01-06 06:10:30.000000000 +0100
+++ wpa_supplicant-0.3.8_slave/config.h 2005-06-10 17:43:24.000000000 +0200
@@ -26,7 +26,8 @@
int fast_reauth;
};
-
+struct wpa_config * wpa_config_slave(void);
+struct wpa_ssid * wpa_ssid_from_iface(char * buf);
struct wpa_config * wpa_config_read(const char *config_file);
void wpa_config_free(struct wpa_config *ssid);
diff -ruN wpa_supplicant-0.3.8/ctrl_iface.c wpa_supplicant-0.3.8_slave/ctrl_iface.c
--- wpa_supplicant-0.3.8/ctrl_iface.c 2005-01-29 19:17:48.000000000 +0100
+++ wpa_supplicant-0.3.8_slave/ctrl_iface.c 2005-06-11 13:45:35.000000000 +0200
@@ -78,7 +78,6 @@
}
}
-
static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
char *cmd)
{
@@ -102,11 +101,32 @@
} else if (strcasecmp(cmd, "EAPOL::maxStart") == 0) {
eapol_sm_configure(wpa_s->eapol,
-1, -1, -1, atoi(value));
- } else
+ } else if (strcasecmp(cmd, "AP_MODE") == 0) {
+ if (atoi(value) >= 0 && atoi(value) <= 2)
+ wpa_s->conf->ap_scan = atoi(value);
+ else
+ return -1;
+ } else
return -1;
return 0;
}
+static int wpa_supplicant_ctrl_iface_network(struct wpa_supplicant *wpa_s, char *cmd)
+{
+ struct wpa_ssid *ssid;
+
+ if(!wpa_s->slave)
+ return 1;
+ if((ssid = wpa_ssid_from_iface(cmd)) == NULL)
+ return 1;
+ wpa_s->current_ssid = NULL;
+ eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
+ rsn_preauth_deinit(wpa_s);
+ wpa_s->conf->ssid = ssid;
+ wpa_s->reassociate = 1;
+ wpa_supplicant_req_scan(wpa_s, 0, 0);
+ return 0;
+}
static int wpa_supplicant_ctrl_iface_preauth(struct wpa_supplicant *wpa_s,
char *addr)
@@ -391,6 +411,9 @@
} else if (strncmp(buf, "STATUS", 6) == 0) {
reply_len = wpa_supplicant_ctrl_iface_status(
wpa_s, buf + 6, reply, reply_size);
+ } else if (strncmp(buf, "NETWORK ", 8) == 0) {
+ if (wpa_supplicant_ctrl_iface_network(wpa_s, buf + 8))
+ reply_len = -1;
} else if (strcmp(buf, "PMKSA") == 0) {
reply_len = pmksa_cache_list(wpa_s, reply, reply_size);
} else if (strncmp(buf, "SET ", 4) == 0) {
diff -ruN wpa_supplicant-0.3.8/wpa_cli.c wpa_supplicant-0.3.8_slave/wpa_cli.c
--- wpa_supplicant-0.3.8/wpa_cli.c 2005-02-05 07:51:25.000000000 +0100
+++ wpa_supplicant-0.3.8_slave/wpa_cli.c 2005-06-11 13:57:47.000000000 +0200
@@ -98,6 +98,7 @@
" logoff = IEEE 802.1X EAPOL state machine logoff\n"
" logon = IEEE 802.1X EAPOL state machine logon\n"
" set = set variables (shows list of variables when run without arguments)\n"
+" network = add network config (semicolon between each and double semicolon at end)\n"
" pmksa = show PMKSA cache\n"
" reassociate = force reassociation\n"
" reconfigure = force wpa_supplicant to re-read its configuration file\n"
@@ -263,7 +264,8 @@
" EAPOL::startPeriod (EAPOL state machine start period, in "
"seconds)\n"
" EAPOL::maxStart (EAPOL state machine maximum start "
- "attempts)\n");
+ "attempts)\n"
+ " AP_MODE (ap_scan mode: 0-2)\n");
}
@@ -290,6 +292,28 @@
return wpa_ctrl_command(ctrl, cmd);
}
+static int wpa_cli_cmd_network(struct wpa_ctrl *ctrl, int argc, char *argv[])
+{
+ char cmd[256];
+
+ if (argc == 0) {
+ printf("Use same network options as in config file. "
+ "Each separated by semicolon and double semicolon at end.\n");
+ return 0;
+ }
+
+ if (argc != 1) {
+ printf("Invalid NETWORK command: needs one argument\n");
+ return 0;
+ }
+
+ if (snprintf(cmd, sizeof(cmd), "NETWORK %s", argv[0]) >=
+ sizeof(cmd) - 1) {
+ printf("Too long NETWORK command.\n");
+ return 0;
+ }
+ return wpa_ctrl_command(ctrl, cmd);
+}
static int wpa_cli_cmd_logoff(struct wpa_ctrl *ctrl, int argc, char *argv[])
{
@@ -498,6 +522,7 @@
{ "otp", wpa_cli_cmd_otp },
{ "reconfigure", wpa_cli_cmd_reconfigure },
{ "terminate", wpa_cli_cmd_terminate },
+ { "network", wpa_cli_cmd_network },
{ NULL, NULL }
};
diff -ruN wpa_supplicant-0.3.8/wpa_supplicant.c wpa_supplicant-0.3.8_slave/wpa_supplicant.c
--- wpa_supplicant-0.3.8/wpa_supplicant.c 2005-02-05 07:51:25.000000000 +0100
+++ wpa_supplicant-0.3.8_slave/wpa_supplicant.c 2005-06-11 14:50:35.000000000 +0200
@@ -2114,6 +2114,7 @@
" -h = show this help text\n"
" -L = show license (GPL and BSD)\n"
" -q = decrease debugging verbosity (-qq even less)\n"
+ " -S = slave mode\n"
" -v = show version\n"
" -w = wait for interface to be added, if needed\n"
" -N = start describing new interface\n");
@@ -2142,7 +2143,6 @@
return wpa_s;
}
-
static int wpa_supplicant_init(struct wpa_supplicant *wpa_s,
const char *confname, const char *driver,
const char *ifname)
@@ -2154,7 +2154,9 @@
return -1;
}
- if (confname) {
+ if (wpa_s->slave)
+ wpa_s->conf = wpa_config_slave();
+ else if (confname) {
wpa_s->confname = rel2abs_path(confname);
if (wpa_s->confname == NULL) {
wpa_printf(MSG_ERROR, "Failed to get absolute path "
@@ -2171,7 +2173,7 @@
}
}
- if (wpa_s->conf == NULL || wpa_s->conf->ssid == NULL) {
+ if (wpa_s->conf == NULL || (wpa_s->conf->ssid == NULL && !wpa_s->slave)) {
usage();
printf("\nNo networks (SSID) configured.\n");
return -1;
@@ -2291,7 +2293,7 @@
struct wpa_supplicant *head, *wpa_s;
int c;
const char *confname, *driver, *ifname;
- int daemonize = 0, wait_for_interface = 0, disable_eapol = 0, exitcode;
+ int daemonize = 0, wait_for_interface = 0, disable_eapol = 0, slave = 0, exitcode;
#ifdef CONFIG_NATIVE_WINDOWS
WSADATA wsaData;
@@ -2312,7 +2314,7 @@
ifname = confname = driver = NULL;
for (;;) {
- c = getopt(argc, argv, "Bc:D:dehi:KLNqtvw");
+ c = getopt(argc, argv, "Bc:D:dehi:KLNqtvwS");
if (c < 0)
break;
switch (c) {
@@ -2359,6 +2361,9 @@
case 'w':
wait_for_interface++;
break;
+ case 'S':
+ slave++;
+ break;
case 'N':
if (wpa_supplicant_init(wpa_s, confname, driver,
ifname))
@@ -2375,7 +2380,10 @@
return -1;
}
}
-
+
+ if (slave)
+ wpa_s->slave = 1;
+
if (wpa_supplicant_init(wpa_s, confname, driver, ifname))
return -1;
diff -ruN wpa_supplicant-0.3.8/wpa_supplicant_i.h wpa_supplicant-0.3.8_slave/wpa_supplicant_i.h
--- wpa_supplicant-0.3.8/wpa_supplicant_i.h 2005-01-31 05:25:36.000000000 +0100
+++ wpa_supplicant-0.3.8_slave/wpa_supplicant_i.h 2005-06-10 17:24:29.000000000 +0200
@@ -58,6 +58,7 @@
struct l2_packet_data *l2;
unsigned char own_addr[ETH_ALEN];
char ifname[100];
+ int slave;
#ifdef CONFIG_XSUPPLICANT_IFACE
int dot1x_s; /* socket for connection to Xsupplicant */
int ext_pmk_received; /* 1 = PMK was received from Xsupplicant */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]