[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: [RFC] [PATCH] WPA PSK support for netcfg



Glenn Saberton wrote:
> Hello,
>     Attached is a patch for adding support for installing over a wpa
> psk protected wifi network. Its still a work in progress, but I am
> happy enough with the basic functionality to want to push it out and
> get some feedback on what the d-i team may think in regard to
> implementation or whether its worthwhile pursuing at all. Apologies
> for some noise in the patch as I had run indent on my copy, so there
> is a bit of redundant cruft in there. A basic udeb for wpasupplicant
> is needed but the clients it supplies and various drivers could be cut
> out in the udeb if the team thinks its worthwile pursuing. Thus the
> size of the udeb could be a bit smaller than the default build for
> wpasupp (ie no eap support, no clients or dbus support) Basically, it
> writes out a supplicant config during configuration of wireless device
> and starts wpasupp with that file. This appeared to me to be the
> simplist way of getting support into netcfg. I have copied the
> killall.sh script to kill wpasupp when required, though I am not
> really happy with that and will be looking to remove that in the
> future. My attempts at using kill() or such functions weren't very
> successfull and any pointers here would be appreciated. I have also
> set debconf priority to high when configuring wireless, as otherwise
> netcfg will try and associate to a random AP and this is not really
> desirable leading to the need to reconfigure wifi and manually enter
> the essid. I would like to add a scan function to netcfg in the future
> to allow people to chose their AP from a list but I am not sure on how
> to get cdebconf to chose the selected AP. Any pointers on this would
> also be appreciated. I have only tested this on my eeepc, but I dont
> see why it wouldn't work on other chipsets. Let the comments flow and
> please CC me as I am not subscribed to the list. Patch is attached or
> you can dget foomagic.org/eeepc/netcfg/netcfg_1.43.dsc
>
> Cheers
>
> Glenn
New patch attached regarding Christian Perrier's comments. Please keep
them coming and don't forget to CC me :)

Cheers

Glenn
diff -Nurb ../netcfg-1.43/base-installer netcfg-1.43/base-installer
--- ../netcfg-1.43/base-installer	2008-01-14 10:29:16.000000000 +0900
+++ netcfg-1.43/base-installer	2008-04-18 22:14:33.000000000 +0800
@@ -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 -Nurb ../netcfg-1.43/debian/control netcfg-1.43/debian/control
--- ../netcfg-1.43/debian/control	2008-04-08 19:40:33.000000000 +0800
+++ netcfg-1.43/debian/control	2008-04-18 22:14:33.000000000 +0800
@@ -2,7 +2,7 @@
 Section: debian-installer
 Priority: optional
 Maintainer: Debian Install System Team <debian-boot@lists.debian.org>
-Uploaders: Joey Hess <joeyh@debian.org>, Frans Pop <fjp@debian.org>, Colin Watson <cjwatson@debian.org>
+Uploaders: David Kimdon <dwhedon@debian.org>, Tollef Fog Heen <tfheen@debian.org>, Matt Kraai <kraai@debian.org>, Joey Hess <joeyh@debian.org>, Joshua Kwan <joshk@triplehelix.org>, Thomas Hood <jdthood@yahoo.co.uk>, Frans Pop <fjp@debian.org>, Colin Watson <cjwatson@debian.org>
 Build-Depends: debhelper (>= 5.0.22), dpkg-dev (>= 1.9.0), libdebconfclient0-dev (>= 0.46), libdebian-installer4-dev (>= 0.41), po-debconf (>= 0.5.0), libiw-dev (>= 27+28pre9-1)
 Vcs-Svn: svn://svn.debian.org/d-i/trunk/packages/netcfg
 
diff -Nurb ../netcfg-1.43/debian/netcfg-common.templates netcfg-1.43/debian/netcfg-common.templates
--- ../netcfg-1.43/debian/netcfg-common.templates	2008-03-08 05:00:20.000000000 +0900
+++ netcfg-1.43/debian/netcfg-common.templates	2008-04-18 22:14:33.000000000 +0800
@@ -56,6 +56,14 @@
  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}:
+ Chose Wep/Open if the network is open or secured with wep.
+ Chose WPA if the network is a WPA PSK protected network.
+
 Template: netcfg/wireless_wep
 Type: string
 # :sl1:
@@ -80,6 +88,19 @@
  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 WPA PSK passphrase.
+
 Template: netcfg/invalid_essid
 Type: error
 # :sl2:
@@ -126,6 +147,13 @@
  You may need to load a specific module for your network card, if you have
  one. For this, go back to the network hardware detection step.
 
+Template: netcfg/no_wpa_supplicant
+Type: error
+# :sl2:
+_Description: Wpasupplicant not found
+ The wpa_supplicant binary was not found on the system.
+ Chose WEP/Open wireless network, otherwise chose wired network.
+
 Template: netcfg/kill_switch_enabled
 Type: note
 # A "kill switch" is a physical switch found on some network cards that
@@ -257,7 +285,7 @@
 Type: text
 # base-installer progress bar item
 # :sl1:
-_Description: Storing network settings...
+_Description: Storing network settings ...
 
 Template: debian-installer/netcfg/title
 Type: text
diff -Nurb ../netcfg-1.43/debian/rules netcfg-1.43/debian/rules
--- ../netcfg-1.43/debian/rules	2008-02-09 22:12:23.000000000 +0900
+++ netcfg-1.43/debian/rules	2008-04-18 22:14:33.000000000 +0800
@@ -26,7 +26,7 @@
 	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; \
@@ -36,7 +36,8 @@
 	$(foreach PACKAGE, $(DHCP_PACKAGES), \
 		mkdir -p debian/$(PACKAGE)/etc/dhcp debian/$(PACKAGE)/etc/dhcp3; \
 		mkdir -p debian/$(PACKAGE)/var/dhcp ; \
-		install -m 755 killall.sh debian/$(PACKAGE)/bin/killall.sh)
+		install -m 755 killall.sh debian/$(PACKAGE)/bin/killall.sh; \
+		install -m 755 killwpa.sh debian/$(PACKAGE)/bin/killwpa.sh)
 
 
 # Build architecture-independent files here.
diff -Nurb ../netcfg-1.43/dhcp.c netcfg-1.43/dhcp.c
--- ../netcfg-1.43/dhcp.c	2008-01-18 20:20:02.000000000 +0900
+++ netcfg-1.43/dhcp.c	2008-04-18 22:14:33.000000000 +0800
@@ -50,6 +50,9 @@
             fprintf(fp, "\thostname %s\n", dhostname);
         }
         if (is_wireless_iface(iface)) {
+    	    if (requested_wpa_supplicant)
+    		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");
@@ -58,6 +61,7 @@
             if (wepkey != NULL)
                 fprintf(fp, "\twireless-key1 %s\n", wepkey);
         }
+	}
         fclose(fp);
     }
     
@@ -184,6 +188,7 @@
         return 1;
     else {
         /* dhcp_pid contains the child's PID */
+
         signal(SIGCHLD, &dhcp_client_sigchld);
         return 0;
     }
@@ -196,6 +201,11 @@
     return 0;
 }
 
+static int kill_wpa_supplicant(void)    /* I would much rather kill wpasupp by pid, but my attempts at using kill() proved buggy */
+{
+    system("killwpa.sh");
+    return 0;
+}
 
 /*
  * Poll the started DHCP client for netcfg/dhcp_timeout seconds (def. 15)
@@ -302,7 +312,48 @@
         return REPLY_DONT_CONFIGURE;
 }
 
+int reconfigure_wifi(struct debconfclient *client)
+{        
+    enum { ABORT, ESSID, SECURITY, WEP, WPA, DONE } wifistate = ESSID;
+
+		    kill_wpa_supplicant();
+		    kill_dhcp_client();
 
+                    for (;;) {
+                        switch (wifistate) {
+                        case ESSID:
+                            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 == WPAG)
+                	    	 wifistate = WPA;
+                	     else
+                    		 wifistate = WEP;
+                    	     break;
+                    	    }
+                        case WEP:
+                            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 DONE:
+                    	    return 0;
+                    	    break;
+                        case ABORT:
+                            return 1;
+                            break;
+	}
+    }
+}
 /* Here comes another Satan machine. */
 int netcfg_activate_dhcp (struct debconfclient *client)
 {
@@ -472,35 +523,10 @@
                 }
                 break;
             case REPLY_RECONFIGURE_WIFI:
-                {
-                    /* oh god - a NESTED satan machine */
-                    enum { ABORT, DONE, ESSID, WEP } wifistate = ESSID;
-                    for (;;) {
-                        switch (wifistate) {
-                        case ESSID:
-                            wifistate = ( netcfg_wireless_set_essid(client, interface, "high") == GO_BACK ) ?
-                                ABORT : WEP;
-                            break;
-                        case WEP:
-                            wifistate = ( netcfg_wireless_set_wep (client, interface) == GO_BACK ) ?
-                                ESSID : DONE;
-                            break;
-                        case ABORT:
-                            state = ASK_OPTIONS;
-                            break;
-                        case DONE:
-                            if (dhcp_pid > 0)
-                                state = POLL;
-                            else {
-                                kill_dhcp_client();
+                if (!reconfigure_wifi(client))
                                 state = START;
-                            }
-                            break;
-                        }
-                        if (wifistate == DONE || wifistate == ABORT)
-                            break;
-                    }
-                }
+            	else
+            	    state = ASK_OPTIONS;
                 break;
             }
             break;
diff -Nurb ../netcfg-1.43/killwpa.sh netcfg-1.43/killwpa.sh
--- ../netcfg-1.43/killwpa.sh	1970-01-01 08:00:00.000000000 +0800
+++ netcfg-1.43/killwpa.sh	2008-04-18 22:14:33.000000000 +0800
@@ -0,0 +1,16 @@
+#!/bin/sh
+# Killall for dhcp clients.
+
+# Use [] in sed /address/ to avoid matching sed command itself in ps output
+pids=$(ps ax | sed -n '/[w]pa/s/^[ ]*\([0-9]*\).*/\1/p')
+
+for pid in $pids; do
+  if kill -0 $pid 2>/dev/null; then
+    kill -TERM $pid
+    sleep 1
+    # Still alive? Die!
+    if kill -0 $pid 2>/dev/null; then
+      kill -KILL $pid
+    fi
+  fi
+done
diff -Nurb ../netcfg-1.43/Makefile netcfg-1.43/Makefile
--- ../netcfg-1.43/Makefile	2008-01-14 10:48:18.000000000 +0900
+++ netcfg-1.43/Makefile	2008-04-18 22:14:33.000000000 +0800
@@ -17,8 +17,8 @@
 
 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 -Nurb ../netcfg-1.43/netcfg.c netcfg-1.43/netcfg.c
--- ../netcfg-1.43/netcfg.c	2006-09-23 21:24:37.000000000 +0800
+++ netcfg-1.43/netcfg.c	2008-04-18 22:14:33.000000000 +0800
@@ -33,6 +33,7 @@
 #endif
 #include "netcfg.h"
 
+int requested_wpa_supplicant = 0;
 static method_t netcfg_method = DHCP;
 
 response_t netcfg_get_method(struct debconfclient *client)
@@ -61,7 +62,21 @@
 int main(int argc, char *argv[])
 {
     int num_interfaces = 0;
-    enum { BACKUP, GET_INTERFACE, GET_HOSTNAME_ONLY, GET_METHOD, GET_DHCP, GET_STATIC, WCONFIG, WCONFIG_ESSID, WCONFIG_WEP, QUIT } state = GET_INTERFACE;
+    enum {  BACKUP, \
+	    GET_INTERFACE, \
+	    GET_HOSTNAME_ONLY, \
+	    GET_METHOD, \
+	    GET_DHCP, \
+	    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;
     char **ifaces;
@@ -239,15 +254,40 @@
             break;
             
         case WCONFIG_ESSID:
-            if (netcfg_wireless_set_essid (client, interface, NULL) == GO_BACK)
+	    if (netcfg_wireless_set_essid(client, interface, "high") == GO_BACK)
                 state = BACKUP;
             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 == WPAG)
+    		    state = WCONFIG_WPA;
+    		else
                 state = WCONFIG_WEP;
             break;
+	    }
             
         case WCONFIG_WEP:
-            if (netcfg_wireless_set_wep (client, interface) == GO_BACK)
-                state = WCONFIG_ESSID;
+            if (netcfg_wireless_set_wep(client, interface) == GO_BACK)
+                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;
diff -Nurb ../netcfg-1.43/netcfg.h netcfg-1.43/netcfg.h
--- ../netcfg-1.43/netcfg.h	2008-01-18 20:20:02.000000000 +0900
+++ netcfg-1.43/netcfg.h	2008-04-18 22:14:33.000000000 +0800
@@ -10,11 +10,15 @@
 #define DHCLIENT3_CONF	"/etc/dhcp3/dhclient.conf"
 #define DOMAIN_FILE     "/tmp/domain_name"
 #define NTP_SERVER_FILE "/tmp/dhcp-ntp-servers"
+#define WPASUPP_FILE	"/etc/wpa_supplicant/wpa_supplicant.conf"
 
 #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 +45,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, WEPG, WPAG } response_t;
 typedef enum { DHCP, STATIC, DUNNO } method_t;
 typedef enum { ADHOC = 1, MANAGED = 2 } wifimode_t;
 
@@ -49,6 +53,7 @@
 extern int wfd, skfd;
 extern int input_result;
 extern int have_domain;
+extern int requested_wpa_supplicant;
 
 /* network config */
 extern char *interface;
@@ -64,7 +69,7 @@
 extern struct in_addr pointopoint;
 
 /* wireless */
-extern char *essid, *wepkey;
+extern char *essid, *wepkey, *passphrase;
 extern wifimode_t mode;
 
 /* common functions */
@@ -111,7 +116,12 @@
 
 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 netcfg_write_wpa (char *essid, char *passphrase);
+extern int start_wpa_supplicant (struct debconfclient *client);
+/*extern int kill_wpa_supplicant (void);*/
 extern int iface_is_hotpluggable(const char *iface);
 extern short find_in_stab (const char *iface);
 extern void deconfigure_network(void);
diff -Nurb ../netcfg-1.43/netcfg-static.c netcfg-1.43/netcfg-static.c
--- ../netcfg-1.43/netcfg-static.c	2006-09-23 21:24:37.000000000 +0800
+++ netcfg-1.43/netcfg-static.c	2008-04-18 22:14:33.000000000 +0800
@@ -32,8 +32,19 @@
     int num_interfaces = 0;
     static struct debconfclient *client;
     static int requested_wireless_tools = 0;
+    static int requested_wpa_supplicant = 0;
     
-    enum { BACKUP, GET_INTERFACE, GET_HOSTNAME_ONLY, GET_STATIC, WCONFIG, WCONFIG_ESSID, WCONFIG_WEP, QUIT} state = GET_INTERFACE;
+    enum { BACKUP, \
+	   GET_INTERFACE, \
+	   GET_HOSTNAME_ONLY, \
+	   GET_STATIC, \
+	   WCONFIG, \
+	   WCONFIG_ESSID, \
+	   WCONFIG_SECURITY, \
+	   WCONFIG_WEP, \
+	   WCONFIG_WPA,  \
+	   QUIT} 
+	state = GET_INTERFACE;
     
     /* initialize libd-i */
     di_system_init("netcfg-static");
@@ -91,6 +102,16 @@
             if (netcfg_wireless_set_essid (client, interface, NULL))
                 state = BACKUP;
             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) == WPAG)
+    		    state = WCONFIG_WPA;
+    		else
                 state = WCONFIG_WEP;
             break;
             
@@ -101,6 +122,18 @@
                 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;
+	    break;
+            
         case QUIT:
             return 0;
         }
diff -Nurb ../netcfg-1.43/wireless.c netcfg-1.43/wireless.c
--- ../netcfg-1.43/wireless.c	2007-04-10 06:27:06.000000000 +0800
+++ netcfg-1.43/wireless.c	2008-04-18 22:14:33.000000000 +0800
@@ -17,53 +17,54 @@
 wifimode_t mode = MANAGED;
 
 /* wireless config */
-char* wepkey = NULL;
-char* essid = NULL;
+char *wepkey = NULL;
+char *essid = NULL;
+char *passphrase = NULL;
 
 #ifdef WIRELESS
 
 int is_wireless_iface (const char* iface)
 {
     wireless_config wc;
-    return (iw_get_basic_config (wfd, (char*)iface, &wc) == 0);
+    return (iw_get_basic_config (wfd, (char*) iface, &wc) == 0);
 }
 
-int netcfg_wireless_set_essid (struct debconfclient * client, char *iface, char* priority)
+int netcfg_wireless_set_essid (struct debconfclient *client, char *iface, char *priority)
 {
     int ret, couldnt_associate = 0;
     wireless_config wconf;
-    char* tf = NULL, *user_essid = NULL, *ptr = wconf.essid;
+  char *tf = NULL, *user_essid = NULL, *ptr = wconf.essid;
     
     iw_get_basic_config (wfd, iface, &wconf);
     
-    debconf_subst(client, "netcfg/wireless_essid", "iface", iface);
-    debconf_subst(client, "netcfg/wireless_essid_again", "iface", iface);
-    debconf_subst(client, "netcfg/wireless_adhoc_managed", "iface", iface);
+  debconf_subst (client, "netcfg/wireless_essid", "iface", iface);
+  debconf_subst (client, "netcfg/wireless_essid_again", "iface", iface);
+  debconf_subst (client, "netcfg/wireless_adhoc_managed", "iface", iface);
     
-    debconf_input(client, priority ? priority : "low", "netcfg/wireless_adhoc_managed");
+  debconf_input (client, priority ? priority : "low", "netcfg/wireless_adhoc_managed");
     
-    if (debconf_go(client) == 30)
+  if (debconf_go (client) == 30)
         return GO_BACK;
     
-    debconf_get(client, "netcfg/wireless_adhoc_managed");
+  debconf_get (client, "netcfg/wireless_adhoc_managed");
     
-    if (!strcmp(client->value, "Ad-hoc network (Peer to peer)"))
+  if (!strcmp (client->value, "Ad-hoc network (Peer to peer)"))
         mode = ADHOC;
     
     wconf.has_mode = 1;
     wconf.mode = mode;
     
-    debconf_input(client, priority ? priority : "low", "netcfg/wireless_essid");
+  debconf_input (client, priority ? priority : "low", "netcfg/wireless_essid");
     
-    if (debconf_go(client) == 30)
+  if (debconf_go (client) == 30)
         return GO_BACK;
     
-    debconf_get(client, "netcfg/wireless_essid");
-    tf = strdup(client->value);
+  debconf_get (client, "netcfg/wireless_essid");
+  tf = strdup (client->value);
     
 automatic:
     /* question not asked or user doesn't care or we're successfully associated */
-    if (!empty_str(wconf.essid) || empty_str(client->value)) 
+  if (!empty_str (wconf.essid) || empty_str (client->value))
     {
         int i, success = 0;
         
@@ -73,39 +74,39 @@
         
         iw_set_basic_config (wfd, iface, &wconf);
         
-        /* Wait for association.. (MAX_SECS seconds)*/
-#define MAX_SECS 3
+      /* Wait for association.. (MAX_SECS seconds) */
+#define MAX_SECS 5
         
-        debconf_capb(client, "backup progresscancel");
-        debconf_progress_start(client, 0, MAX_SECS, "netcfg/wifi_progress_title");
-        if (debconf_progress_info(client, "netcfg/wifi_progress_info") == 30)
+      debconf_capb (client, "backup progresscancel");
+      debconf_progress_start (client, 0, MAX_SECS, "netcfg/wifi_progress_title");
+      if (debconf_progress_info (client, "netcfg/wifi_progress_info") == 30)
             goto stop;
         netcfg_progress_displayed = 1;
         
         for (i = 0; i <= MAX_SECS; i++) {
             int progress_ret;
             
-            interface_up(iface);
+	  interface_up (iface);
             sleep (1);
             iw_get_basic_config (wfd, iface, &wconf);
             
-            if (!empty_str(wconf.essid)) {
+	  if (!empty_str (wconf.essid)) {
                 /* Save for later */
-                debconf_set(client, "netcfg/wireless_essid", wconf.essid);
-                debconf_progress_set(client, MAX_SECS);
+	      debconf_set (client, "netcfg/wireless_essid", wconf.essid);
+	      debconf_progress_set (client, MAX_SECS);
                 success = 1;
                 break;
             }
             
-            progress_ret = debconf_progress_step(client, 1);
-            interface_down(iface);
+	  progress_ret = debconf_progress_step (client, 1);
+	  interface_down (iface);
             if (progress_ret == 30)
                 break;
         }
         
     stop:
-        debconf_progress_stop(client);
-        debconf_capb(client, "backup");
+      debconf_progress_stop (client);
+      debconf_capb (client, "backup");
         netcfg_progress_displayed = 0;
         
         if (success)
@@ -115,39 +116,42 @@
     }
     /* yes, wants to set an essid by himself */
     
-    if (strlen(tf) <= IW_ESSID_MAX_SIZE) /* looks ok, let's use it */
+  if (strlen (tf) <= IW_ESSID_MAX_SIZE)	/* looks ok, let's use it */
         user_essid = tf;
     
-    while (!user_essid || empty_str(user_essid) ||
-           strlen(user_essid) > IW_ESSID_MAX_SIZE) {
+  while (!user_essid || empty_str (user_essid) ||
+	 strlen (user_essid) > IW_ESSID_MAX_SIZE)
+    {
         /* Misnomer of a check. Basically, if we went through autodetection,
          * we want to enter this loop, but we want to suppress anything that
          * relied on the checking of tf/user_essid (i.e. "", in most cases.) */
-        if (!couldnt_associate) {
-            debconf_subst(client, "netcfg/invalid_essid", "essid", user_essid);
-            debconf_input(client, "high", "netcfg/invalid_essid");
-            debconf_go(client);
+      if (!couldnt_associate)
+	{
+	  debconf_subst (client, "netcfg/invalid_essid", "essid", user_essid);
+	  debconf_input (client, "high", "netcfg/invalid_essid");
+	  debconf_go (client);
         }
         
         if (couldnt_associate)
-            ret = debconf_input(client, "critical", "netcfg/wireless_essid_again");
+	ret = debconf_input (client, "critical", "netcfg/wireless_essid_again");
         else
-            ret = debconf_input(client, "low", "netcfg/wireless_essid");
+	ret = debconf_input (client, "low", "netcfg/wireless_essid");
         
         /* we asked the question once, why can't we ask it again? */
         if (ret == 30)
             /* maybe netcfg/wireless_essid was preseeded; if so, give up */
             break;
         
-        if (debconf_go(client) == 30) /* well, we did, but he wants to go back */
+      if (debconf_go (client) == 30)	/* well, we did, but he wants to go back */
             return GO_BACK;
         
         if (couldnt_associate)
-            debconf_get(client, "netcfg/wireless_essid_again");
+	debconf_get (client, "netcfg/wireless_essid_again");
         else
-            debconf_get(client, "netcfg/wireless_essid");
+	debconf_get (client, "netcfg/wireless_essid");
         
-        if (empty_str(client->value)) {
+      if (empty_str (client->value))
+	{
             if (couldnt_associate)
                 /* we've already tried the empty string here, so give up */
                 break;
@@ -158,14 +162,14 @@
         /* But now we'd not like to suppress any MORE errors */
         couldnt_associate = 0;
         
-        free(user_essid);
-        user_essid = strdup(client->value);
+      free (user_essid);
+      user_essid = strdup (client->value);
     }
     
     essid = user_essid;
     
-    memset(ptr, 0, IW_ESSID_MAX_SIZE + 1);
-    snprintf(wconf.essid, IW_ESSID_MAX_SIZE + 1, "%s", essid);
+  memset (ptr, 0, IW_ESSID_MAX_SIZE + 1);
+  snprintf (wconf.essid, IW_ESSID_MAX_SIZE + 1, "%s", essid);
     wconf.has_essid = 1;
     wconf.essid_on = 1;
     
@@ -174,12 +178,12 @@
     return 0;
 }
 
-static void unset_wep_key (char* iface)
+static void unset_wep_key (char *iface)
 {
     wireless_config wconf;
     int ret;
     
-    iw_get_basic_config(wfd, iface, &wconf);
+  iw_get_basic_config (wfd, iface, &wconf);
     
     wconf.has_key = 1;
     wconf.key[0] = '\0';
@@ -189,31 +193,52 @@
     ret = iw_set_basic_config (wfd, iface, &wconf);
 }
 
-int netcfg_wireless_set_wep (struct debconfclient * client, char* iface)
+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);
+  di_info("ret = %d", ret);
+
+  if (ret == 30)
+    return GO_BACK;
+
+  debconf_get (client, "netcfg/wireless_security_type");
+  di_info ("client->value = %s", client->value);
+
+  if (client->value[1] == 'e')
+     return WEPG;
+  else
+     return WPAG;
+
+}
+
+int netcfg_wireless_set_wep (struct debconfclient *client, char *iface)
 {
     wireless_config wconf;
-    char* rv = NULL;
+  char *rv = NULL;
     int ret, keylen, err = 0;
-    unsigned char buf [IW_ENCODING_TOKEN_MAX + 1];
+  unsigned char buf[IW_ENCODING_TOKEN_MAX + 1];
     struct iwreq wrq;
     
     iw_get_basic_config (wfd, iface, &wconf);
     
-    debconf_subst(client, "netcfg/wireless_wep", "iface", iface);
+  debconf_subst (client, "netcfg/wireless_wep", "iface", iface);
     debconf_input (client, "high", "netcfg/wireless_wep");
-    ret = debconf_go(client);
+  ret = debconf_go (client);
  
     if (ret == 30)
         return GO_BACK;
     
-    debconf_get(client, "netcfg/wireless_wep");
+  debconf_get (client, "netcfg/wireless_wep");
     rv = client->value;
     
-    if (empty_str(rv)) {
+  if (empty_str (rv)) {
         unset_wep_key (iface);
         
         if (wepkey != NULL) {
-            free(wepkey);
+	  free (wepkey);
             wepkey = NULL;
         }
         
@@ -221,35 +246,86 @@
     }
     
     while ((keylen = iw_in_key (rv, buf)) == -1) {
-        debconf_subst(client, "netcfg/invalid_wep", "wepkey", rv);
-        debconf_input(client, "critical", "netcfg/invalid_wep");
-        debconf_go(client);
+      debconf_subst (client, "netcfg/invalid_wep", "wepkey", rv);
+      debconf_input (client, "critical", "netcfg/invalid_wep");
+      debconf_go (client);
         
         debconf_input (client, "high", "netcfg/wireless_wep");
-        ret = debconf_go(client);
+      ret = debconf_go (client);
         
         if (ret == 30)
             return GO_BACK;
         
-        debconf_get(client, "netcfg/wireless_wep");
+      debconf_get (client, "netcfg/wireless_wep");
         rv = client->value;
     }
     
     /* Now rv is safe to store since it parsed fine */
-    wepkey = strdup(rv);
+  wepkey = strdup (rv);
     
     wrq.u.data.pointer = buf;
     wrq.u.data.flags = 0;
     wrq.u.data.length = keylen;
     
-    if ((err = iw_set_ext(skfd, iface, SIOCSIWENCODE, &wrq)) < 0) {
-        di_warning("setting WEP key on %s failed with code %d", iface, err);
+  if ((err = iw_set_ext (skfd, iface, SIOCSIWENCODE, &wrq)) < 0) {
+      di_warning ("setting WEP key on %s failed with code %d", iface, err);
         return -1;
     }
     
     return 0;
 }
 
+int netcfg_set_passphrase (struct debconfclient *client, char *iface)
+{
+  wireless_config wconf;
+  char *pass = NULL;
+  int ret, start;
+  di_info ("set pass");
+  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");
+  pass = client->value;
+
+  while (strlen (pass) < WPA_MIN || strlen (pass) > WPA_MAX) {
+      debconf_subst (client, "netcfg/invalid_pass", "passphrase", pass);
+      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");
+      pass = client->value;
+    }
+
+  passphrase = pass;
+  di_info ("passphrase == pass %s", passphrase);
+  start = netcfg_write_wpa (essid, passphrase);
+  if (start != 0)
+    return -1;
+  di_info ("netcfg_write_wpa");
+  start = start_wpa_supplicant (client);
+
+  if (start != 0)
+    return -1;
+  di_info ("start wpa");
+  return 0;
+}
+
+
 #else
 
 int is_wireless_iface (const char *iface)
@@ -273,4 +349,18 @@
     return 0;
 }
 
+int netcfg_wireless_set_security (struct debconfclient *client, char *iface)
+{
+  (void) client;
+  (void) iface;
+  return 0;
+}
+
+int netcfg_set_passphrase (struct debconfclient *client, char *iface)
+{
+  (void) client;
+  (void) iface;
+  return 0;
+}
+
 #endif
diff -Nurb ../netcfg-1.43/wpa.c netcfg-1.43/wpa.c
--- ../netcfg-1.43/wpa.c	1970-01-01 08:00:00.000000000 +0800
+++ netcfg-1.43/wpa.c	2008-04-18 22:14:33.000000000 +0800
@@ -0,0 +1,93 @@
+/*
+* WPA module for netcfg
+*
+* Copyright (C) 2008 Glenn Saberton <gsaberton@foomagic.org>
+*
+* Licensed under the terms of the GNU General Public License version 2
+*
+* Functions shamelessly copied from dhcp.c, if you are looking for comments
+* look in that file.
+*/
+
+#include "netcfg.h"
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <debian-installer.h>
+
+
+static int wpa_supplicant_exit_status = 1;
+pid_t wpa_supplicant_pid = -1;
+pid_t wpa_pid;
+pid_t wpa;
+/*
+* Build an /etc/wpa_supplicant.conf
+* file.
+*/
+
+int
+netcfg_write_wpa (char *essid, char *passphrase)
+{
+  FILE *fp;
+
+  if ((fp = file_open (WPASUPP_FILE, "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;
+}
+
+static void
+wpa_supplicant_sigchild (int sig __attribute__ ((unused)))
+{
+  if (wpa_supplicant_pid <= 0)
+    return;
+
+  waitpid (wpa_supplicant_pid, &wpa_supplicant_exit_status, 0);
+  wpa_supplicant_pid = -1;
+}
+
+int
+start_wpa_supplicant (struct debconfclient *client)
+{
+
+  if (access ("/sbin/wpa_supplicant", F_OK) == 0);
+
+  else
+    {
+      debconf_input (client, "critical", "netcfg/no_wpa_supplicant");
+      debconf_go (client);
+      exit (1);
+    }
+
+wpa_supplicant_pid = fork();
+
+  if (wpa_supplicant_pid == 0)
+    {
+        fclose(client->out);
+        wpa = (getpid() + 6);  /* I *know* this is horrendous, but I am too stupid to work it out  */
+
+        if (execlp ("wpa_supplicant", "wpa_supplicant", "-i", interface, "-c",
+                    "/etc/wpa_supplicant/wpa_supplicant.conf", "-B", NULL) == -1)
+          {
+           di_error("could not exec wpasupplicant: %s", strerror(errno));
+           return 1;
+          }
+        else
+             return 0;
+    } 
+  else
+    {
+     signal(SIGCHLD, &wpa_supplicant_sigchild);
+     return 0;
+    }
+}

Reply to: