00001
00016 #include "includes.h"
00017 #include "common.h"
00018 #include <sys/types.h>
00019 #include <sys/stat.h>
00020 #include <sys/wait.h>
00021 #include <fcntl.h>
00022 #include <dirent.h>
00023
00024 #include "wps/wps.h"
00025
00026 #ifdef CONFIG_NATIVE_WINDOWS
00027 #define UFD_DIR1 "%s\\SMRTNTKY"
00028 #define UFD_DIR2 UFD_DIR1 "\\WFAWSC"
00029 #define UFD_FILE UFD_DIR2 "\\%s"
00030 #else
00031 #define UFD_DIR1 "%s/SMRTNTKY"
00032 #define UFD_DIR2 UFD_DIR1 "/WFAWSC"
00033 #define UFD_FILE UFD_DIR2 "/%s"
00034 #endif
00035
00036
00037 struct wps_ufd_data {
00038 int ufd_fd;
00039 };
00040
00041
00042 static int dev_pwd_e_file_filter(const struct dirent *entry)
00043 {
00044 unsigned int prefix;
00045 char ext[5];
00046
00047 if (sscanf(entry->d_name, "%8x.%4s", &prefix, ext) != 2)
00048 return 0;
00049 if (prefix == 0)
00050 return 0;
00051 if (os_strcasecmp(ext, "WFA") != 0)
00052 return 0;
00053
00054 return 1;
00055 }
00056
00057
00058 static int wps_get_dev_pwd_e_file_name(char *path, char *file_name)
00059 {
00060 struct dirent **namelist;
00061 int i, file_num;
00062
00063 file_num = scandir(path, &namelist, &dev_pwd_e_file_filter,
00064 alphasort);
00065 if (file_num < 0) {
00066 wpa_printf(MSG_ERROR, "WPS: OOB file not found: %d (%s)",
00067 errno, strerror(errno));
00068 return -1;
00069 }
00070 if (file_num == 0) {
00071 wpa_printf(MSG_ERROR, "WPS: OOB file not found");
00072 os_free(namelist);
00073 return -1;
00074 }
00075 os_strlcpy(file_name, namelist[0]->d_name, 13);
00076 for (i = 0; i < file_num; i++)
00077 os_free(namelist[i]);
00078 os_free(namelist);
00079 return 0;
00080 }
00081
00082
00083 static int get_file_name(struct wps_context *wps, int registrar,
00084 const char *path, char *file_name)
00085 {
00086 switch (wps->oob_conf.oob_method) {
00087 case OOB_METHOD_CRED:
00088 os_snprintf(file_name, 13, "00000000.WSC");
00089 break;
00090 case OOB_METHOD_DEV_PWD_E:
00091 if (registrar) {
00092 char temp[128];
00093 os_snprintf(temp, sizeof(temp), UFD_DIR2, path);
00094 if (wps_get_dev_pwd_e_file_name(temp, file_name) < 0)
00095 return -1;
00096 } else {
00097 u8 *mac_addr = wps->dev.mac_addr;
00098
00099 os_snprintf(file_name, 13, "%02X%02X%02X%02X.WFA",
00100 mac_addr[2], mac_addr[3], mac_addr[4],
00101 mac_addr[5]);
00102 }
00103 break;
00104 case OOB_METHOD_DEV_PWD_R:
00105 os_snprintf(file_name, 13, "00000000.WFA");
00106 break;
00107 default:
00108 wpa_printf(MSG_ERROR, "WPS: Invalid USBA OOB method");
00109 return -1;
00110 }
00111 return 0;
00112 }
00113
00114
00115 static int ufd_mkdir(const char *path)
00116 {
00117 if (mkdir(path, S_IRWXU) < 0 && errno != EEXIST) {
00118 wpa_printf(MSG_ERROR, "WPS (UFD): Failed to create directory "
00119 "'%s': %d (%s)", path, errno, strerror(errno));
00120 return -1;
00121 }
00122 return 0;
00123 }
00124
00125
00126 static void * init_ufd(struct wps_context *wps,
00127 struct oob_device_data *oob_dev, int registrar)
00128 {
00129 int write_f;
00130 char temp[128];
00131 char *path = oob_dev->device_path;
00132 char filename[13];
00133 struct wps_ufd_data *data;
00134 int ufd_fd;
00135
00136 if (path == NULL)
00137 return NULL;
00138
00139 write_f = wps->oob_conf.oob_method == OOB_METHOD_DEV_PWD_E ?
00140 !registrar : registrar;
00141
00142 if (get_file_name(wps, registrar, path, filename) < 0) {
00143 wpa_printf(MSG_ERROR, "WPS (UFD): Failed to get file name");
00144 return NULL;
00145 }
00146
00147 if (write_f) {
00148 os_snprintf(temp, sizeof(temp), UFD_DIR1, path);
00149 if (ufd_mkdir(temp))
00150 return NULL;
00151 os_snprintf(temp, sizeof(temp), UFD_DIR2, path);
00152 if (ufd_mkdir(temp))
00153 return NULL;
00154 }
00155
00156 os_snprintf(temp, sizeof(temp), UFD_FILE, path, filename);
00157 if (write_f)
00158 ufd_fd = open(temp, O_WRONLY | O_CREAT | O_TRUNC,
00159 S_IRUSR | S_IWUSR);
00160 else
00161 ufd_fd = open(temp, O_RDONLY);
00162 if (ufd_fd < 0) {
00163 wpa_printf(MSG_ERROR, "WPS (UFD): Failed to open %s: %s",
00164 temp, strerror(errno));
00165 return NULL;
00166 }
00167
00168 data = os_zalloc(sizeof(*data));
00169 if (data == NULL)
00170 return NULL;
00171 data->ufd_fd = ufd_fd;
00172 return data;
00173 }
00174
00175
00176 static struct wpabuf * read_ufd(void *priv)
00177 {
00178 struct wps_ufd_data *data = priv;
00179 struct wpabuf *buf;
00180 struct stat s;
00181 size_t file_size;
00182
00183 if (fstat(data->ufd_fd, &s) < 0) {
00184 wpa_printf(MSG_ERROR, "WPS (UFD): Failed to get file size");
00185 return NULL;
00186 }
00187
00188 file_size = s.st_size;
00189 buf = wpabuf_alloc(file_size);
00190 if (buf == NULL) {
00191 wpa_printf(MSG_ERROR, "WPS (UFD): Failed to alloc read "
00192 "buffer");
00193 return NULL;
00194 }
00195
00196 if (read(data->ufd_fd, wpabuf_mhead(buf), file_size) !=
00197 (int) file_size) {
00198 wpabuf_free(buf);
00199 wpa_printf(MSG_ERROR, "WPS (UFD): Failed to read");
00200 return NULL;
00201 }
00202 wpabuf_put(buf, file_size);
00203 return buf;
00204 }
00205
00206
00207 static int write_ufd(void *priv, struct wpabuf *buf)
00208 {
00209 struct wps_ufd_data *data = priv;
00210
00211 if (write(data->ufd_fd, wpabuf_mhead(buf), wpabuf_len(buf)) !=
00212 (int) wpabuf_len(buf)) {
00213 wpa_printf(MSG_ERROR, "WPS (UFD): Failed to write");
00214 return -1;
00215 }
00216 return 0;
00217 }
00218
00219
00220 static void deinit_ufd(void *priv)
00221 {
00222 struct wps_ufd_data *data = priv;
00223 close(data->ufd_fd);
00224 os_free(data);
00225 }
00226
00227
00228 struct oob_device_data oob_ufd_device_data = {
00229 .device_name = NULL,
00230 .device_path = NULL,
00231 .init_func = init_ufd,
00232 .read_func = read_ufd,
00233 .write_func = write_ufd,
00234 .deinit_func = deinit_ufd,
00235 };
00236