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)", value_len);
00095 return -1;
00096 }
00097 if (len + 4 + length > msg_size) {
00098 DLOG_ERR("Message data too short?");
00099 return -1;
00100 }
00101
00102 memcpy(value, msg+len+4, length);
00103
00104
00105 return length;
00106 }
00107
00108 len = len + length + 4;
00109 }
00110
00111 return -1;
00112 }
00120 int handle_wps_ie(unsigned char* p,
00121 struct scan_results_t *scan_results,
00122 unsigned int length)
00123 {
00124 guint value = 0;
00125 char device_name[MAX_DEVICE_NAME+1];
00126 #ifdef DEBUG_WPS
00127 char uuid_e[MAX_UUID_E_LEN];
00128 #endif
00129 gint len;
00130
00131 int ret = -1;
00132
00133 if (length < 2) {
00134 DLOG_ERR("WPS IE too short");
00135 return -1;
00136 }
00137 #if 0
00138 unsigned int i;
00139 for (i=0;i<length;i++) {
00140 DLOG_DEBUG("%02x", p[i]);
00141 }
00142 #endif
00143
00144
00145 if (get_tlv_value(p, length, WPS_VERSION_TLV, (unsigned char*)&value,
00146 sizeof(value)) < 0 || value != WPS_VERSION) {
00147 DLOG_ERR("Unknown WPS version received (%02x)", value);
00148 return ret;
00149 }
00150
00151 if (get_tlv_value(p, length, WPS_STATE_TLV, (unsigned char*)&value,
00152 sizeof(value)) < 0) {
00153 DLOG_ERR("Could not get WPS state");
00154 return ret;
00155 }
00156
00157 DLOG_DEBUG("WPS state: %s", value == WPS_STATE_CONFIGURED?"configured":
00158 "unconfigured");
00159
00160 scan_results->cap_bits |= WLANCOND_WPS;
00161
00162 ret = 0;
00163
00164
00165 if (get_tlv_value(p, length, WPS_APSETUPLOCKED_TLV,
00166 (unsigned char*)&value, sizeof(value)) < 0) {
00167
00168 } else {
00169 DLOG_DEBUG("ap_setup_locked: %d", value);
00170 }
00171
00172 if (get_tlv_value(p, length, WPS_SELECTEDREGISTRAR_TLV,
00173 (unsigned char*)&value, sizeof(value)) < 0) {
00174
00175 } else if (value) {
00176 DLOG_DEBUG("Device is selected registrar");
00177 scan_results->cap_bits |= WLANCOND_WPS_CONFIGURED;
00178 }
00179
00180 if (get_tlv_value(p, length, WPS_DEVICEPASSWORD_ID_TLV,
00181 (unsigned char*)&value, sizeof(value)) < 0) {
00182
00183
00184 scan_results->cap_bits |= WLANCOND_WPS_PIN;
00185 scan_results->cap_bits |= WLANCOND_WPS_PUSH_BUTTON;
00186 } else {
00187 if (GUINT16_FROM_BE(value) == WPS_PIN_CODE) {
00188 DLOG_ERR("PIN supported");
00189 scan_results->cap_bits |= WLANCOND_WPS_PIN;
00190 }
00191 if (GUINT16_FROM_BE(value) == WPS_PUSH_BUTTON) {
00192 DLOG_ERR("PBC supported");
00193 scan_results->cap_bits |= WLANCOND_WPS_PUSH_BUTTON;
00194 }
00195 }
00196
00197 if ((len = get_tlv_value(p, length, WPS_DEVICENAME_TLV,
00198 (unsigned char*)&device_name,
00199 sizeof(device_name)-1)) < 0) {
00200
00201 } else {
00202 device_name[len] = '\0';
00203 DLOG_DEBUG("Device name: %s", device_name);
00204 }
00205
00206 #ifdef DEBUG_WPS
00207
00208 if (get_tlv_value(p, length, WPS_SELECTEDREGISTRARCONFIGMETHODS_TLV,
00209 (unsigned char*)&value, sizeof(value)) < 0) {
00210 DLOG_ERR("Could not get config_methods");
00211 } else {
00212 DLOG_DEBUG("Config_methods: %04x", GUINT16_FROM_BE(value));
00213 }
00214
00215 if ((len = get_tlv_value(p, length, WPS_UUID_E_TLV,
00216 (unsigned char*)&uuid_e,
00217 sizeof(uuid_e))) < 0) {
00218 DLOG_ERR("Could not get UUID-E");
00219 } else {
00220 #if 0
00221 int j;
00222 for (j=0;j<len;j++) {
00223 DLOG_DEBUG("UUID-E: %d", uuid_e[j]);
00224 }
00225 #endif
00226 }
00227 #endif
00228
00229 return ret;
00230 }