ieee80211softmac_auth.c 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  1. #include "ieee80211softmac_priv.h"
  2. static void ieee80211softmac_auth_queue(void *data);
  3. /* Queues an auth request to the desired AP */
  4. int
  5. ieee80211softmac_auth_req(struct ieee80211softmac_device *mac,
  6. struct ieee80211softmac_network *net)
  7. {
  8. struct ieee80211softmac_auth_queue_item *auth;
  9. unsigned long flags;
  10. function_enter();
  11. if (net->authenticating)
  12. return 0;
  13. /* Add the network if it's not already added */
  14. ieee80211softmac_add_network(mac, net);
  15. dprintk(KERN_NOTICE PFX "Queueing Authentication Request to "MAC_FMT"\n", MAC_ARG(net->bssid));
  16. /* Queue the auth request */
  17. auth = (struct ieee80211softmac_auth_queue_item *)
  18. kmalloc(sizeof(struct ieee80211softmac_auth_queue_item), GFP_KERNEL);
  19. if(auth == NULL)
  20. return -ENOMEM;
  21. auth->net = net;
  22. auth->mac = mac;
  23. auth->retry = IEEE80211SOFTMAC_AUTH_RETRY_LIMIT;
  24. auth->state = IEEE80211SOFTMAC_AUTH_OPEN_REQUEST;
  25. INIT_WORK(&auth->work, &ieee80211softmac_auth_queue, (void *)auth);
  26. /* Lock (for list) */
  27. spin_lock_irqsave(&mac->lock, flags);
  28. /* add to list */
  29. list_add_tail(&auth->list, &mac->auth_queue);
  30. queue_work(mac->workqueue, &auth->work);
  31. spin_unlock_irqrestore(&mac->lock, flags);
  32. return 0;
  33. }
  34. /* Sends an auth request to the desired AP and handles timeouts */
  35. static void
  36. ieee80211softmac_auth_queue(void *data)
  37. {
  38. struct ieee80211softmac_device *mac;
  39. struct ieee80211softmac_auth_queue_item *auth;
  40. struct ieee80211softmac_network *net;
  41. unsigned long flags;
  42. function_enter();
  43. auth = (struct ieee80211softmac_auth_queue_item *)data;
  44. net = auth->net;
  45. mac = auth->mac;
  46. if(auth->retry > 0) {
  47. /* Switch to correct channel for this network */
  48. mac->set_channel(mac->dev, net->channel);
  49. /* Lock and set flags */
  50. spin_lock_irqsave(&mac->lock, flags);
  51. net->authenticated = 0;
  52. net->authenticating = 1;
  53. /* add a timeout call so we eventually give up waiting for an auth reply */
  54. queue_delayed_work(mac->workqueue, &auth->work, IEEE80211SOFTMAC_AUTH_TIMEOUT);
  55. auth->retry--;
  56. spin_unlock_irqrestore(&mac->lock, flags);
  57. if (ieee80211softmac_send_mgt_frame(mac, auth->net, IEEE80211_STYPE_AUTH, auth->state))
  58. dprintk(KERN_NOTICE PFX "Sending Authentication Request to "MAC_FMT" failed (this shouldn't happen, wait for the timeout).\n", MAC_ARG(net->bssid));
  59. else
  60. dprintk(KERN_NOTICE PFX "Sent Authentication Request to "MAC_FMT".\n", MAC_ARG(net->bssid));
  61. return;
  62. }
  63. printkl(KERN_WARNING PFX "Authentication timed out with "MAC_FMT"\n", MAC_ARG(net->bssid));
  64. /* Remove this item from the queue */
  65. spin_lock_irqsave(&mac->lock, flags);
  66. ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_AUTH_TIMEOUT, net);
  67. cancel_delayed_work(&auth->work); /* just to make sure... */
  68. list_del(&auth->list);
  69. spin_unlock_irqrestore(&mac->lock, flags);
  70. /* Free it */
  71. kfree(auth);
  72. }
  73. /* Handle the auth response from the AP
  74. * This should be registered with ieee80211 as handle_auth
  75. */
  76. int
  77. ieee80211softmac_auth_resp(struct net_device *dev, struct ieee80211_auth *auth)
  78. {
  79. struct list_head *list_ptr;
  80. struct ieee80211softmac_device *mac = ieee80211_priv(dev);
  81. struct ieee80211softmac_auth_queue_item *aq = NULL;
  82. struct ieee80211softmac_network *net = NULL;
  83. unsigned long flags;
  84. u8 * data;
  85. function_enter();
  86. /* Find correct auth queue item */
  87. spin_lock_irqsave(&mac->lock, flags);
  88. list_for_each(list_ptr, &mac->auth_queue) {
  89. aq = list_entry(list_ptr, struct ieee80211softmac_auth_queue_item, list);
  90. net = aq->net;
  91. if (!memcmp(net->bssid, auth->header.addr2, ETH_ALEN))
  92. break;
  93. else
  94. aq = NULL;
  95. }
  96. spin_unlock_irqrestore(&mac->lock, flags);
  97. /* Make sure that we've got an auth queue item for this request */
  98. if(aq == NULL)
  99. {
  100. printkl(KERN_DEBUG PFX "Authentication response received from "MAC_FMT" but no queue item exists.\n", MAC_ARG(auth->header.addr2));
  101. /* Error #? */
  102. return -1;
  103. }
  104. /* Check for out of order authentication */
  105. if(!net->authenticating)
  106. {
  107. printkl(KERN_DEBUG PFX "Authentication response received from "MAC_FMT" but did not request authentication.\n",MAC_ARG(auth->header.addr2));
  108. return -1;
  109. }
  110. /* Parse the auth packet */
  111. switch(auth->algorithm) {
  112. case WLAN_AUTH_OPEN:
  113. /* Check the status code of the response */
  114. switch(auth->status) {
  115. case WLAN_STATUS_SUCCESS:
  116. /* Update the status to Authenticated */
  117. spin_lock_irqsave(&mac->lock, flags);
  118. net->authenticating = 0;
  119. net->authenticated = 1;
  120. spin_unlock_irqrestore(&mac->lock, flags);
  121. /* Send event */
  122. printkl(KERN_NOTICE PFX "Open Authentication completed with "MAC_FMT"\n", MAC_ARG(net->bssid));
  123. ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_AUTHENTICATED, net);
  124. break;
  125. default:
  126. /* Lock and reset flags */
  127. spin_lock_irqsave(&mac->lock, flags);
  128. net->authenticated = 0;
  129. net->authenticating = 0;
  130. spin_unlock_irqrestore(&mac->lock, flags);
  131. printkl(KERN_NOTICE PFX "Open Authentication with "MAC_FMT" failed, error code: %i\n",
  132. MAC_ARG(net->bssid), le16_to_cpup(&auth->status));
  133. /* Count the error? */
  134. break;
  135. }
  136. goto free_aq;
  137. break;
  138. case WLAN_AUTH_SHARED_KEY:
  139. /* Figure out where we are in the process */
  140. switch(auth->transaction) {
  141. case IEEE80211SOFTMAC_AUTH_SHARED_CHALLENGE:
  142. /* Check to make sure we have a challenge IE */
  143. data = (u8 *)auth->info_element;
  144. if(*data++ != MFIE_TYPE_CHALLENGE){
  145. printkl(KERN_NOTICE PFX "Shared Key Authentication failed due to a missing challenge.\n");
  146. break;
  147. }
  148. /* Save the challenge */
  149. spin_lock_irqsave(&mac->lock, flags);
  150. net->challenge_len = *data++;
  151. if(net->challenge_len > WLAN_AUTH_CHALLENGE_LEN)
  152. net->challenge_len = WLAN_AUTH_CHALLENGE_LEN;
  153. if(net->challenge != NULL)
  154. kfree(net->challenge);
  155. net->challenge = kmalloc(net->challenge_len, GFP_ATOMIC);
  156. memcpy(net->challenge, data, net->challenge_len);
  157. aq->state = IEEE80211SOFTMAC_AUTH_SHARED_RESPONSE;
  158. spin_unlock_irqrestore(&mac->lock, flags);
  159. /* Switch to correct channel for this network */
  160. mac->set_channel(mac->dev, net->channel);
  161. /* Send our response (How to encrypt?) */
  162. ieee80211softmac_send_mgt_frame(mac, aq->net, IEEE80211_STYPE_AUTH, aq->state);
  163. break;
  164. case IEEE80211SOFTMAC_AUTH_SHARED_PASS:
  165. /* Check the status code of the response */
  166. switch(auth->status) {
  167. case WLAN_STATUS_SUCCESS:
  168. /* Update the status to Authenticated */
  169. spin_lock_irqsave(&mac->lock, flags);
  170. net->authenticating = 0;
  171. net->authenticated = 1;
  172. spin_unlock_irqrestore(&mac->lock, flags);
  173. printkl(KERN_NOTICE PFX "Shared Key Authentication completed with "MAC_FMT"\n",
  174. MAC_ARG(net->bssid));
  175. break;
  176. default:
  177. printkl(KERN_NOTICE PFX "Shared Key Authentication with "MAC_FMT" failed, error code: %i\n",
  178. MAC_ARG(net->bssid), le16_to_cpup(&auth->status));
  179. /* Lock and reset flags */
  180. spin_lock_irqsave(&mac->lock, flags);
  181. net->authenticating = 0;
  182. net->authenticated = 0;
  183. spin_unlock_irqrestore(&mac->lock, flags);
  184. /* Count the error? */
  185. break;
  186. }
  187. goto free_aq;
  188. break;
  189. default:
  190. printkl(KERN_WARNING PFX "Unhandled Authentication Step: %i\n", auth->transaction);
  191. break;
  192. }
  193. goto free_aq;
  194. break;
  195. default:
  196. /* ERROR */
  197. goto free_aq;
  198. break;
  199. }
  200. return 0;
  201. free_aq:
  202. /* Cancel the timeout */
  203. spin_lock_irqsave(&mac->lock, flags);
  204. cancel_delayed_work(&aq->work);
  205. /* Remove this item from the queue */
  206. list_del(&aq->list);
  207. spin_unlock_irqrestore(&mac->lock, flags);
  208. /* Free it */
  209. kfree(aq);
  210. return 0;
  211. }
  212. /*
  213. * Handle deauthorization
  214. */
  215. void
  216. ieee80211softmac_deauth_from_net(struct ieee80211softmac_device *mac,
  217. struct ieee80211softmac_network *net)
  218. {
  219. struct ieee80211softmac_auth_queue_item *aq = NULL;
  220. struct list_head *list_ptr;
  221. unsigned long flags;
  222. function_enter();
  223. /* Lock and reset status flags */
  224. spin_lock_irqsave(&mac->lock, flags);
  225. net->authenticating = 0;
  226. net->authenticated = 0;
  227. /* Find correct auth queue item, if it exists */
  228. list_for_each(list_ptr, &mac->auth_queue) {
  229. aq = list_entry(list_ptr, struct ieee80211softmac_auth_queue_item, list);
  230. if (!memcmp(net->bssid, aq->net->bssid, ETH_ALEN))
  231. break;
  232. else
  233. aq = NULL;
  234. }
  235. /* Cancel pending work */
  236. if(aq != NULL)
  237. /* Not entirely safe? What about running work? */
  238. cancel_delayed_work(&aq->work);
  239. /* Free our network ref */
  240. ieee80211softmac_del_network_locked(mac, net);
  241. if(net->challenge != NULL)
  242. kfree(net->challenge);
  243. kfree(net);
  244. /* let's try to re-associate */
  245. queue_work(mac->workqueue, &mac->associnfo.work);
  246. spin_unlock_irqrestore(&mac->lock, flags);
  247. }
  248. /*
  249. * Sends a deauth request to the desired AP
  250. */
  251. int
  252. ieee80211softmac_deauth_req(struct ieee80211softmac_device *mac,
  253. struct ieee80211softmac_network *net, int reason)
  254. {
  255. int ret;
  256. function_enter();
  257. /* Make sure the network is authenticated */
  258. if (!net->authenticated)
  259. {
  260. printkl(KERN_DEBUG PFX "Can't send deauthentication packet, network is not authenticated.\n");
  261. /* Error okay? */
  262. return -EPERM;
  263. }
  264. /* Send the de-auth packet */
  265. if((ret = ieee80211softmac_send_mgt_frame(mac, net, IEEE80211_STYPE_DEAUTH, reason)))
  266. return ret;
  267. ieee80211softmac_deauth_from_net(mac, net);
  268. return 0;
  269. }
  270. /*
  271. * This should be registered with ieee80211 as handle_deauth
  272. */
  273. int
  274. ieee80211softmac_deauth_resp(struct net_device *dev, struct ieee80211_auth *auth)
  275. {
  276. struct ieee80211softmac_network *net = NULL;
  277. struct ieee80211softmac_device *mac = ieee80211_priv(dev);
  278. function_enter();
  279. if (!auth) {
  280. dprintk("deauth without deauth packet. eek!\n");
  281. return 0;
  282. }
  283. net = ieee80211softmac_get_network_by_bssid(mac, auth->header.addr2);
  284. if (net == NULL) {
  285. printkl(KERN_DEBUG PFX "Recieved deauthentication packet from "MAC_FMT", but that network is unknown.\n",
  286. MAC_ARG(auth->header.addr2));
  287. return 0;
  288. }
  289. /* Make sure the network is authenticated */
  290. if(!net->authenticated)
  291. {
  292. printkl(KERN_DEBUG PFX "Can't perform deauthentication, network is not authenticated.\n");
  293. /* Error okay? */
  294. return -EPERM;
  295. }
  296. ieee80211softmac_deauth_from_net(mac, net);
  297. return 0;
  298. }