WPS NFC: Add connection handover support for ER

wpa_supplicant can now generate the WPS carrier record for connection
handover response when acting as an ER. The AP whose configuration is
provided in this way is identified with an UUID as an argument to
wps-nfc.py.

Signed-hostap: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
Jouni Malinen 2013-02-24 10:56:29 +02:00 committed by Jouni Malinen
parent c39fdb8529
commit f3f2ba2e6e
4 changed files with 129 additions and 12 deletions

View file

@ -910,12 +910,12 @@ static int wpas_ctrl_nfc_get_handover_req(struct wpa_supplicant *wpa_s,
static int wpas_ctrl_nfc_get_handover_sel_wps(struct wpa_supplicant *wpa_s, static int wpas_ctrl_nfc_get_handover_sel_wps(struct wpa_supplicant *wpa_s,
char *reply, size_t max_len, char *reply, size_t max_len,
int ndef, int cr) int ndef, int cr, char *uuid)
{ {
struct wpabuf *buf; struct wpabuf *buf;
int res; int res;
buf = wpas_wps_nfc_handover_sel(wpa_s, ndef, cr); buf = wpas_wps_nfc_handover_sel(wpa_s, ndef, cr, uuid);
if (buf == NULL) if (buf == NULL)
return -1; return -1;
@ -934,7 +934,7 @@ static int wpas_ctrl_nfc_get_handover_sel(struct wpa_supplicant *wpa_s,
char *cmd, char *reply, char *cmd, char *reply,
size_t max_len) size_t max_len)
{ {
char *pos; char *pos, *pos2;
int ndef; int ndef;
pos = os_strchr(cmd, ' '); pos = os_strchr(cmd, ' ');
@ -949,10 +949,13 @@ static int wpas_ctrl_nfc_get_handover_sel(struct wpa_supplicant *wpa_s,
else else
return -1; return -1;
pos2 = os_strchr(pos, ' ');
if (pos2)
*pos2++ = '\0';
if (os_strcmp(pos, "WPS") == 0 || os_strcmp(pos, "WPS-CR") == 0) { if (os_strcmp(pos, "WPS") == 0 || os_strcmp(pos, "WPS-CR") == 0) {
return wpas_ctrl_nfc_get_handover_sel_wps( return wpas_ctrl_nfc_get_handover_sel_wps(
wpa_s, reply, max_len, ndef, wpa_s, reply, max_len, ndef,
os_strcmp(pos, "WPS-CR") == 0); os_strcmp(pos, "WPS-CR") == 0, pos2);
} }
return -1; return -1;

View file

@ -82,15 +82,86 @@ def wpas_get_handover_req():
return wpas.request("NFC_GET_HANDOVER_REQ NDEF WPS-CR").rstrip().decode("hex") return wpas.request("NFC_GET_HANDOVER_REQ NDEF WPS-CR").rstrip().decode("hex")
def wpas_report_handover(req, sel): def wpas_get_handover_sel(uuid):
wpas = wpas_connect() wpas = wpas_connect()
if (wpas == None): if (wpas == None):
return None return None
return wpas.request("NFC_REPORT_HANDOVER INIT WPS " + return wpas.request("NFC_GET_HANDOVER_SEL NDEF WPS-CR " + uuid).rstrip().decode("hex")
def wpas_report_handover(req, sel, type):
wpas = wpas_connect()
if (wpas == None):
return None
return wpas.request("NFC_REPORT_HANDOVER " + type + " WPS " +
str(req).encode("hex") + " " + str(req).encode("hex") + " " +
str(sel).encode("hex")) str(sel).encode("hex"))
class HandoverServer(nfc.handover.HandoverServer):
def __init__(self):
super(HandoverServer, self).__init__()
def process_request(self, request):
print "HandoverServer - request received"
print "Parsed handover request: " + request.pretty()
sel = nfc.ndef.HandoverSelectMessage(version="1.2")
for carrier in request.carriers:
print "Remote carrier type: " + carrier.type
if carrier.type == "application/vnd.wfa.wsc":
print "WPS carrier type match - add WPS carrier record"
self.received_carrier = carrier.record
data = wpas_get_handover_sel(self.uuid)
if data is None:
print "Could not get handover select carrier record from wpa_supplicant"
continue
print "Handover select carrier record from wpa_supplicant:"
print data.encode("hex")
self.sent_carrier = data
message = nfc.ndef.Message(data);
sel.add_carrier(message[0], "active", message[1:])
print "Handover select:"
print sel.pretty()
print str(sel).encode("hex")
print "Sending handover select"
return sel
def wps_handover_resp(peer, uuid):
print "Trying to handle WPS handover with AP " + uuid
srv = HandoverServer()
srv.sent_carrier = None
srv.uuid = uuid
nfc.llcp.activate(peer);
try:
print "Trying handover";
srv.start()
print "Wait for disconnect"
while nfc.llcp.connected():
time.sleep(0.1)
print "Disconnected after handover"
except nfc.llcp.ConnectRefused:
print "Handover connection refused"
nfc.llcp.shutdown()
return
if srv.sent_carrier:
wpas_report_handover(srv.received_carrier, srv.sent_carrier, "RESP")
print "Remove peer"
nfc.llcp.shutdown()
print "Done with handover"
time.sleep(1)
def wps_handover_init(peer): def wps_handover_init(peer):
print "Trying to initiate WPS handover" print "Trying to initiate WPS handover"
@ -154,7 +225,7 @@ def wps_handover_init(peer):
print "Remote carrier type: " + carrier.type print "Remote carrier type: " + carrier.type
if carrier.type == "application/vnd.wfa.wsc": if carrier.type == "application/vnd.wfa.wsc":
print "WPS carrier type match - send to wpa_supplicant" print "WPS carrier type match - send to wpa_supplicant"
wpas_report_handover(data, carrier.record) wpas_report_handover(data, carrier.record, "INIT")
wifi = nfc.ndef.WifiConfigRecord(carrier.record) wifi = nfc.ndef.WifiConfigRecord(carrier.record)
print wifi.pretty() print wifi.pretty()
@ -281,6 +352,10 @@ def main():
clf = nfc.ContactlessFrontend() clf = nfc.ContactlessFrontend()
try: try:
arg_uuid = None
if len(sys.argv) > 1:
arg_uuid = sys.argv[1]
if len(sys.argv) > 1 and sys.argv[1] == "write-config": if len(sys.argv) > 1 and sys.argv[1] == "write-config":
wps_write_config_tag(clf) wps_write_config_tag(clf)
raise SystemExit raise SystemExit
@ -298,7 +373,10 @@ def main():
tag = find_peer(clf) tag = find_peer(clf)
if isinstance(tag, nfc.DEP): if isinstance(tag, nfc.DEP):
if arg_uuid is None:
wps_handover_init(tag) wps_handover_init(tag)
else:
wps_handover_resp(tag, arg_uuid)
continue continue
if tag.ndef: if tag.ndef:

View file

@ -2003,12 +2003,48 @@ struct wpabuf * wpas_wps_nfc_handover_req(struct wpa_supplicant *wpa_s, int cr)
} }
struct wpabuf * wpas_wps_nfc_handover_sel(struct wpa_supplicant *wpa_s, #ifdef CONFIG_WPS_NFC
int ndef, int cr) struct wpabuf * wpas_wps_er_nfc_handover_sel(struct wpa_supplicant *wpa_s,
int ndef, const char *uuid)
{ {
struct wpabuf *ret;
u8 u[UUID_LEN];
if (!wpa_s->wps_er)
return NULL;
if (uuid == NULL || uuid_str2bin(uuid, u))
return NULL;
/*
* Handover Select carrier record for WPS uses the same format as
* configuration token.
*/
ret = wps_er_nfc_config_token(wpa_s->wps_er, u);
if (ndef && ret) {
struct wpabuf *tmp;
tmp = ndef_build_wifi(ret);
wpabuf_free(ret);
if (tmp == NULL)
return NULL;
ret = tmp;
}
return ret;
}
#endif /* CONFIG_WPS_NFC */
struct wpabuf * wpas_wps_nfc_handover_sel(struct wpa_supplicant *wpa_s,
int ndef, int cr, const char *uuid)
{
struct wpabuf *ret;
if (!cr) if (!cr)
return NULL; return NULL;
return wpas_ap_wps_nfc_handover_sel(wpa_s, ndef); ret = wpas_ap_wps_nfc_handover_sel(wpa_s, ndef);
if (ret)
return ret;
return wpas_wps_er_nfc_handover_sel(wpa_s, ndef, uuid);
} }

View file

@ -70,7 +70,7 @@ int wpas_wps_nfc_tag_read(struct wpa_supplicant *wpa_s,
const struct wpabuf *data); const struct wpabuf *data);
struct wpabuf * wpas_wps_nfc_handover_req(struct wpa_supplicant *wpa_s, int cr); struct wpabuf * wpas_wps_nfc_handover_req(struct wpa_supplicant *wpa_s, int cr);
struct wpabuf * wpas_wps_nfc_handover_sel(struct wpa_supplicant *wpa_s, struct wpabuf * wpas_wps_nfc_handover_sel(struct wpa_supplicant *wpa_s,
int ndef, int cr); int ndef, int cr, const char *uuid);
int wpas_wps_nfc_rx_handover_req(struct wpa_supplicant *wpa_s, int wpas_wps_nfc_rx_handover_req(struct wpa_supplicant *wpa_s,
const struct wpabuf *data); const struct wpabuf *data);
int wpas_wps_nfc_rx_handover_sel(struct wpa_supplicant *wpa_s, int wpas_wps_nfc_rx_handover_sel(struct wpa_supplicant *wpa_s,