remove @EAP_LDFLAGS@, no longer exists
[mech_eap.orig] / libeap / src / wps / wps_ufd.c
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
15 #include "includes.h"
16 #include "common.h"
17 #include <sys/types.h>
18 #include <sys/stat.h>
19 #include <sys/wait.h>
20 #include <fcntl.h>
21 #include <dirent.h>
22
23 #include "wps/wps.h"
24 #include "wps/wps_i.h"
25
26 #ifdef CONFIG_NATIVE_WINDOWS
27 #define UFD_DIR1 "%s\\SMRTNTKY"
28 #define UFD_DIR2 UFD_DIR1 "\\WFAWSC"
29 #define UFD_FILE UFD_DIR2 "\\%s"
30 #else /* CONFIG_NATIVE_WINDOWS */
31 #define UFD_DIR1 "%s/SMRTNTKY"
32 #define UFD_DIR2 UFD_DIR1 "/WFAWSC"
33 #define UFD_FILE UFD_DIR2 "/%s"
34 #endif /* CONFIG_NATIVE_WINDOWS */
35
36
37 struct wps_ufd_data {
38         int ufd_fd;
39 };
40
41
42 static int dev_pwd_e_file_filter(const struct dirent *entry)
43 {
44         unsigned int prefix;
45         char ext[5];
46
47         if (sscanf(entry->d_name, "%8x.%4s", &prefix, ext) != 2)
48                 return 0;
49         if (prefix == 0)
50                 return 0;
51         if (os_strcasecmp(ext, "WFA") != 0)
52                 return 0;
53
54         return 1;
55 }
56
57
58 static int wps_get_dev_pwd_e_file_name(char *path, char *file_name)
59 {
60         struct dirent **namelist;
61         int i, file_num;
62
63         file_num = scandir(path, &namelist, &dev_pwd_e_file_filter,
64                            alphasort);
65         if (file_num < 0) {
66                 wpa_printf(MSG_ERROR, "WPS: OOB file not found: %d (%s)",
67                            errno, strerror(errno));
68                 return -1;
69         }
70         if (file_num == 0) {
71                 wpa_printf(MSG_ERROR, "WPS: OOB file not found");
72                 os_free(namelist);
73                 return -1;
74         }
75         os_strlcpy(file_name, namelist[0]->d_name, 13);
76         for (i = 0; i < file_num; i++)
77                 os_free(namelist[i]);
78         os_free(namelist);
79         return 0;
80 }
81
82
83 static int get_file_name(struct wps_context *wps, int registrar,
84                          const char *path, char *file_name)
85 {
86         switch (wps->oob_conf.oob_method) {
87         case OOB_METHOD_CRED:
88                 os_snprintf(file_name, 13, "00000000.WSC");
89                 break;
90         case OOB_METHOD_DEV_PWD_E:
91                 if (registrar) {
92                         char temp[128];
93                         os_snprintf(temp, sizeof(temp), UFD_DIR2, path);
94                         if (wps_get_dev_pwd_e_file_name(temp, file_name) < 0)
95                                 return -1;
96                 } else {
97                         u8 *mac_addr = wps->dev.mac_addr;
98
99                         os_snprintf(file_name, 13, "%02X%02X%02X%02X.WFA",
100                                     mac_addr[2], mac_addr[3], mac_addr[4],
101                                     mac_addr[5]);
102                 }
103                 break;
104         case OOB_METHOD_DEV_PWD_R:
105                 os_snprintf(file_name, 13, "00000000.WFA");
106                 break;
107         default:
108                 wpa_printf(MSG_ERROR, "WPS: Invalid USBA OOB method");
109                 return -1;
110         }
111         return 0;
112 }
113
114
115 static int ufd_mkdir(const char *path)
116 {
117         if (mkdir(path, S_IRWXU) < 0 && errno != EEXIST) {
118                 wpa_printf(MSG_ERROR, "WPS (UFD): Failed to create directory "
119                            "'%s': %d (%s)", path, errno, strerror(errno));
120                 return -1;
121         }
122         return 0;
123 }
124
125
126 static void * init_ufd(struct wps_context *wps,
127                        struct oob_device_data *oob_dev, int registrar)
128 {
129         int write_f;
130         char temp[128];
131         char *path = oob_dev->device_path;
132         char filename[13];
133         struct wps_ufd_data *data;
134         int ufd_fd;
135
136         if (path == NULL)
137                 return NULL;
138
139         write_f = wps->oob_conf.oob_method == OOB_METHOD_DEV_PWD_E ?
140                 !registrar : registrar;
141
142         if (get_file_name(wps, registrar, path, filename) < 0) {
143                 wpa_printf(MSG_ERROR, "WPS (UFD): Failed to get file name");
144                 return NULL;
145         }
146
147         if (write_f) {
148                 os_snprintf(temp, sizeof(temp), UFD_DIR1, path);
149                 if (ufd_mkdir(temp))
150                         return NULL;
151                 os_snprintf(temp, sizeof(temp), UFD_DIR2, path);
152                 if (ufd_mkdir(temp))
153                         return NULL;
154         }
155
156         os_snprintf(temp, sizeof(temp), UFD_FILE, path, filename);
157         if (write_f)
158                 ufd_fd = open(temp, O_WRONLY | O_CREAT | O_TRUNC,
159                               S_IRUSR | S_IWUSR);
160         else
161                 ufd_fd = open(temp, O_RDONLY);
162         if (ufd_fd < 0) {
163                 wpa_printf(MSG_ERROR, "WPS (UFD): Failed to open %s: %s",
164                            temp, strerror(errno));
165                 return NULL;
166         }
167
168         data = os_zalloc(sizeof(*data));
169         if (data == NULL)
170                 return NULL;
171         data->ufd_fd = ufd_fd;
172         return data;
173 }
174
175
176 static struct wpabuf * read_ufd(void *priv)
177 {
178         struct wps_ufd_data *data = priv;
179         struct wpabuf *buf;
180         struct stat s;
181         size_t file_size;
182
183         if (fstat(data->ufd_fd, &s) < 0) {
184                 wpa_printf(MSG_ERROR, "WPS (UFD): Failed to get file size");
185                 return NULL;
186         }
187
188         file_size = s.st_size;
189         buf = wpabuf_alloc(file_size);
190         if (buf == NULL) {
191                 wpa_printf(MSG_ERROR, "WPS (UFD): Failed to alloc read "
192                            "buffer");
193                 return NULL;
194         }
195
196         if (read(data->ufd_fd, wpabuf_mhead(buf), file_size) !=
197             (int) file_size) {
198                 wpabuf_free(buf);
199                 wpa_printf(MSG_ERROR, "WPS (UFD): Failed to read");
200                 return NULL;
201         }
202         wpabuf_put(buf, file_size);
203         return buf;
204 }
205
206
207 static int write_ufd(void *priv, struct wpabuf *buf)
208 {
209         struct wps_ufd_data *data = priv;
210
211         if (write(data->ufd_fd, wpabuf_mhead(buf), wpabuf_len(buf)) !=
212             (int) wpabuf_len(buf)) {
213                 wpa_printf(MSG_ERROR, "WPS (UFD): Failed to write");
214                 return -1;
215         }
216         return 0;
217 }
218
219
220 static void deinit_ufd(void *priv)
221 {
222         struct wps_ufd_data *data = priv;
223         close(data->ufd_fd);
224         os_free(data);
225 }
226
227
228 struct oob_device_data oob_ufd_device_data = {
229         .device_name    = NULL,
230         .device_path    = NULL,
231         .init_func      = init_ufd,
232         .read_func      = read_ufd,
233         .write_func     = write_ufd,
234         .deinit_func    = deinit_ufd,
235 };