static enum http_reply_code web_process_set_selected_registrar(struct upnp_wps_device_sm *sm, struct sockaddr_in *cli, char *data, struct wpabuf **reply, const char **replyname) { struct wpabuf *msg; enum http_reply_code ret; struct subscription *s; struct upnp_wps_device_interface *iface; int err = 0; wpa_printf(MSG_DEBUG, "WPS UPnP: SetSelectedRegistrar"); s = find_er(sm, cli); if (s == NULL) { wpa_printf(MSG_DEBUG, "WPS UPnP: Ignore SetSelectedRegistrar " "from unknown ER"); return UPNP_ACTION_FAILED; } msg = xml_get_base64_item(data, "NewMessage", &ret); if (msg == NULL) return ret; dl_list_for_each(iface, &sm->interfaces, struct upnp_wps_device_interface, list) { if (upnp_er_set_selected_registrar(iface->wps->registrar, s, msg)) err = 1; } wpabuf_free(msg); if (err) return HTTP_INTERNAL_SERVER_ERROR; *replyname = NULL; *reply = NULL; return HTTP_OK; }
static void wps_er_http_event(struct wps_er *er, struct http_request *req, unsigned int ap_id) { struct wps_er_ap *ap = wps_er_ap_get_id(er, ap_id); struct wpabuf *event; enum http_reply_code ret; if (ap == NULL) { wpa_printf(MSG_DEBUG, "WPS ER: HTTP event from unknown AP id " "%u", ap_id); wps_er_http_resp_not_found(req); return; } wpa_printf(MSG_MSGDUMP, "WPS ER: HTTP event from AP id %u: %s", ap_id, http_request_get_data(req)); event = xml_get_base64_item(http_request_get_data(req), "WLANEvent", &ret); if (event == NULL) { wpa_printf(MSG_DEBUG, "WPS ER: Could not extract WLANEvent " "from the event notification"); /* * Reply with OK anyway to avoid getting unregistered from * events. */ wps_er_http_resp_ok(req); return; } wps_er_process_wlanevent(ap, event); wpabuf_free(event); wps_er_http_resp_ok(req); }
static enum http_reply_code web_process_put_message(struct upnp_wps_device_sm *sm, char *data, struct wpabuf **reply, const char **replyname) { struct wpabuf *msg; static const char *name = "NewOutMessage"; enum http_reply_code ret; enum wps_process_res res; enum wsc_op_code op_code; /* * PutMessage is used by external UPnP-based Registrar to perform WPS * operation with the access point itself; as compared with * PutWLANResponse which is for proxying. */ wpa_printf(MSG_DEBUG, "WPS UPnP: PutMessage"); msg = xml_get_base64_item(data, "NewInMessage", &ret); if (msg == NULL) return ret; res = wps_process_msg(sm->peer.wps, WSC_UPnP, msg); if (res == WPS_FAILURE) *reply = NULL; else *reply = wps_get_msg(sm->peer.wps, &op_code); wpabuf_free(msg); if (*reply == NULL) return HTTP_INTERNAL_SERVER_ERROR; *replyname = name; return HTTP_OK; }
static enum http_reply_code web_process_put_wlan_response(struct upnp_wps_device_sm *sm, char *data, struct wpabuf **reply, const char **replyname) { struct wpabuf *msg; enum http_reply_code ret; u8 macaddr[ETH_ALEN]; int ev_type; int type; char *val; /* * External UPnP-based Registrar is passing us a message to be proxied * over to a Wi-Fi -based client of ours. */ wpa_printf(MSG_DEBUG, "WPS UPnP: PutWLANResponse"); msg = xml_get_base64_item(data, "NewMessage", &ret); if (msg == NULL) return ret; val = xml_get_first_item(data, "NewWLANEventType"); if (val == NULL) { wpabuf_free(msg); return UPNP_ARG_VALUE_INVALID; } ev_type = atol(val); os_free(val); val = xml_get_first_item(data, "NewWLANEventMAC"); if (val == NULL || hwaddr_aton(val, macaddr)) { wpabuf_free(msg); os_free(val); return UPNP_ARG_VALUE_INVALID; } os_free(val); if (ev_type == UPNP_WPS_WLANEVENT_TYPE_EAP) { struct wps_parse_attr attr; if (wps_parse_msg(msg, &attr) < 0 || attr.msg_type == NULL) type = -1; else type = *attr.msg_type; wpa_printf(MSG_DEBUG, "WPS UPnP: Message Type %d", type); } else type = -1; if (!sm->ctx->rx_req_put_wlan_response || sm->ctx->rx_req_put_wlan_response(sm->priv, ev_type, macaddr, msg, type)) { wpa_printf(MSG_INFO, "WPS UPnP: Fail: sm->ctx->" "rx_req_put_wlan_response"); wpabuf_free(msg); return HTTP_INTERNAL_SERVER_ERROR; } wpabuf_free(msg); *replyname = NULL; *reply = NULL; return HTTP_OK; }
static void wps_er_http_put_message_cb(void *ctx, struct http_client *c, enum http_client_event event) { struct wps_er_ap *ap = ctx; struct wpabuf *reply; char *msg = NULL; switch (event) { case HTTP_CLIENT_OK: wpa_printf(MSG_DEBUG, "WPS ER: PutMessage OK"); reply = http_client_get_body(c); if (reply == NULL) break; msg = os_zalloc(wpabuf_len(reply) + 1); if (msg == NULL) break; os_memcpy(msg, wpabuf_head(reply), wpabuf_len(reply)); break; case HTTP_CLIENT_FAILED: case HTTP_CLIENT_INVALID_REPLY: case HTTP_CLIENT_TIMEOUT: wpa_printf(MSG_DEBUG, "WPS ER: PutMessage failed"); if (ap->wps) { wps_deinit(ap->wps); ap->wps = NULL; } break; } http_client_free(ap->http); ap->http = NULL; if (msg) { struct wpabuf *buf; enum http_reply_code ret; buf = xml_get_base64_item(msg, "NewOutMessage", &ret); os_free(msg); if (buf == NULL) { wpa_printf(MSG_DEBUG, "WPS ER: Could not extract " "NewOutMessage from PutMessage response"); wps_deinit(ap->wps); ap->wps = NULL; return; } wps_er_ap_process(ap, buf); wpabuf_free(buf); } }
static void wps_er_ap_learn(struct wps_er_ap *ap, const char *dev_info) { struct wpabuf *info; enum http_reply_code ret; wpa_printf(MSG_DEBUG, "WPS ER: Received GetDeviceInfo response (M1) " "from the AP"); info = xml_get_base64_item(dev_info, "NewDeviceInfo", &ret); if (info == NULL) { wpa_printf(MSG_DEBUG, "WPS ER: Could not extract " "NewDeviceInfo from GetDeviceInfo response"); return; } ap->m1_handler(ap, info); wpabuf_free(info); }
static enum http_reply_code web_process_put_wlan_response(struct upnp_wps_device_sm *sm, char *data, struct wpabuf **reply, const char **replyname) { struct wpabuf *msg; enum http_reply_code ret; u8 macaddr[ETH_ALEN]; int ev_type; int type; char *val; struct upnp_wps_device_interface *iface; int ok = 0; /* * External UPnP-based Registrar is passing us a message to be proxied * over to a Wi-Fi -based client of ours. */ wpa_printf(MSG_DEBUG, "WPS UPnP: PutWLANResponse"); msg = xml_get_base64_item(data, "NewMessage", &ret); if (msg == NULL) { wpa_printf(MSG_DEBUG, "WPS UPnP: Could not extract NewMessage " "from PutWLANResponse"); return ret; } val = xml_get_first_item(data, "NewWLANEventType"); if (val == NULL) { wpa_printf(MSG_DEBUG, "WPS UPnP: No NewWLANEventType in " "PutWLANResponse"); wpabuf_free(msg); return UPNP_ARG_VALUE_INVALID; } ev_type = atol(val); os_free(val); val = xml_get_first_item(data, "NewWLANEventMAC"); if (val == NULL) { wpa_printf(MSG_DEBUG, "WPS UPnP: No NewWLANEventMAC in " "PutWLANResponse"); wpabuf_free(msg); return UPNP_ARG_VALUE_INVALID; } if (hwaddr_aton(val, macaddr)) { wpa_printf(MSG_DEBUG, "WPS UPnP: Invalid NewWLANEventMAC in " "PutWLANResponse: '%s'", val); #ifdef CONFIG_WPS_STRICT { struct wps_parse_attr attr; if (wps_parse_msg(msg, &attr) < 0 || attr.version2) { wpabuf_free(msg); os_free(val); return UPNP_ARG_VALUE_INVALID; } } #endif /* CONFIG_WPS_STRICT */ if (hwaddr_aton2(val, macaddr) > 0) { /* * At least some versions of Intel PROset seem to be * using dot-deliminated MAC address format here. */ wpa_printf(MSG_DEBUG, "WPS UPnP: Workaround - allow " "incorrect MAC address format in " "NewWLANEventMAC: %s -> " MACSTR, val, MAC2STR(macaddr)); } else { wpabuf_free(msg); os_free(val); return UPNP_ARG_VALUE_INVALID; } } os_free(val); if (ev_type == UPNP_WPS_WLANEVENT_TYPE_EAP) { struct wps_parse_attr attr; if (wps_parse_msg(msg, &attr) < 0 || attr.msg_type == NULL) type = -1; else type = *attr.msg_type; wpa_printf(MSG_DEBUG, "WPS UPnP: Message Type %d", type); } else type = -1; dl_list_for_each(iface, &sm->interfaces, struct upnp_wps_device_interface, list) { if (iface->ctx->rx_req_put_wlan_response && iface->ctx->rx_req_put_wlan_response(iface->priv, ev_type, macaddr, msg, type) == 0) ok = 1; } if (!ok) { wpa_printf(MSG_INFO, "WPS UPnP: Fail: sm->ctx->" "rx_req_put_wlan_response"); wpabuf_free(msg); return HTTP_INTERNAL_SERVER_ERROR; } wpabuf_free(msg); *replyname = NULL; *reply = NULL; return HTTP_OK; }
static enum http_reply_code web_process_put_message(struct upnp_wps_device_sm *sm, char *data, struct wpabuf **reply, const char **replyname) { struct wpabuf *msg; static const char *name = "NewOutMessage"; enum http_reply_code ret; enum wps_process_res res; enum wsc_op_code op_code; struct upnp_wps_device_interface *iface; struct wps_parse_attr attr; struct upnp_wps_peer *tmp, *peer; iface = dl_list_first(&sm->interfaces, struct upnp_wps_device_interface, list); if (!iface) return HTTP_INTERNAL_SERVER_ERROR; /* * PutMessage is used by external UPnP-based Registrar to perform WPS * operation with the access point itself; as compared with * PutWLANResponse which is for proxying. */ wpa_printf(MSG_DEBUG, "WPS UPnP: PutMessage"); msg = xml_get_base64_item(data, "NewInMessage", &ret); if (msg == NULL) return ret; if (wps_parse_msg(msg, &attr)) { wpa_printf(MSG_DEBUG, "WPS UPnP: Could not parse PutMessage - NewInMessage"); wpabuf_free(msg); return HTTP_BAD_REQUEST; } /* Find a matching active peer session */ peer = NULL; dl_list_for_each(tmp, &iface->peers, struct upnp_wps_peer, list) { if (!tmp->wps) continue; if (attr.enrollee_nonce && os_memcmp(tmp->wps->nonce_e, attr.enrollee_nonce, WPS_NONCE_LEN) != 0) continue; /* Enrollee nonce mismatch */ if (attr.msg_type && *attr.msg_type != WPS_M2 && *attr.msg_type != WPS_M2D && attr.registrar_nonce && os_memcmp(tmp->wps->nonce_r, attr.registrar_nonce, WPS_NONCE_LEN) != 0) continue; /* Registrar nonce mismatch */ peer = tmp; break; } if (!peer) { /* Try to use the first entry in case message could work with * it. The actual handler function will reject this, if needed. * This maintains older behavior where only a single peer entry * was supported. */ peer = dl_list_first(&iface->peers, struct upnp_wps_peer, list); }