00001
00023 #include <stdio.h>
00024 #include <stdlib.h>
00025 #include <stdint.h>
00026 #include <string.h>
00027 #include <sys/ioctl.h>
00028 #include <glib.h>
00029 #include <glib-object.h>
00030 #include <unistd.h>
00031 #include "common.h"
00032 #include "wpa.h"
00033 #include "wps.h"
00034 #include "log.h"
00035
00036 #define WPS_VERSION 0x10
00037 #define MAX_DEVICE_NAME 32
00038
00039 #define WPS_STATE_UNCONFIGURED 0x01
00040 #define WPS_STATE_CONFIGURED 0x02
00041
00042 #define WPS_PIN_CODE 0
00043 #define WPS_PUSH_BUTTON 4
00044
00045
00046 #define WPS_VERSION_TLV 0x104A
00047 #define WPS_STATE_TLV 0x1044
00048 #define WPS_APSETUPLOCKED_TLV 0x1057
00049 #define WPS_SELECTEDREGISTRAR_TLV 0x1041
00050 #define WPS_DEVICEPASSWORD_ID_TLV 0x1012
00051 #define WPS_SELECTEDREGISTRARCONFIGMETHODS_TLV 0x1053
00052 #define WPS_DEVICENAME_TLV 0x1011
00053 #define WPS_UUID_E_TLV 0x1047
00054
00064 static int get_tlv_value(guchar* msg, guint msg_size, guint type,
00065 guchar* value, guint value_len)
00066 {
00067 guint len = 0;
00068
00069 if (msg_size < 4) {
00070 DLOG_ERR("Message too short");
00071 return -1;
00072 }
00073
00074
00075 while (len + 4 < msg_size)
00076 {
00077 guint hi = msg[len];
00078 guint lo = msg[len+1];
00079 guint tmp_type = (hi << 8) + lo;
00080
00081
00082
00083 guint length = 0;
00084
00085 hi = msg[len+2];
00086 lo = msg[len+3];
00087
00088 length = (hi << 8) + lo;
00089
00090
00091 if (tmp_type == type)
00092 {
00093 if (length > value_len) {
00094 DLOG_ERR("Too much data for buffer (%d)",
00095 value_len);
00096 return -1;
00097 }
00098 if (len + 4 + length > msg_size) {
00099 DLOG_ERR("Message data too short?");
00100 return -1;
00101 }
00102
00103 memcpy(value, msg+len+4, length);
00104
00105
00106 return length;
00107 }
00108
00109 len = len + length + 4;
00110 }
00111
00112 return -1;
00113 }
00121 int handle_wps_ie(unsigned char* p,
00122 struct scan_results_t *scan_results,
00123 unsigned int length)
00124 {
00125 guint value = 0;
00126 char device_name[MAX_DEVICE_NAME+1];
00127 #ifdef DEBUG_WPS
00128 char uuid_e[MAX_UUID_E_LEN];
00129 #endif
00130 gint len;
00131
00132 int ret = -1;
00133
00134 if (length < 2) {
00135 DLOG_ERR("WPS IE too short");
00136 return -1;
00137 }
00138 #if 0
00139 unsigned int i;
00140 for (i=0;i<length;i++) {
00141 DLOG_DEBUG("%02x", p[i]);
00142 }
00143 #endif
00144
00145
00146 if (get_tlv_value(p, length, WPS_VERSION_TLV, (unsigned char*)&value,
00147 sizeof(value)) < 0 || value != WPS_VERSION) {
00148 DLOG_ERR("Unknown WPS version received (%02x)", value);
00149 return ret;
00150 }
00151
00152 if (get_tlv_value(p, length, WPS_STATE_TLV, (unsigned char*)&value,
00153 sizeof(value)) < 0) {
00154 DLOG_ERR("Could not get WPS state");
00155 return ret;
00156 }
00157
00158 DLOG_DEBUG("WPS state: %s", value == WPS_STATE_CONFIGURED?"configured":
00159 "unconfigured");
00160
00161 scan_results->cap_bits |= WLANCOND_WPS;
00162
00163 ret = 0;
00164
00165
00166 if (get_tlv_value(p, length, WPS_APSETUPLOCKED_TLV,
00167 (unsigned char*)&value, sizeof(value)) < 0) {
00168
00169 } else {
00170 DLOG_DEBUG("ap_setup_locked: %d", value);
00171 }
00172
00173 if (get_tlv_value(p, length, WPS_SELECTEDREGISTRAR_TLV,
00174 (unsigned char*)&value, sizeof(value)) < 0) {
00175
00176 } else if (value) {
00177 DLOG_DEBUG("Device is selected registrar");
00178 scan_results->cap_bits |= WLANCOND_WPS_CONFIGURED;
00179 }
00180
00181 if (get_tlv_value(p, length, WPS_DEVICEPASSWORD_ID_TLV,
00182 (unsigned char*)&value, sizeof(value)) < 0) {
00183
00184
00185 scan_results->cap_bits |= WLANCOND_WPS_PIN;
00186 scan_results->cap_bits |= WLANCOND_WPS_PUSH_BUTTON;
00187 } else {
00188 if (GUINT16_FROM_BE(value) == WPS_PIN_CODE) {
00189 DLOG_ERR("PIN supported");
00190 scan_results->cap_bits |= WLANCOND_WPS_PIN;
00191 }
00192 if (GUINT16_FROM_BE(value) == WPS_PUSH_BUTTON) {
00193 DLOG_ERR("PBC supported");
00194 scan_results->cap_bits |= WLANCOND_WPS_PUSH_BUTTON;
00195 }
00196 }
00197
00198 if ((len = get_tlv_value(p, length, WPS_DEVICENAME_TLV,
00199 (unsigned char*)&device_name,
00200 sizeof(device_name)-1)) < 0) {
00201
00202 } else {
00203 device_name[len] = '\0';
00204 DLOG_DEBUG("Device name: %s", device_name);
00205 }
00206
00207 #ifdef DEBUG_WPS
00208
00209 if (get_tlv_value(p, length, WPS_SELECTEDREGISTRARCONFIGMETHODS_TLV,
00210 (unsigned char*)&value, sizeof(value)) < 0) {
00211 DLOG_ERR("Could not get config_methods");
00212 } else {
00213 DLOG_DEBUG("Config_methods: %04x", GUINT16_FROM_BE(value));
00214 }
00215
00216 if ((len = get_tlv_value(p, length, WPS_UUID_E_TLV,
00217 (unsigned char*)&uuid_e,
00218 sizeof(uuid_e))) < 0) {
00219 DLOG_ERR("Could not get UUID-E");
00220 } else {
00221 #if 0
00222 int j;
00223 for (j=0;j<len;j++) {
00224 DLOG_DEBUG("UUID-E: %d", uuid_e[j]);
00225 }
00226 #endif
00227 }
00228 #endif
00229
00230 return ret;
00231 }