Guest User

Untitled

a guest
Jul 22nd, 2018
205
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.52 KB | None | 0 0
  1. /*
  2. * Ultra_bcm_config - A utility that does one thing, pretty well.
  3. *
  4. * Andrew Robinson <andrew.robinson@gmail.com>
  5. *
  6. * Based off of the framework provided by iwconfig.c - the standard
  7. * linux wireless driver configuration tool. Modified to pass a special
  8. * structure to the custom Broadcom BCM4329 chipset driver running in the
  9. * kernel to enable AccessPoint mode, broadcasting of the SSID, and WEP/WPA
  10. * encryption.
  11. *
  12. * Also references a publically available implementation of the SHA1
  13. * hashing algorthim for WPA key generation. The BCM driver requires a fully
  14. * hashed key to enable WPA encryption. Function has been modified to return
  15. * proper ASCII characters for sending in the ASCII_CMD structure.
  16. *
  17. * TODO:
  18. * - Advanced error checking - We look for arg counts right now... more could
  19. * be done.
  20. * - TX Power Config - Easy call to bcm4329 driver, uses same offset as current.
  21. */
  22.  
  23. #include "iwlib.h"
  24.  
  25. #include <stdio.h>
  26. #include <stdlib.h>
  27.  
  28. #include "wpa_supplicant/includes.h"
  29. #include "wpa_supplicant/common.h"
  30. #include "wpa_supplicant/sha1.h"
  31.  
  32. #define WSEC_MAX_PSK_LEN 64
  33.  
  34. /**************************** CONSTANTS ****************************/
  35.  
  36. /*
  37. * Error codes defined for setting args
  38. */
  39. #define IWERR_ARG_NUM -2
  40. #define IWERR_ARG_TYPE -3
  41. #define IWERR_ARG_SIZE -4
  42. #define IWERR_ARG_CONFLICT -5
  43. #define IWERR_SET_EXT -6
  44. #define IWERR_GET_EXT -7
  45.  
  46.  
  47.  
  48. /**************************** VARIABLES ****************************/
  49.  
  50. /*
  51. * Deal with errors in set_info() efficiently...
  52. */
  53. static int errarg;
  54. static int errmax;
  55.  
  56.  
  57. static void
  58. build_ap_string(char * output,
  59. char * ssid,
  60. char * sec,
  61. char * key,
  62. char * channel,
  63. char secondString )
  64.  
  65. {
  66. if(secondString)
  67. {
  68. strcpy(output, "ASCII_CMD=AP_BSS_START,SSID=");
  69. output += 28;
  70. }
  71. else
  72. {
  73. strcpy(output, "ASCII_CMD=AP_CFG,SSID=");
  74. output += 22;
  75. }
  76.  
  77. strcpy(output, ssid);
  78. output += strlen(ssid);
  79.  
  80.  
  81. strcpy(output, ",SEC=");
  82. output += 5;
  83. strcpy(output, sec);
  84. output += strlen(sec);
  85.  
  86.  
  87. strcpy(output, ",KEY=");
  88. output += 5;
  89.  
  90. unsigned char psk[32];
  91.  
  92. pbkdf2_sha1(key, ssid, strlen(ssid), 4096, psk, 32);
  93. int i;
  94. char* ptr;
  95. char key_str_buf[WSEC_MAX_PSK_LEN+1];
  96. ptr = key_str_buf;
  97. for (i=0; i<(WSEC_MAX_PSK_LEN/8); i++){
  98. sprintf(ptr, "%02x%02x%02x%02x", (uint)psk[i*4], (uint)psk[i*4+1], (uint)psk[i*4+2], (uint)psk[i*4+3]);
  99. ptr += 8;
  100. }
  101. strcpy(output, key_str_buf);
  102. output += strlen(key_str_buf);
  103.  
  104. strcpy(output, ",CHANNEL=");
  105. output += 9;
  106. strcpy(output, channel);
  107. output += strlen(channel);
  108.  
  109. strcpy(output, ",PREAMBLE=0,MAX_SCB=8,END");
  110. output += 25;
  111. *output = 0;
  112. }
  113.  
  114. /*
  115. * set_mode_info
  116. * This function is completely original code
  117. */
  118. static int
  119. set_mode_info(int skfd, /* Socket name */
  120. char * ifname, /* Dev name */
  121. char * args[], /* Command line args */
  122. int count) /* Args count */
  123. {
  124.  
  125. /* The wrq pointer struct is a mechanism to pass data from user-land to kernel-space memory.
  126. * It has a allocatable field where we can stuff a struct of an arbitary size into it for
  127. * passing custom code to the driver
  128. */
  129. struct iwreq wrq;
  130. unsigned int k; /* Must be unsigned */
  131.  
  132. /* Arguments to be passed:
  133. 1 - AP Name
  134. 2 - Encryption Type
  135. 3 - Encryption Key (unencrypted)
  136. 4 - Channel Number (0 is automatically scan) */
  137.  
  138. // Some length error checking. Lengths are defined in iwlib.h as part of the ap_profile struct
  139. if(strlen(args[1]) > SSID_LEN)
  140. {
  141. errmax = IW_ESSID_MAX_SIZE;
  142. return(IWERR_ARG_SIZE);
  143. }
  144.  
  145. if(strlen(args[3]) > KEY_LEN)
  146. {
  147. errmax = IW_ESSID_MAX_SIZE;
  148. return(IWERR_ARG_SIZE);
  149. }
  150.  
  151. double freq;
  152. char * unit;
  153. freq = strtod(args[4], &unit);
  154.  
  155. /* This is the original functionality of set_mode in iwconfig.
  156. * It is not strictly nessessary anymore but will
  157. * make it look like the interface
  158. * is an access point to the kernel and iwconfig utilities,
  159. * instead of just making it
  160. * an access point and not showing anything.
  161. */
  162. wrq.u.mode = 3;
  163. if(iw_set_ext(skfd, ifname, SIOCSIWMODE, &wrq) < 0)
  164. return(IWERR_SET_EXT);
  165.  
  166. /* There are two different versions of the bcm driver on android phones. For some
  167. it requires us to build an ASCII string in memory and then send that string to the driver
  168. using io_ctl commands. The other version requires us to use a struct and send a more compact
  169. binary representation of the data to the driver. I believe google will be looking to use the first
  170. method because it's dead simple. We switch on arg[0] to determine
  171. */
  172. if(!strcmp(args[0], "softap_htc"))
  173. {
  174. /* STANDARD STRUCT BUILDING MODE */
  175. if(strlen(args[2]) > SEC_LEN)
  176. {
  177. errmax = IW_ESSID_MAX_SIZE;
  178. return(IWERR_ARG_SIZE);
  179. }
  180.  
  181. /* Data is a union member of what can be stored within the wrq pointer. In this case we set it to the maximum string
  182. length and manually allocate memory for it.
  183. */
  184. wrq.u.data.length = 162;
  185. wrq.u.data.pointer = malloc(162);
  186.  
  187. /* Now that we have 162 bytes of free memory allocation is important. The way
  188. the bcm driver hands it is it does a strcom on the first 31 characters and stores
  189. the command string within this block of memory. We will now write the required
  190. piece into memory
  191. */
  192. strcpy(wrq.u.data.pointer, "AP_PROFILE_SET");
  193.  
  194. /* ap_profile is defined in iwlib by me.
  195. * we toss it 32 bytes deep into the wrq pointer, because
  196. * the bcm driver expects it there.
  197. */
  198.  
  199. /* Create a ap_profile pointer and assign it to a memory location 32 bytes deep within the wrq data struct */
  200. struct ap_profile * ap = (struct ap_profile *)(wrq.u.data.pointer + 32);
  201.  
  202. /* Setup our payload for delivery */
  203. strcpy(ap->ssid,args[1]);
  204. strcpy(ap->sec ,args[2]);
  205. strcpy(ap->key , args[3]);
  206.  
  207. /* 0 means auto config on the channel. I recommend using that one.*/
  208. ap->channel = (int) freq;
  209. ap->max_scb = 2;
  210.  
  211. /* Pass the wrq structure deep into kernel memory for copying and processing. */
  212. if(iw_set_ext(skfd, ifname, SIOCSIWPRIV, &wrq) < 0)
  213. return(IWERR_SET_EXT);
  214. }
  215. else
  216. {
  217. /* ASCII STRING BUILD */
  218.  
  219. /* maxmimum length of this string will be <300 bytes */
  220. wrq.u.data.length = 300;
  221. wrq.u.data.pointer = malloc(300);
  222.  
  223. /* Test commands + formatting template:
  224. //char *cmd = "ASCII_CMD= ASCII_CMD=AP_CFG,SSID=AndroidTether,SEC=open,KEY=28e4636bb4e166ab752b859f7b2bc7b26db3d817b5ef79965f48fd76be8d2a19,CHANNEL=6,PREAMBLE=0,MAX_SCB=8,END";
  225. //char *cmd2 = "ASCII_CMD= ASCII_CMD=AP_BSS_START,SSID=AndroidTether,SEC=open,KEY=28e4636bb4e166ab752b859f7b2bc7b26db3d817b5ef79965f48fd76be8d2a19,CHANNEL=6,PREAMBLE=0,MAX_SCB=8,END";
  226. */
  227.  
  228. /* Added 32 spaces and command text for command */
  229. char cmd[267] = "ASCII_CMD= ";
  230.  
  231. /* Call string builder function */
  232. build_ap_string(cmd+32,args[1],args[2],args[3],args[4],0);
  233. fprintf(stderr, cmd);
  234. strcpy(wrq.u.data.pointer, cmd);
  235. if(iw_set_ext(skfd, ifname, SIOCSIWPRIV, &wrq) < 0)
  236. return(IWERR_SET_EXT);
  237.  
  238. build_ap_string(cmd+32,args[1],args[2],args[3],args[4],1);
  239. fprintf(stderr, cmd);
  240. strcpy(wrq.u.data.pointer, cmd);
  241. if(iw_set_ext(skfd, ifname, SIOCSIWPRIV, &wrq) < 0)
  242. return(IWERR_SET_EXT);
  243. }
  244.  
  245. /* Free allocated memory. */
  246. free(wrq.u.data.pointer);
  247. return(1);
  248. }
  249.  
  250. /*
  251. * set_info
  252. * In the original iwconfig file this function acted as a branching conditional function that would ferry the input parameters to the
  253. neccesary functions and deal with return values. Even though we only have one command I have left it in tact for future expansion.
  254. */
  255. static int
  256. set_info(int skfd, /* The socket */
  257. char * args[], /* Command line args */
  258. int count, /* Args count */
  259. char * ifname) /* Dev name */
  260. {
  261.  
  262. int ret;
  263.  
  264. /* Call the command */
  265. ret = set_mode_info(skfd, ifname, args, count);
  266.  
  267. /* Deal with various errors, taken from iwconfig.c */
  268. if(ret < 0)
  269. {
  270. switch(ret)
  271. {
  272. case IWERR_ARG_NUM:
  273. fprintf(stderr, " too few arguments.\n");
  274. break;
  275. case IWERR_ARG_TYPE:
  276. if(errarg < 0)
  277. errarg = 0;
  278. if(errarg >= count)
  279. errarg = count - 1;
  280. fprintf(stderr, " invalid argument \"%s\".\n", args[errarg]);
  281. break;
  282. case IWERR_ARG_SIZE:
  283. fprintf(stderr, " argument too big (max %d)\n", errmax);
  284. break;
  285. case IWERR_ARG_CONFLICT:
  286. if(errarg < 0)
  287. errarg = 0;
  288. if(errarg >= count)
  289. errarg = count - 1;
  290. fprintf(stderr, " conflicting argument \"%s\".\n", args[errarg]);
  291. break;
  292. case IWERR_SET_EXT:
  293. fprintf(stderr, " SET failed on device %-1.16s ; %s.\n",
  294. ifname, strerror(errno));
  295. break;
  296. case IWERR_GET_EXT:
  297. fprintf(stderr, " GET failed on device %-1.16s ; %s.\n",
  298. ifname, strerror(errno));
  299. break;
  300. }
  301. return(ret);
  302. }
  303. /* Done, all done */
  304. return(0);
  305. }
  306.  
  307. /*
  308. * MAIN Body. Returns 0 on success, -1 on failure to the system
  309. */
  310. int
  311. main(int argc,
  312. char ** argv)
  313. {
  314. /* Raw socket descriptor, skfd is -1 on failure to open */
  315. int skfd;
  316. int goterr = 0;
  317.  
  318. /* Create a channel to the NET kernel using iw system call, defined in iwlib.h. */
  319. /* All io_ctl will be carried out referencing this socket descripter*/
  320. if((skfd = iw_sockets_open()) < 0)
  321. {
  322. perror("socket");
  323. exit(-1);
  324. }
  325.  
  326. /* Ensure the proper number of arguments has been passed */
  327. if(argc == 7)
  328. /* The other args on the line specify options to be set... */
  329. goterr = set_info(skfd, argv + 2, argc - 2, argv[1]);
  330. else
  331. {
  332. goterr = -1;
  333. fprintf(stderr, "Wrong number of args.");
  334. }
  335. /* Close the NET socket. */
  336. iw_sockets_close(skfd);
  337. return(goterr);
  338. }
Add Comment
Please, Sign In to add comment