You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

wpa.c 10 KiB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423
  1. /*
  2. * WPA module for netcfg
  3. *
  4. * Copyright (C) 2008 Glenn Saberton <gsaberton@foomagic.org>
  5. *
  6. * Licensed under the terms of the GNU General Public License version 2
  7. *
  8. */
  9. #include "netcfg.h"
  10. #include <errno.h>
  11. #include <stdlib.h>
  12. #include <unistd.h>
  13. #include <debian-installer.h>
  14. #include "wpa_ctrl.h"
  15. #include <iwlib.h>
  16. pid_t wpa_supplicant_pid = -1;
  17. enum wpa_t wpa_supplicant_status;
  18. struct wpa_ctrl *ctrl;
  19. char *passphrase = NULL;
  20. static int wpa_is_running = 0;
  21. int init_wpa_supplicant_support(void)
  22. {
  23. if (access("/sbin/wpa_supplicant", F_OK) == 0)
  24. wpa_supplicant_status = WPA_OK;
  25. else {
  26. wpa_supplicant_status = WPA_UNAVAIL;
  27. di_info("Wpasupplicant not found on the system. Disabling WPA options");
  28. }
  29. return 0;
  30. }
  31. int kill_wpa_supplicant(void)
  32. {
  33. pid_t wpa_pid;
  34. FILE *fp;
  35. fp = (fopen(WPAPID, "r"));
  36. if (fp == NULL) {
  37. di_warning("Couldn't read Wpasupplicant pid file, not trying to kill.");
  38. return 0;
  39. }
  40. else {
  41. fscanf(fp, "%d", &wpa_pid);
  42. fclose(fp);
  43. }
  44. if ((kill(wpa_pid, SIGTERM)) == 0)
  45. return 0;
  46. else {
  47. kill(wpa_pid, SIGKILL);
  48. unlink(WPAPID);
  49. return 0;
  50. }
  51. }
  52. int wireless_security_type (struct debconfclient *client, char *iface)
  53. {
  54. int ret = 0 ;
  55. debconf_subst(client, "netcfg/wireless_security_type", "iface", iface);
  56. debconf_input(client, "high", "netcfg/wireless_security_type");
  57. ret = debconf_go(client);
  58. if (ret == 30)
  59. return GO_BACK;
  60. debconf_get(client, "netcfg/wireless_security_type");
  61. if (!strcmp(client->value, "wep/open"))
  62. return REPLY_WEP;
  63. else
  64. return REPLY_WPA;
  65. }
  66. int netcfg_set_passphrase (struct debconfclient *client, char *iface)
  67. {
  68. int ret;
  69. debconf_subst(client, "netcfg/wireless_wpa", "iface", iface);
  70. debconf_input(client, "high", "netcfg/wireless_wpa");
  71. ret = debconf_go(client);
  72. if (ret == 30)
  73. return GO_BACK;
  74. if (passphrase != NULL)
  75. free(passphrase);
  76. debconf_get(client, "netcfg/wireless_wpa");
  77. passphrase = strdup(client->value);
  78. while (strlen(passphrase) < WPA_MIN || strlen(passphrase) > WPA_MAX) {
  79. debconf_subst(client, "netcfg/invalid_pass", "passphrase", passphrase);
  80. debconf_input(client, "critical", "netcfg/invalid_pass");
  81. debconf_go(client);
  82. free(passphrase);
  83. debconf_input(client, "high", "netcfg/wireless_wpa");
  84. ret = debconf_go(client);
  85. if (ret == 30)
  86. return GO_BACK;
  87. debconf_get(client, "netcfg/wireless_wpa");
  88. passphrase = strdup(client->value);
  89. }
  90. return 0;
  91. }
  92. static int start_wpa_daemon(struct debconfclient *client)
  93. {
  94. wpa_supplicant_pid = fork();
  95. if (wpa_supplicant_pid == 0) {
  96. fclose(client->out);
  97. if (execlp("wpa_supplicant", "wpa_supplicant", "-i", interface, "-C",
  98. WPASUPP_CTRL, "-P", WPAPID, "-B", NULL) == -1) {
  99. di_error("could not exec wpasupplicant: %s", strerror(errno));
  100. return 1;
  101. }
  102. else
  103. return 0;
  104. }
  105. else {
  106. waitpid(wpa_supplicant_pid, NULL, 0);
  107. return 0;
  108. }
  109. }
  110. void wpa_daemon_running(void)
  111. {
  112. FILE *fp = fopen(WPAPID, "r");
  113. if (fp) {
  114. wpa_is_running = 1;
  115. fclose(fp);
  116. }
  117. }
  118. static int wpa_connect(char *iface)
  119. {
  120. char *cfile;
  121. int flen, res;
  122. flen = (strlen(WPASUPP_CTRL) + strlen(iface) + 2);
  123. cfile = malloc(flen);
  124. if (cfile == NULL) {
  125. di_info("Can't allocate memory for WPA control iface.");
  126. return 1;
  127. }
  128. res = snprintf(cfile, flen, "%s/%s", WPASUPP_CTRL, iface);
  129. if ((res < 0) || (res >= flen)) {
  130. free(cfile);
  131. return 1;
  132. }
  133. ctrl = wpa_ctrl_open(cfile);
  134. free(cfile);
  135. if (ctrl == NULL) {
  136. di_info("Couldn't connect to wpasupplicant");
  137. return 1;
  138. }
  139. else
  140. return 0;
  141. }
  142. static int netcfg_wpa_cmd (char *cmd)
  143. {
  144. char buf[256];
  145. size_t len;
  146. int ret;
  147. len = sizeof(buf) -1;
  148. ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len, NULL);
  149. if (ret < 0) {
  150. di_info("Sending %s to wpasupplicant failed", cmd);
  151. return 1;
  152. }
  153. return 0;
  154. }
  155. static int wpa_set_ssid (char *ssid)
  156. {
  157. int ret, res;
  158. size_t len;
  159. char cmd[256];
  160. char buf[256];
  161. res = snprintf(cmd, sizeof(cmd), "SET_NETWORK 0 %s \"%s\"", "ssid", ssid);
  162. if (res < 0)
  163. return 1;
  164. len = sizeof(buf) -1;
  165. ret = wpa_ctrl_request(ctrl, cmd, sizeof(cmd), buf, &len, NULL);
  166. if (ret != 0) {
  167. di_info("Failed to set the ssid with wpasupplicant");
  168. return 1;
  169. }
  170. return 0;
  171. }
  172. static int wpa_set_psk(char *passphrase)
  173. {
  174. int ret, res;
  175. size_t len;
  176. char buf[256];
  177. char cmd[256];
  178. res = snprintf(cmd, sizeof(cmd), "SET_NETWORK 0 %s \"%s\"", "psk", passphrase);
  179. if (res < 0)
  180. return 1;
  181. len = sizeof(buf) -1;
  182. ret = wpa_ctrl_request(ctrl, cmd, sizeof(cmd), buf, &len, NULL);
  183. if (ret != 0)
  184. return 1;
  185. return 0;
  186. }
  187. static int wpa_status(void)
  188. {
  189. int ret;
  190. size_t len;
  191. char buf[2048];
  192. const char *success = "wpa_state=COMPLETED";
  193. len = sizeof(buf) -1;
  194. ret = wpa_ctrl_request(ctrl, "STATUS", 7, buf, &len, NULL);
  195. if (ret == 0) {
  196. buf[len] = '\0';
  197. di_info("buf = %s", buf);
  198. }
  199. else
  200. return 1;
  201. if (strstr(buf, success) == NULL)
  202. return 1;
  203. else {
  204. di_info("success");
  205. return 0;
  206. }
  207. }
  208. int poll_wpa_supplicant(struct debconfclient *client)
  209. {
  210. int wpa_timeout = 60;
  211. int seconds_slept = 0;
  212. int state = 1;
  213. debconf_capb(client, "backup progresscancel");
  214. debconf_progress_start(client, 0, wpa_timeout, "netcfg/wpa_progress");
  215. for (seconds_slept = 0; seconds_slept <= wpa_timeout; seconds_slept++) {
  216. if (debconf_progress_info(client, "netcfg/wpa_progress_note") == 30)
  217. goto stop;
  218. if (debconf_progress_step(client, 1) == 30)
  219. goto stop;
  220. sleep(1);
  221. if ((seconds_slept <= wpa_timeout) && (seconds_slept % 5) == 0) {
  222. if (!wpa_status()) {
  223. debconf_progress_set(client, wpa_timeout);
  224. debconf_progress_info(client, "netcfg/wpa_success_note");
  225. state = 0;
  226. sleep(2);
  227. goto stop;
  228. }
  229. }
  230. if (seconds_slept == wpa_timeout) {
  231. debconf_progress_stop(client);
  232. debconf_capb(client, "backup");
  233. debconf_capb(client, "");
  234. debconf_input(client, "critical", "netcfg/wpa_supplicant_failed");
  235. debconf_go(client);
  236. debconf_capb(client, "backup");
  237. return 1;
  238. }
  239. }
  240. stop:
  241. debconf_progress_stop(client);
  242. debconf_capb(client, "backup");
  243. if (!state)
  244. return 0;
  245. else
  246. return 1;
  247. }
  248. int wpa_supplicant_start(struct debconfclient *client, char *iface, char *ssid, char *passphrase)
  249. {
  250. int retry = 0;
  251. enum { CHECK_DAEMON,
  252. START_DAEMON,
  253. CONNECT,
  254. PING,
  255. ADD_NETWORK,
  256. SET_ESSID,
  257. SET_PSK,
  258. SET_SCAN_SSID,
  259. ENABLE_NETWORK,
  260. POLL,
  261. ABORT,
  262. SUCCESS } state = CHECK_DAEMON;
  263. for (;;) {
  264. switch(state) {
  265. case CHECK_DAEMON:
  266. wpa_daemon_running();
  267. if (wpa_is_running)
  268. state = CONNECT;
  269. else
  270. state = START_DAEMON;
  271. break;
  272. case START_DAEMON:
  273. if (!start_wpa_daemon(client))
  274. state = CONNECT;
  275. else
  276. state = ABORT;
  277. break;
  278. case CONNECT:
  279. if (wpa_connect(iface) == 0)
  280. state = PING;
  281. else
  282. state = ABORT;
  283. break;
  284. case PING:
  285. /* if the daemon doesn't respond, try and ping
  286. * it and increment retry. If we have done
  287. * this 4 times, something must be wrong
  288. * so bail out. */
  289. retry++;
  290. if (retry > 4)
  291. state = ABORT;
  292. else if (netcfg_wpa_cmd("PING")) {
  293. kill_wpa_supplicant();
  294. state = START_DAEMON;
  295. break;
  296. }
  297. else
  298. state = ADD_NETWORK;
  299. break;
  300. case ADD_NETWORK:
  301. if (wpa_is_running) {
  302. state = SET_ESSID;
  303. break;
  304. }
  305. if (netcfg_wpa_cmd("ADD_NETWORK"))
  306. state = PING;
  307. else
  308. state = SET_ESSID;
  309. break;
  310. case SET_ESSID:
  311. if (wpa_set_ssid(ssid))
  312. state = PING;
  313. else
  314. state = SET_PSK;
  315. break;
  316. case SET_PSK:
  317. if (wpa_set_psk(passphrase))
  318. state = PING;
  319. else
  320. state = SET_SCAN_SSID;
  321. break;
  322. case SET_SCAN_SSID:
  323. if (netcfg_wpa_cmd("SET_NETWORK 0 scan_ssid 1"))
  324. state = PING;
  325. else
  326. state = ENABLE_NETWORK;
  327. break;
  328. case ENABLE_NETWORK:
  329. if (netcfg_wpa_cmd("ENABLE_NETWORK 0"))
  330. state = PING;
  331. else
  332. state = POLL;
  333. break;
  334. case POLL:
  335. if (poll_wpa_supplicant(client))
  336. state = ABORT;
  337. else
  338. state = SUCCESS;
  339. break;
  340. case ABORT:
  341. if (ctrl == NULL)
  342. return GO_BACK;
  343. else {
  344. wpa_ctrl_close(ctrl);
  345. ctrl = NULL;
  346. return GO_BACK;
  347. }
  348. case SUCCESS:
  349. if (ctrl == NULL)
  350. return 0;
  351. else {
  352. wpa_ctrl_close(ctrl);
  353. ctrl = NULL;
  354. return 0;
  355. }
  356. }
  357. }
  358. }