int wps_er_learn(struct wps_er *er, const u8 *uuid, const u8 *pin, size_t pin_len) { struct wps_er_ap *ap; if (er == NULL) return -1; ap = wps_er_ap_get(er, NULL, uuid); if (ap == NULL) { wpa_printf(MSG_DEBUG, "WPS ER: AP not found for learn " "request"); return -1; } if (ap->wps) { wpa_printf(MSG_DEBUG, "WPS ER: Pending operation ongoing " "with the AP - cannot start learn"); return -1; } if (wps_er_send_get_device_info(ap, wps_er_ap_learn_m1) < 0) return -1; er->skip_set_sel_reg = 1; wps_registrar_add_pin(er->wps->registrar, NULL, uuid, pin, pin_len, 0); er->skip_set_sel_reg = 0; return 0; }
int wpas_wps_er_add_pin(struct wpa_supplicant *wpa_s, const char *uuid, const char *pin) { u8 u[UUID_LEN]; int any = 0; if (os_strcmp(uuid, "any") == 0) any = 1; else if (uuid_str2bin(uuid, u)) return -1; return wps_registrar_add_pin(wpa_s->wps->registrar, any ? NULL : u, (const u8 *) pin, os_strlen(pin), 300); }
static int wps_add_pin(struct hostapd_data *hapd, void *ctx) { struct wps_add_pin_data *data = ctx; int ret; if (hapd->wps == NULL) return 0; ret = wps_registrar_add_pin(hapd->wps->registrar, data->addr, data->uuid, data->pin, data->pin_len, data->timeout); if (ret == 0) data->added++; return ret; }
int hostapd_wps_add_pin(struct hostapd_data *hapd, const char *uuid, const char *pin) { u8 u[UUID_LEN]; int any = 0; if (hapd->wps == NULL) return -1; if (os_strcmp(uuid, "any") == 0) any = 1; else if (uuid_str2bin(uuid, u)) return -1; return wps_registrar_add_pin(hapd->wps->registrar, any ? NULL : u, (const u8 *) pin, os_strlen(pin)); }
/* * Remove the last WPS pin (if any), build the next WPS pin in the p1 and p2 arrays, * and populate the wps structure with the new pin. */ char *build_next_pin() { char *pin = NULL; struct wps_data *wps = get_wps(); /* Remove previous pin */ wps_registrar_invalidate_pin(wps->wps->registrar, wps->uuid_e); /* Build a new pin */ pin = build_wps_pin(); if(pin) { /* Add the new pin */ if(wps_registrar_add_pin(wps->wps->registrar, NULL, (const u8 *) pin, PIN_SIZE, 0) != 0) { free(pin); pin = NULL; } } return pin; }
int wps_er_config(struct wps_er *er, const u8 *uuid, const u8 *addr, const u8 *pin, size_t pin_len, const struct wps_credential *cred) { struct wps_er_ap *ap; if (er == NULL) return -1; ap = wps_er_ap_get(er, NULL, uuid, addr); if (ap == NULL) { wpa_printf(MSG_DEBUG, "WPS ER: AP not found for config " "request"); return -1; } if (uuid == NULL) uuid = ap->uuid; if (ap->wps) { wpa_printf(MSG_DEBUG, "WPS ER: Pending operation ongoing " "with the AP - cannot start config"); return -1; } os_free(ap->ap_settings); ap->ap_settings = os_malloc(sizeof(*cred)); if (ap->ap_settings == NULL) return -1; os_memcpy(ap->ap_settings, cred, sizeof(*cred)); ap->ap_settings->cred_attr = NULL; if (wps_er_send_get_device_info(ap, wps_er_ap_config_m1) < 0) return -1; er->skip_set_sel_reg = 1; wps_registrar_add_pin(er->wps->registrar, NULL, uuid, pin, pin_len, 0); er->skip_set_sel_reg = 0; return 0; }
static void * eap_wsc_init(struct eap_sm *sm) { struct eap_wsc_data *data; const u8 *identity; size_t identity_len; int registrar; struct wps_config cfg; const char *pos, *end; const char *phase1; struct wps_context *wps; struct wps_credential new_ap_settings; int res; int nfc = 0; u8 pkhash[WPS_OOB_PUBKEY_HASH_LEN]; wps = sm->wps; if (wps == NULL) { wpa_printf(MSG_ERROR, "EAP-WSC: WPS context not available"); return NULL; } identity = eap_get_config_identity(sm, &identity_len); if (identity && identity_len == WSC_ID_REGISTRAR_LEN && os_memcmp(identity, WSC_ID_REGISTRAR, WSC_ID_REGISTRAR_LEN) == 0) registrar = 1; /* Supplicant is Registrar */ else if (identity && identity_len == WSC_ID_ENROLLEE_LEN && os_memcmp(identity, WSC_ID_ENROLLEE, WSC_ID_ENROLLEE_LEN) == 0) registrar = 0; /* Supplicant is Enrollee */ else { wpa_hexdump_ascii(MSG_INFO, "EAP-WSC: Unexpected identity", identity, identity_len); return NULL; } data = os_zalloc(sizeof(*data)); if (data == NULL) return NULL; data->state = registrar ? MESG : WAIT_START; data->registrar = registrar; data->wps_ctx = wps; os_memset(&cfg, 0, sizeof(cfg)); cfg.wps = wps; cfg.registrar = registrar; phase1 = eap_get_config_phase1(sm); if (phase1 == NULL) { wpa_printf(MSG_INFO, "EAP-WSC: phase1 configuration data not " "set"); os_free(data); return NULL; } pos = os_strstr(phase1, "pin="); if (pos) { pos += 4; cfg.pin = (const u8 *) pos; while (*pos != '\0' && *pos != ' ') pos++; cfg.pin_len = pos - (const char *) cfg.pin; if (cfg.pin_len == 6 && os_strncmp((const char *) cfg.pin, "nfc-pw", 6) == 0) { cfg.pin = NULL; cfg.pin_len = 0; nfc = 1; } } else { pos = os_strstr(phase1, "pbc=1"); if (pos) cfg.pbc = 1; } pos = os_strstr(phase1, "dev_pw_id="); if (pos) { u16 id = atoi(pos + 10); if (id == DEV_PW_NFC_CONNECTION_HANDOVER) nfc = 1; if (cfg.pin || id == DEV_PW_NFC_CONNECTION_HANDOVER) cfg.dev_pw_id = id; } if (cfg.pin == NULL && !cfg.pbc && !nfc) { wpa_printf(MSG_INFO, "EAP-WSC: PIN or PBC not set in phase1 " "configuration data"); os_free(data); return NULL; } pos = os_strstr(phase1, " pkhash="); if (pos) { size_t len; pos += 8; end = os_strchr(pos, ' '); if (end) len = end - pos; else len = os_strlen(pos); if (len != 2 * WPS_OOB_PUBKEY_HASH_LEN || hexstr2bin(pos, pkhash, WPS_OOB_PUBKEY_HASH_LEN)) { wpa_printf(MSG_INFO, "EAP-WSC: Invalid pkhash"); os_free(data); return NULL; } cfg.peer_pubkey_hash = pkhash; } res = eap_wsc_new_ap_settings(&new_ap_settings, phase1); if (res < 0) { os_free(data); wpa_printf(MSG_DEBUG, "EAP-WSC: Failed to parse new AP " "settings"); return NULL; } if (res == 1) { wpa_printf(MSG_DEBUG, "EAP-WSC: Provide new AP settings for " "WPS"); cfg.new_ap_settings = &new_ap_settings; } data->wps = wps_init(&cfg); if (data->wps == NULL) { os_free(data); wpa_printf(MSG_DEBUG, "EAP-WSC: wps_init failed"); return NULL; } res = eap_get_config_fragment_size(sm); if (res > 0) data->fragment_size = res; else data->fragment_size = WSC_FRAGMENT_SIZE; wpa_printf(MSG_DEBUG, "EAP-WSC: Fragment size limit %u", (unsigned int) data->fragment_size); if (registrar && cfg.pin) { wps_registrar_add_pin(data->wps_ctx->registrar, NULL, NULL, cfg.pin, cfg.pin_len, 0); } /* Use reduced client timeout for WPS to avoid long wait */ if (sm->ClientTimeout > 30) sm->ClientTimeout = 30; return data; }
static void * eap_wsc_init(struct eap_sm *sm) { struct eap_wsc_data *data; const u8 *identity; size_t identity_len; int registrar; struct wps_config cfg; const char *pos; const char *phase1; struct wps_context *wps; struct wps_credential new_ap_settings; int res; u8 dev_pw[WPS_OOB_DEVICE_PASSWORD_LEN]; int nfc = 0; wps = sm->wps; if (wps == NULL) { wpa_printf(MSG_ERROR, "EAP-WSC: WPS context not available"); return NULL; } identity = eap_get_config_identity(sm, &identity_len); if (identity && identity_len == WSC_ID_REGISTRAR_LEN && os_memcmp(identity, WSC_ID_REGISTRAR, WSC_ID_REGISTRAR_LEN) == 0) registrar = 1; /* Supplicant is Registrar */ else if (identity && identity_len == WSC_ID_ENROLLEE_LEN && os_memcmp(identity, WSC_ID_ENROLLEE, WSC_ID_ENROLLEE_LEN) == 0) registrar = 0; /* Supplicant is Enrollee */ else { wpa_hexdump_ascii(MSG_INFO, "EAP-WSC: Unexpected identity", identity, identity_len); return NULL; } data = os_zalloc(sizeof(*data)); if (data == NULL) return NULL; data->state = registrar ? MESG : WAIT_START; data->registrar = registrar; data->wps_ctx = wps; os_memset(&cfg, 0, sizeof(cfg)); cfg.wps = wps; cfg.registrar = registrar; phase1 = eap_get_config_phase1(sm); if (phase1 == NULL) { wpa_printf(MSG_INFO, "EAP-WSC: phase1 configuration data not " "set"); os_free(data); return NULL; } pos = os_strstr(phase1, "pin="); if (pos) { pos += 4; cfg.pin = (const u8 *) pos; while (*pos != '\0' && *pos != ' ') pos++; cfg.pin_len = pos - (const char *) cfg.pin; if (cfg.pin_len >= WPS_OOB_DEVICE_PASSWORD_MIN_LEN * 2 && cfg.pin_len <= WPS_OOB_DEVICE_PASSWORD_LEN * 2 && hexstr2bin((const char *) cfg.pin, dev_pw, cfg.pin_len / 2) == 0) { /* Convert OOB Device Password to binary */ cfg.pin = dev_pw; cfg.pin_len /= 2; } if (cfg.pin_len == 6 && os_strncmp((const char *) cfg.pin, "nfc-pw", 6) == 0) { cfg.pin = NULL; cfg.pin_len = 0; nfc = 1; } } else { pos = os_strstr(phase1, "pbc=1"); if (pos) cfg.pbc = 1; } if (cfg.pin == NULL && !cfg.pbc && !nfc) { wpa_printf(MSG_INFO, "EAP-WSC: PIN or PBC not set in phase1 " "configuration data"); os_free(data); return NULL; } pos = os_strstr(phase1, "dev_pw_id="); if (pos && cfg.pin) cfg.dev_pw_id = atoi(pos + 10); res = eap_wsc_new_ap_settings(&new_ap_settings, phase1); if (res < 0) { os_free(data); return NULL; } if (res == 1) { wpa_printf(MSG_DEBUG, "EAP-WSC: Provide new AP settings for " "WPS"); cfg.new_ap_settings = &new_ap_settings; } data->wps = wps_init(&cfg); if (data->wps == NULL) { os_free(data); return NULL; } res = eap_get_config_fragment_size(sm); if (res > 0) data->fragment_size = res; else data->fragment_size = WSC_FRAGMENT_SIZE; wpa_printf(MSG_DEBUG, "EAP-WSC: Fragment size limit %u", (unsigned int) data->fragment_size); if (registrar && cfg.pin) { wps_registrar_add_pin(data->wps_ctx->registrar, NULL, NULL, cfg.pin, cfg.pin_len, 0); } /* Use reduced client timeout for WPS to avoid long wait */ if (sm->ClientTimeout > 30) sm->ClientTimeout = 30; return data; }
static void * eap_wsc_init(struct eap_sm *sm) { struct eap_wsc_data *data; const u8 *identity; size_t identity_len; int registrar; struct wps_config cfg; const char *pos; const char *phase1; struct wps_context *wps; struct wps_credential new_ap_settings; int res; wps = sm->wps; if (wps == NULL) { wpa_printf(MSG_ERROR, "EAP-WSC: WPS context not available"); return NULL; } identity = eap_get_config_identity(sm, &identity_len); if (identity && identity_len == WSC_ID_REGISTRAR_LEN && os_memcmp(identity, WSC_ID_REGISTRAR, WSC_ID_REGISTRAR_LEN) == 0) registrar = 1; /* Supplicant is Registrar */ else if (identity && identity_len == WSC_ID_ENROLLEE_LEN && os_memcmp(identity, WSC_ID_ENROLLEE, WSC_ID_ENROLLEE_LEN) == 0) registrar = 0; /* Supplicant is Enrollee */ else { wpa_hexdump_ascii(MSG_INFO, "EAP-WSC: Unexpected identity", identity, identity_len); return NULL; } data = os_zalloc(sizeof(*data)); if (data == NULL) return NULL; data->state = registrar ? MESG : WAIT_START; data->registrar = registrar; data->wps_ctx = wps; os_memset(&cfg, 0, sizeof(cfg)); cfg.wps = wps; cfg.registrar = registrar; phase1 = eap_get_config_phase1(sm); if (phase1 == NULL) { wpa_printf(MSG_INFO, "EAP-WSC: phase1 configuration data not " "set"); os_free(data); return NULL; } pos = os_strstr(phase1, "pin="); if (pos) { pos += 4; cfg.pin = (const u8 *) pos; while (*pos != '\0' && *pos != ' ') pos++; cfg.pin_len = pos - (const char *) cfg.pin; } else { pos = os_strstr(phase1, "pbc=1"); if (pos) cfg.pbc = 1; } if (cfg.pin == NULL && !cfg.pbc) { wpa_printf(MSG_INFO, "EAP-WSC: PIN or PBC not set in phase1 " "configuration data"); os_free(data); return NULL; } pos = os_strstr(phase1, "dev_pw_id="); if (pos && cfg.pin) cfg.dev_pw_id = atoi(pos + 10); res = eap_wsc_new_ap_settings(&new_ap_settings, phase1); if (res < 0) { os_free(data); return NULL; } if (res == 1) { wpa_printf(MSG_DEBUG, "EAP-WSC: Provide new AP settings for " "WPS"); cfg.new_ap_settings = &new_ap_settings; } data->wps = wps_init(&cfg); if (data->wps == NULL) { os_free(data); return NULL; } res = eap_get_config_fragment_size(sm); if (res > 0) data->fragment_size = res; else data->fragment_size = WSC_FRAGMENT_SIZE; wpa_printf(MSG_DEBUG, "EAP-WSC: Fragment size limit %u", (unsigned int) data->fragment_size); if (registrar && cfg.pin) { wps_registrar_add_pin(data->wps_ctx->registrar, NULL, cfg.pin, cfg.pin_len, 0); } return data; }