wps_ufd.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. /*
  2. * UFD routines for Wi-Fi Protected Setup
  3. * Copyright (c) 2009, Masashi Honma <honma@ictec.co.jp>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License version 2 as
  7. * published by the Free Software Foundation.
  8. *
  9. * Alternatively, this software may be distributed under the terms of BSD
  10. * license.
  11. *
  12. * See README and COPYING for more details.
  13. */
  14. #include "includes.h"
  15. #include "common.h"
  16. #include <sys/types.h>
  17. #include <sys/stat.h>
  18. #include <sys/wait.h>
  19. #include <fcntl.h>
  20. #include <dirent.h>
  21. #include "wps/wps.h"
  22. #include "wps/wps_i.h"
  23. #ifdef CONFIG_NATIVE_WINDOWS
  24. #define UFD_DIR1 "%s\\SMRTNTKY"
  25. #define UFD_DIR2 UFD_DIR1 "\\WFAWSC"
  26. #define UFD_FILE UFD_DIR2 "\\%s"
  27. #else /* CONFIG_NATIVE_WINDOWS */
  28. #define UFD_DIR1 "%s/SMRTNTKY"
  29. #define UFD_DIR2 UFD_DIR1 "/WFAWSC"
  30. #define UFD_FILE UFD_DIR2 "/%s"
  31. #endif /* CONFIG_NATIVE_WINDOWS */
  32. struct wps_ufd_data {
  33. int ufd_fd;
  34. };
  35. static int dev_pwd_e_file_filter(const struct dirent *entry)
  36. {
  37. unsigned int prefix;
  38. char ext[5];
  39. if (sscanf(entry->d_name, "%8x.%4s", &prefix, ext) != 2)
  40. return 0;
  41. if (prefix == 0)
  42. return 0;
  43. if (os_strcasecmp(ext, "WFA") != 0)
  44. return 0;
  45. return 1;
  46. }
  47. static int wps_get_dev_pwd_e_file_name(char *path, char *file_name)
  48. {
  49. struct dirent **namelist;
  50. int i, file_num;
  51. file_num = scandir(path, &namelist, &dev_pwd_e_file_filter,
  52. alphasort);
  53. if (file_num < 0) {
  54. wpa_printf(MSG_ERROR, "WPS: OOB file not found: %d (%s)",
  55. errno, strerror(errno));
  56. return -1;
  57. }
  58. if (file_num == 0) {
  59. wpa_printf(MSG_ERROR, "WPS: OOB file not found");
  60. os_free(namelist);
  61. return -1;
  62. }
  63. os_strlcpy(file_name, namelist[0]->d_name, 13);
  64. for (i = 0; i < file_num; i++)
  65. os_free(namelist[i]);
  66. os_free(namelist);
  67. return 0;
  68. }
  69. static int get_file_name(struct wps_context *wps, int registrar,
  70. const char *path, char *file_name)
  71. {
  72. switch (wps->oob_conf.oob_method) {
  73. case OOB_METHOD_CRED:
  74. os_snprintf(file_name, 13, "00000000.WSC");
  75. break;
  76. case OOB_METHOD_DEV_PWD_E:
  77. if (registrar) {
  78. char temp[128];
  79. os_snprintf(temp, sizeof(temp), UFD_DIR2, path);
  80. if (wps_get_dev_pwd_e_file_name(temp, file_name) < 0)
  81. return -1;
  82. } else {
  83. u8 *mac_addr = wps->dev.mac_addr;
  84. os_snprintf(file_name, 13, "%02X%02X%02X%02X.WFA",
  85. mac_addr[2], mac_addr[3], mac_addr[4],
  86. mac_addr[5]);
  87. }
  88. break;
  89. case OOB_METHOD_DEV_PWD_R:
  90. os_snprintf(file_name, 13, "00000000.WFA");
  91. break;
  92. default:
  93. wpa_printf(MSG_ERROR, "WPS: Invalid USBA OOB method");
  94. return -1;
  95. }
  96. return 0;
  97. }
  98. static int ufd_mkdir(const char *path)
  99. {
  100. if (mkdir(path, S_IRWXU) < 0 && errno != EEXIST) {
  101. wpa_printf(MSG_ERROR, "WPS (UFD): Failed to create directory "
  102. "'%s': %d (%s)", path, errno, strerror(errno));
  103. return -1;
  104. }
  105. return 0;
  106. }
  107. static void * init_ufd(struct wps_context *wps,
  108. struct oob_device_data *oob_dev, int registrar)
  109. {
  110. int write_f;
  111. char temp[128];
  112. char *path = oob_dev->device_path;
  113. char filename[13];
  114. struct wps_ufd_data *data;
  115. int ufd_fd;
  116. if (path == NULL)
  117. return NULL;
  118. write_f = wps->oob_conf.oob_method == OOB_METHOD_DEV_PWD_E ?
  119. !registrar : registrar;
  120. if (get_file_name(wps, registrar, path, filename) < 0) {
  121. wpa_printf(MSG_ERROR, "WPS (UFD): Failed to get file name");
  122. return NULL;
  123. }
  124. if (write_f) {
  125. os_snprintf(temp, sizeof(temp), UFD_DIR1, path);
  126. if (ufd_mkdir(temp))
  127. return NULL;
  128. os_snprintf(temp, sizeof(temp), UFD_DIR2, path);
  129. if (ufd_mkdir(temp))
  130. return NULL;
  131. }
  132. os_snprintf(temp, sizeof(temp), UFD_FILE, path, filename);
  133. if (write_f)
  134. ufd_fd = open(temp, O_WRONLY | O_CREAT | O_TRUNC,
  135. S_IRUSR | S_IWUSR);
  136. else
  137. ufd_fd = open(temp, O_RDONLY);
  138. if (ufd_fd < 0) {
  139. wpa_printf(MSG_ERROR, "WPS (UFD): Failed to open %s: %s",
  140. temp, strerror(errno));
  141. return NULL;
  142. }
  143. data = os_zalloc(sizeof(*data));
  144. if (data == NULL)
  145. return NULL;
  146. data->ufd_fd = ufd_fd;
  147. return data;
  148. }
  149. static struct wpabuf * read_ufd(void *priv)
  150. {
  151. struct wps_ufd_data *data = priv;
  152. struct wpabuf *buf;
  153. struct stat s;
  154. size_t file_size;
  155. if (fstat(data->ufd_fd, &s) < 0) {
  156. wpa_printf(MSG_ERROR, "WPS (UFD): Failed to get file size");
  157. return NULL;
  158. }
  159. file_size = s.st_size;
  160. buf = wpabuf_alloc(file_size);
  161. if (buf == NULL) {
  162. wpa_printf(MSG_ERROR, "WPS (UFD): Failed to alloc read "
  163. "buffer");
  164. return NULL;
  165. }
  166. if (read(data->ufd_fd, wpabuf_mhead(buf), file_size) !=
  167. (int) file_size) {
  168. wpabuf_free(buf);
  169. wpa_printf(MSG_ERROR, "WPS (UFD): Failed to read");
  170. return NULL;
  171. }
  172. wpabuf_put(buf, file_size);
  173. return buf;
  174. }
  175. static int write_ufd(void *priv, struct wpabuf *buf)
  176. {
  177. struct wps_ufd_data *data = priv;
  178. if (write(data->ufd_fd, wpabuf_mhead(buf), wpabuf_len(buf)) !=
  179. (int) wpabuf_len(buf)) {
  180. wpa_printf(MSG_ERROR, "WPS (UFD): Failed to write");
  181. return -1;
  182. }
  183. return 0;
  184. }
  185. static void deinit_ufd(void *priv)
  186. {
  187. struct wps_ufd_data *data = priv;
  188. close(data->ufd_fd);
  189. os_free(data);
  190. }
  191. struct oob_device_data oob_ufd_device_data = {
  192. .device_name = NULL,
  193. .device_path = NULL,
  194. .init_func = init_ufd,
  195. .read_func = read_ufd,
  196. .write_func = write_ufd,
  197. .deinit_func = deinit_ufd,
  198. };