[RFC v5] [PATCH 3/3] Add WPA support to netcfg
OK, maybe I get it right this time. So sorry for the noise I am generating on the list, seems I am a slow learner.
Add support to netcfg. This patch add functionality to choose to install from a WPA PSK protected wifi network. If wpasupplicant is not available, fall
back to previous behaviour.
Fixes bug #327309
---
packages/netcfg/Makefile | 4 +-
packages/netcfg/base-installer | 2 +-
packages/netcfg/debian/netcfg-common.templates | 21 +++++
packages/netcfg/debian/rules | 2 +-
packages/netcfg/dhcp.c | 57 +++++++++++---
packages/netcfg/netcfg-static.c | 37 +++++++++-
packages/netcfg/netcfg.c | 43 ++++++++++-
packages/netcfg/netcfg.h | 16 ++++-
packages/netcfg/static.c | 18 +++--
packages/netcfg/wireless.c | 66 ++++++++++++++++-
packages/netcfg/wpa.c | 97 ++++++++++++++++++++++++
11 files changed, 332 insertions(+), 31 deletions(-)
create mode 100644 packages/netcfg/wpa.c
diff --git a/packages/netcfg/Makefile b/packages/netcfg/Makefile
index 4753350..15d2f67 100644
--- a/packages/netcfg/Makefile
+++ b/packages/netcfg/Makefile
@@ -17,8 +17,8 @@ endif
all: $(TARGETS)
-netcfg-static: netcfg-static.o static.o
-netcfg: netcfg.o dhcp.o static.o ethtool-lite.o
+netcfg-static: netcfg-static.o static.o wpa.o
+netcfg: netcfg.o dhcp.o static.o ethtool-lite.o wpa.o
$(TARGETS): $(COMMON_OBJS)
$(CC) -o $@ $^ $(LDOPTS)
diff --git a/packages/netcfg/base-installer b/packages/netcfg/base-installer
index da51feb..9ae7a56 100644
--- a/packages/netcfg/base-installer
+++ b/packages/netcfg/base-installer
@@ -1,7 +1,7 @@
#!/bin/sh -e
# Copy all relevant networking-related files to /target.
-for file in /etc/network/interfaces /etc/networks /etc/hostname /etc/resolv.conf /etc/hosts; do
+for file in /etc/network/interfaces /etc/networks /etc/hostname /etc/resolv.conf /etc/hosts /etc/wpa_supplicant/wpa_supplicant.conf; do
if [ -f "$file" ]; then
mkdir /target/$(dirname $file) -p
cp $file /target/$file
diff --git a/packages/netcfg/debian/netcfg-common.templates b/packages/netcfg/debian/netcfg-common.templates
index 973411e..8ac6f09 100644
--- a/packages/netcfg/debian/netcfg-common.templates
+++ b/packages/netcfg/debian/netcfg-common.templates
@@ -56,6 +56,14 @@ _Description: Wireless ESSID for ${iface}:
of the wireless network you would like ${iface} to use. To skip wireless
configuration and continue, leave this field blank.
+Template: netcfg/wireless_security_type
+Type: select
+__Choices: WEP/Open, WPA PSK
+# :sl2:
+_Description: Wireless Network Type for ${iface}:
+ Choose WEP/Open if the network is open or secured with WEP.
+ Choose WPA if the network is a WPA PSK protected network.
+
Template: netcfg/wireless_wep
Type: string
# :sl1:
@@ -80,6 +88,19 @@ _Description: Invalid WEP key
the next screen carefully on how to enter your WEP key correctly, and try
again.
+Template: netcfg/invalid_pass
+Type: error
+# :sl2:
+_Description: Invalid passphrase
+ The WPA PSK passphrase was either too long (more than 64 characters)
+ or too short (less than 8 characters).
+
+Template: netcfg/wireless_wpa
+Type: string
+# :sl1:
+_Description: WPA passphrase for wireless device ${iface}:
+ Enter a passphrase for WPA PSK authentication.
+
Template: netcfg/invalid_essid
Type: error
# :sl2:
diff --git a/packages/netcfg/debian/rules b/packages/netcfg/debian/rules
index 21b5f13..fdc2ff3 100755
--- a/packages/netcfg/debian/rules
+++ b/packages/netcfg/debian/rules
@@ -26,7 +26,7 @@ install: build
dh_testdir
dh_testroot
dh_clean -k
- dh_installdirs -A usr/lib/base-installer.d etc/network bin
+ dh_installdirs -A usr/lib/base-installer.d etc/network etc/wpa_supplicant bin
# Install files that are the same in all packages
$(foreach PACKAGE, $(PACKAGES), \
install -m 755 $(PACKAGE) debian/$(PACKAGE)/bin/netcfg; \
diff --git a/packages/netcfg/dhcp.c b/packages/netcfg/dhcp.c
index a98981f..0c84429 100644
--- a/packages/netcfg/dhcp.c
+++ b/packages/netcfg/dhcp.c
@@ -50,13 +50,17 @@ static void netcfg_write_dhcp (char *iface, char *dhostname)
fprintf(fp, "\thostname %s\n", dhostname);
}
if (is_wireless_iface(iface)) {
- fprintf(fp, "\t# wireless-* options are implemented by the wireless-tools package\n");
- fprintf(fp, "\twireless-mode %s\n",
- (mode == MANAGED) ? "managed" : "ad-hoc");
- fprintf(fp, "\twireless-essid %s\n",
- (essid && *essid) ? essid : "any");
- if (wepkey != NULL)
- fprintf(fp, "\twireless-key1 %s\n", wepkey);
+ if (requested_wpa_supplicant == 1)
+ fprintf(fp, "\twpa-conf /etc/wpa_supplicant/wpa_supplicant.conf\n");
+ else {
+ fprintf(fp, "\t# wireless-* options are implemented by the wireless-tools package\n");
+ fprintf(fp, "\twireless-mode %s\n",
+ (mode == MANAGED) ? "managed" : "ad-hoc");
+ fprintf(fp, "\twireless-essid %s\n",
+ (essid && *essid) ? essid : "any");
+ if (wepkey != NULL)
+ fprintf(fp, "\twireless-key1 %s\n", wepkey);
+ }
}
fclose(fp);
}
@@ -306,16 +310,45 @@ int ask_dhcp_options (struct debconfclient *client)
int ask_wifi_configuration (struct debconfclient *client)
{
- enum { ABORT, DONE, ESSID, WEP } wifistate = ESSID;
+ enum { ABORT, ESSID, SECURITY, WEP, WPA, DONE } wifistate = ESSID;
+
+ extern int requested_wpa_supplicant;
+ if (requested_wpa_supplicant != 2)
+ kill_wpa_supplicant();
+
for (;;) {
switch (wifistate) {
case ESSID:
- wifistate = (netcfg_wireless_set_essid(client, interface, "high") == GO_BACK) ?
- ABORT : WEP;
+ if (requested_wpa_supplicant == 2)
+ wifistate = (netcfg_wireless_set_essid(client, interface, "high") == GO_BACK) ?
+ ABORT : WEP;
+ else
+ wifistate = (netcfg_wireless_set_essid(client, interface, "high") == GO_BACK) ?
+ ABORT : SECURITY;
break;
+ case SECURITY:
+ {
+ int ret;
+ ret = netcfg_wireless_set_security(client, interface);
+ if (ret == GO_BACK)
+ wifistate = ESSID;
+ else if (ret == REPLY_WPA)
+ wifistate = WPA;
+ else
+ wifistate = WEP;
+ break;
+ }
case WEP:
- wifistate = (netcfg_wireless_set_wep(client, interface) == GO_BACK) ?
- ESSID : DONE;
+ if (requested_wpa_supplicant == 2)
+ wifistate = (netcfg_wireless_set_wep(client, interface) == GO_BACK) ?
+ ESSID : DONE;
+ else
+ wifistate = (netcfg_wireless_set_wep(client, interface) == GO_BACK) ?
+ SECURITY : DONE;
+ break;
+ case WPA:
+ wifistate = (netcfg_set_passphrase(client, interface) == GO_BACK) ?
+ SECURITY : DONE;
break;
case ABORT:
return REPLY_ASK_OPTIONS;
diff --git a/packages/netcfg/netcfg-static.c b/packages/netcfg/netcfg-static.c
index 285f26f..8e761c4 100644
--- a/packages/netcfg/netcfg-static.c
+++ b/packages/netcfg/netcfg-static.c
@@ -32,6 +32,7 @@ int main(int argc, char** argv)
int num_interfaces = 0;
static struct debconfclient *client;
static int requested_wireless_tools = 0;
+ extern int requested_wpa_supplicant;
enum { BACKUP,
GET_INTERFACE,
@@ -39,7 +40,9 @@ int main(int argc, char** argv)
GET_STATIC,
WCONFIG,
WCONFIG_ESSID,
+ WCONFIG_SECURITY,
WCONFIG_WEP,
+ WCONFIG_WPA,
QUIT } state = GET_INTERFACE;
/* initialize libd-i */
@@ -98,11 +101,41 @@ int main(int argc, char** argv)
if (netcfg_wireless_set_essid(client, interface, NULL))
state = BACKUP;
else
- state = WCONFIG_WEP;
+ if (requested_wpa_supplicant == 2)
+ state = WCONFIG_WEP;
+ else
+ state = WCONFIG_SECURITY;
+ break;
+
+ case WCONFIG_SECURITY:
+ if (netcfg_wireless_set_security (client, interface) == GO_BACK)
+ state = WCONFIG_ESSID;
+ else
+ if (netcfg_wireless_set_security (client, interface) == REPLY_WPA)
+ state = WCONFIG_WPA;
+ else
+ state = WCONFIG_WEP;
break;
case WCONFIG_WEP:
- if (netcfg_wireless_set_wep(client, interface))
+ if (netcfg_wireless_set_wep(client, interface)) {
+ have_wpa_supplicant();
+ if (requested_wpa_supplicant == 2)
+ state = WCONFIG_ESSID;
+ else
+ state = WCONFIG_SECURITY;
+ }
+ else
+ state = GET_STATIC;
+ break;
+
+ case WCONFIG_WPA:
+ if (requested_wpa_supplicant == 0) {
+ di_exec_shell_log("apt-install wpasupplicant");
+ requested_wpa_supplicant = 1;
+ }
+
+ if (netcfg_set_passphrase(client, interface) == GO_BACK)
state = WCONFIG_ESSID;
else
state = GET_STATIC;
diff --git a/packages/netcfg/netcfg.c b/packages/netcfg/netcfg.c
index 3c638aa..b5274e0 100644
--- a/packages/netcfg/netcfg.c
+++ b/packages/netcfg/netcfg.c
@@ -69,11 +69,14 @@ int main(int argc, char *argv[])
GET_STATIC,
WCONFIG,
WCONFIG_ESSID,
+ WCONFIG_SECURITY,
WCONFIG_WEP,
+ WCONFIG_WPA,
QUIT } state = GET_INTERFACE;
static struct debconfclient *client;
static int requested_wireless_tools = 0;
+ extern int requested_wpa_supplicant;
char **ifaces;
char *defiface = NULL, *defwireless = NULL;
response_t res;
@@ -251,19 +254,53 @@ int main(int argc, char *argv[])
case WCONFIG_ESSID:
if (netcfg_wireless_set_essid(client, interface, NULL) == GO_BACK)
state = BACKUP;
- else
- state = WCONFIG_WEP;
+ else {
+ have_wpa_supplicant();
+ if (requested_wpa_supplicant == 2)
+ state = WCONFIG_WEP;
+ else
+ state = WCONFIG_SECURITY;
+ }
break;
+ case WCONFIG_SECURITY:
+ {
+ int ret;
+ ret = netcfg_wireless_set_security(client, interface);
+ if (ret == GO_BACK)
+ state = WCONFIG_ESSID;
+ else if (ret == REPLY_WPA)
+ state = WCONFIG_WPA;
+ else
+ state = WCONFIG_WEP;
+ break;
+ }
+
case WCONFIG_WEP:
if (netcfg_wireless_set_wep(client, interface) == GO_BACK)
- state = WCONFIG_ESSID;
+ if (requested_wpa_supplicant == 2)
+ state = WCONFIG_ESSID;
+ else
+ state = WCONFIG_SECURITY;
else
state = GET_METHOD;
break;
+ case WCONFIG_WPA:
+ if (requested_wpa_supplicant == 0) {
+ di_exec_shell_log("apt-install wpasupplicant");
+ requested_wpa_supplicant = 1;
+ }
+
+ if (netcfg_set_passphrase(client, interface) == GO_BACK)
+ state = WCONFIG_SECURITY;
+ else
+ state = GET_METHOD;
+ break;
+
case QUIT:
return 0;
}
}
}
+
diff --git a/packages/netcfg/netcfg.h b/packages/netcfg/netcfg.h
index a7bc8a9..aa181e4 100644
--- a/packages/netcfg/netcfg.h
+++ b/packages/netcfg/netcfg.h
@@ -10,11 +10,16 @@
#define DHCLIENT3_CONF "/etc/dhcp3/dhclient.conf"
#define DOMAIN_FILE "/tmp/domain_name"
#define NTP_SERVER_FILE "/tmp/dhcp-ntp-servers"
+#define WPASUPP_CONF "/etc/wpa_supplicant/wpa_supplicant.conf"
+#define WPAPID "/var/run/wpa_supplicant/wpa_supplicant.pid"
#define DEVNAMES "/etc/network/devnames"
#define DEVHOTPLUG "/etc/network/devhotplug"
#define STAB "/var/run/stab"
+#define WPA_MIN 8
+#define WPA_MAX 64
+
#define _GNU_SOURCE
#include <sys/types.h>
@@ -41,7 +46,7 @@
"ff02::2 ip6-allrouters\n" \
"ff02::3 ip6-allhosts\n"
-typedef enum { NOT_ASKED = 30, GO_BACK } response_t;
+typedef enum { NOT_ASKED = 30, GO_BACK, REPLY_WEP, REPLY_WPA } response_t;
typedef enum { DHCP, STATIC, DUNNO } method_t;
typedef enum { ADHOC = 1, MANAGED = 2 } wifimode_t;
@@ -49,6 +54,7 @@ extern int netcfg_progress_displayed;
extern int wfd, skfd;
extern int input_result;
extern int have_domain;
+extern int requested_wpa_supplicant;
/* network config */
extern char *interface;
@@ -64,7 +70,7 @@ extern struct in_addr gateway;
extern struct in_addr pointopoint;
/* wireless */
-extern char *essid, *wepkey;
+extern char *essid, *wepkey, *passphrase;
extern wifimode_t mode;
/* common functions */
@@ -111,7 +117,13 @@ extern int is_wireless_iface (const char* iface);
extern int netcfg_wireless_set_essid (struct debconfclient *client, char* iface, char* priority);
extern int netcfg_wireless_set_wep (struct debconfclient *client, char* iface);
+extern int netcfg_wireless_set_security (struct debconfclient *client, char* iface);
+extern int netcfg_set_passphrase (struct debconfclient *client, char* iface);
+extern int have_wpa_supplicant (void);
+extern int kill_wpa_supplicant (void);
+extern int netcfg_write_wpa (char *essid, char *passphrase);
+extern int start_wpa_supplicant (struct debconfclient *client);
extern int iface_is_hotpluggable(const char *iface);
extern short find_in_stab (const char *iface);
extern void deconfigure_network(void);
diff --git a/packages/netcfg/static.c b/packages/netcfg/static.c
index 41a9368..fa339b7 100644
--- a/packages/netcfg/static.c
+++ b/packages/netcfg/static.c
@@ -198,14 +198,18 @@ static int netcfg_write_static(char *domain, struct in_addr nameservers[])
* Write wireless-tools options
*/
if (is_wireless_iface(interface)) {
- fprintf(fp, "\t# wireless-* options are implemented by the wireless-tools package\n");
- fprintf(fp, "\twireless-mode %s\n",
- (mode == MANAGED) ? "managed" : "ad-hoc");
- fprintf(fp, "\twireless-essid %s\n",
- (essid && *essid) ? essid : "any");
+ if (requested_wpa_supplicant == 1)
+ fprintf(fp, "\twpa-conf /etc/wpa_supplicant/wpa_supplicant.conf\n");
+ else {
+ fprintf(fp, "\t# wireless-* options are implemented by the wireless-tools package\n");
+ fprintf(fp, "\twireless-mode %s\n",
+ (mode == MANAGED) ? "managed" : "ad-hoc");
+ fprintf(fp, "\twireless-essid %s\n",
+ (essid && *essid) ? essid : "any");
- if (wepkey != NULL)
- fprintf(fp, "\twireless-key1 %s\n", wepkey);
+ if (wepkey != NULL)
+ fprintf(fp, "\twireless-key1 %s\n", wepkey);
+ }
}
/*
* Write resolvconf options
diff --git a/packages/netcfg/wireless.c b/packages/netcfg/wireless.c
index ed07b8a..f5d87f1 100644
--- a/packages/netcfg/wireless.c
+++ b/packages/netcfg/wireless.c
@@ -19,6 +19,7 @@ wifimode_t mode = MANAGED;
/* wireless config */
char* wepkey = NULL;
char* essid = NULL;
+char* passphrase = NULL;
#ifdef WIRELESS
@@ -53,7 +54,7 @@ int netcfg_wireless_set_essid (struct debconfclient * client, char *iface, char*
wconf.has_mode = 1;
wconf.mode = mode;
- debconf_input(client, priority ? priority : "low", "netcfg/wireless_essid");
+ debconf_input(client, priority ? priority : "high", "netcfg/wireless_essid");
if (debconf_go(client) == 30)
return GO_BACK;
@@ -189,6 +190,25 @@ static void unset_wep_key (char* iface)
ret = iw_set_basic_config (wfd, iface, &wconf);
}
+int netcfg_wireless_set_security (struct debconfclient *client, char *iface)
+{
+ int ret = 0 ;
+ debconf_subst (client, "netcfg/wireless_security_type", "iface", iface);
+ debconf_input (client, "high", "netcfg/wireless_security_type");
+ ret = debconf_go(client);
+
+ if (ret == 30)
+ return GO_BACK;
+
+ debconf_get (client, "netcfg/wireless_security_type");
+
+ if (!strcmp(client->value, "WEP/Open Network"))
+ return REPLY_WEP;
+ else
+ return REPLY_WPA;
+
+}
+
int netcfg_wireless_set_wep (struct debconfclient * client, char* iface)
{
wireless_config wconf;
@@ -250,6 +270,50 @@ int netcfg_wireless_set_wep (struct debconfclient * client, char* iface)
return 0;
}
+int netcfg_set_passphrase (struct debconfclient *client, char *iface)
+{
+ wireless_config wconf;
+ int ret;
+
+ iw_get_basic_config(wfd, iface, &wconf);
+
+ unset_wep_key(iface);
+
+ debconf_subst(client, "netcfg/wireless_wpa", "iface", iface);
+ debconf_input(client, "high", "netcfg/wireless_wpa");
+ ret = debconf_go(client);
+
+ if (ret == 30)
+ return GO_BACK;
+
+ debconf_get(client, "netcfg/wireless_wpa");
+ passphrase = client->value;
+
+ while (strlen(passphrase) < WPA_MIN || strlen(passphrase) > WPA_MAX) {
+ debconf_subst(client, "netcfg/invalid_pass", "passphrase", passphrase);
+ debconf_input(client, "critical", "netcfg/invalid_pass");
+ debconf_go(client);
+
+ debconf_input(client, "high", "netcfg/wireless_wpa");
+ ret = debconf_go (client);
+
+
+ if (ret == 30)
+ return GO_BACK;
+
+ debconf_get (client, "netcfg/wireless_wpa");
+ passphrase = client->value;
+ }
+
+ if (netcfg_write_wpa(essid, passphrase)) {
+ di_warning("Failed to write wpasupplicant config file");
+ return -1;
+ }
+ else
+ start_wpa_supplicant(client);
+ return 0;
+}
+
#else
int is_wireless_iface (const char *iface)
diff --git a/packages/netcfg/wpa.c b/packages/netcfg/wpa.c
new file mode 100644
index 0000000..f0a99b7
--- /dev/null
+++ b/packages/netcfg/wpa.c
@@ -0,0 +1,97 @@
+/*
+* WPA module for netcfg
+*
+* Copyright (C) 2008 Glenn Saberton <gsaberton@foomagic.org>
+*
+* Licensed under the terms of the GNU General Public License version 2
+*
+*/
+
+#include "netcfg.h"
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <debian-installer.h>
+
+pid_t wpa_supplicant_pid = -1;
+int requested_wpa_supplicant = 0;
+
+/*
+* Build an /etc/wpa_supplicant.conf
+* file.
+*/
+
+int netcfg_write_wpa (char *essid, char *passphrase)
+{
+ FILE *fp;
+
+ if ((fp = file_open (WPASUPP_CONF, "w"))) {
+ fprintf (fp, "\n# wpa_supplicant.conf generated during install\n"
+ "ctrl_interface=/var/run/wpa_supplicant\n"
+ "ctrl_interface_group=0\n"
+ "eapol_version=1\n"
+ "ap_scan=1\n\n" /* So we can associate to hidden ssid's */
+ "network={\n");
+ fprintf (fp, "\t\tssid=\"%s\"\n", essid);
+ fprintf (fp, "\t\tpsk=\"%s\"\n", passphrase);
+ fprintf (fp, "\t\tscan_ssid=1\n" "}\n");
+ }
+ fclose (fp);
+ return 0;
+}
+
+int have_wpa_supplicant(void)
+{
+ extern int requested_wpa_supplicant;
+
+ if (access("/sbin/wpa_supplicant", F_OK) == 0)
+ requested_wpa_supplicant = 0;
+ else {
+ requested_wpa_supplicant = 2;
+ di_info("Wpasupplicant not found on the system. Disabling WPA options");
+ }
+ return 0;
+}
+
+int kill_wpa_supplicant(void)
+{
+ int ret;
+ pid_t wpa_pid;
+ FILE *fp;
+
+ fp = (file_open (WPAPID, "r"));
+ if (fp == NULL) {
+ di_warning ("Couldn't read Wpasupplicant pid file, not trying to kill.");
+ return 0;
+ }
+ else {
+ fscanf (fp, "%d", &wpa_pid);
+ fclose (fp);
+ }
+ if ((ret = kill(wpa_pid, SIGTERM)) == 0)
+ return 0;
+ else {
+ kill(wpa_pid, SIGKILL);
+ return 0;
+ }
+}
+
+int start_wpa_supplicant (struct debconfclient *client)
+{
+ wpa_supplicant_pid = fork();
+
+ if (wpa_supplicant_pid == 0) {
+ fclose(client->out);
+ if (execlp ("wpa_supplicant", "wpa_supplicant", "-i", interface, "-c",
+ WPASUPP_CONF, "-P", WPAPID, "-B", NULL) == -1) {
+ di_error("could not exec wpasupplicant: %s", strerror(errno));
+ return 1;
+ }
+ else
+ return 0;
+ }
+ else {
+ waitpid(wpa_supplicant_pid, NULL, 0);
+ return 0;
+ }
+}
--
1.5.5.1
Reply to: