$search
00001 /* 00002 * UFD routines for Wi-Fi Protected Setup 00003 * Copyright (c) 2009, Masashi Honma <honma@ictec.co.jp> 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU General Public License version 2 as 00007 * published by the Free Software Foundation. 00008 * 00009 * Alternatively, this software may be distributed under the terms of BSD 00010 * license. 00011 * 00012 * See README and COPYING for more details. 00013 */ 00014 00015 #include "includes.h" 00016 #include "common.h" 00017 #include <sys/types.h> 00018 #include <sys/stat.h> 00019 #include <sys/wait.h> 00020 #include <fcntl.h> 00021 #include <dirent.h> 00022 00023 #include "wps/wps.h" 00024 #include "wps/wps_i.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 /* CONFIG_NATIVE_WINDOWS */ 00031 #define UFD_DIR1 "%s/SMRTNTKY" 00032 #define UFD_DIR2 UFD_DIR1 "/WFAWSC" 00033 #define UFD_FILE UFD_DIR2 "/%s" 00034 #endif /* CONFIG_NATIVE_WINDOWS */ 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 };