int wpas_wps_init(struct wpa_supplicant *wpa_s) { struct wps_context *wps; struct wps_registrar_config rcfg; wps = os_zalloc(sizeof(*wps)); if (wps == NULL) return -1; wps->cred_cb = wpa_supplicant_wps_cred; wps->event_cb = wpa_supplicant_wps_event; wps->cb_ctx = wpa_s; wps->dev.device_name = wpa_s->conf->device_name; wps->dev.manufacturer = wpa_s->conf->manufacturer; wps->dev.model_name = wpa_s->conf->model_name; wps->dev.model_number = wpa_s->conf->model_number; wps->dev.serial_number = wpa_s->conf->serial_number; if (wpa_s->conf->device_type) { char *pos; u8 oui[4]; /* <categ>-<OUI>-<subcateg> */ wps->dev.categ = atoi(wpa_s->conf->device_type); pos = os_strchr(wpa_s->conf->device_type, '-'); if (pos == NULL) { wpa_printf(MSG_ERROR, "WPS: Invalid device_type"); os_free(wps); return -1; } pos++; if (hexstr2bin(pos, oui, 4)) { wpa_printf(MSG_ERROR, "WPS: Invalid device_type OUI"); os_free(wps); return -1; } wps->dev.oui = WPA_GET_BE32(oui); pos = os_strchr(pos, '-'); if (pos == NULL) { wpa_printf(MSG_ERROR, "WPS: Invalid device_type"); os_free(wps); return -1; } pos++; wps->dev.sub_categ = atoi(pos); } wps->dev.os_version = WPA_GET_BE32(wpa_s->conf->os_version); wps->dev.rf_bands = WPS_RF_24GHZ | WPS_RF_50GHZ; /* TODO: config */ os_memcpy(wps->dev.mac_addr, wpa_s->own_addr, ETH_ALEN); if (is_nil_uuid(wpa_s->conf->uuid)) { uuid_gen_mac_addr(wpa_s->own_addr, wps->uuid); wpa_hexdump(MSG_DEBUG, "WPS: UUID based on MAC address", wps->uuid, WPS_UUID_LEN); } else os_memcpy(wps->uuid, wpa_s->conf->uuid, WPS_UUID_LEN); wps->auth_types = WPS_AUTH_WPA2PSK | WPS_AUTH_WPAPSK; wps->encr_types = WPS_ENCR_AES | WPS_ENCR_TKIP; os_memset(&rcfg, 0, sizeof(rcfg)); rcfg.new_psk_cb = wpas_wps_new_psk_cb; rcfg.pin_needed_cb = wpas_wps_pin_needed_cb; rcfg.cb_ctx = wpa_s; wps->registrar = wps_registrar_init(wps, &rcfg); if (wps->registrar == NULL) { wpa_printf(MSG_DEBUG, "Failed to initialize WPS Registrar"); os_free(wps); return -1; } wpa_s->wps = wps; return 0; }
static void wps_er_ssdp_rx(int sd, void *eloop_ctx, void *sock_ctx) { struct wps_er *er = eloop_ctx; struct sockaddr_in addr; /* client address */ socklen_t addr_len; int nread; char buf[MULTICAST_MAX_READ], *pos, *pos2, *start; int wfa = 0, byebye = 0; int max_age = -1; char *location = NULL; u8 uuid[WPS_UUID_LEN]; addr_len = sizeof(addr); nread = recvfrom(sd, buf, sizeof(buf) - 1, 0, (struct sockaddr *) &addr, &addr_len); if (nread <= 0) return; buf[nread] = '\0'; if (er->filter_addr.s_addr && er->filter_addr.s_addr != addr.sin_addr.s_addr) return; wpa_printf(MSG_DEBUG, "WPS ER: Received SSDP from %s", inet_ntoa(addr.sin_addr)); wpa_hexdump_ascii(MSG_MSGDUMP, "WPS ER: Received SSDP contents", (u8 *) buf, nread); if (sd == er->multicast_sd) { /* Reply to M-SEARCH */ if (os_strncmp(buf, "HTTP/1.1 200 OK", 15) != 0) return; /* unexpected response header */ } else { /* Unsolicited message (likely NOTIFY or M-SEARCH) */ if (os_strncmp(buf, "NOTIFY ", 7) != 0) return; /* only process notifications */ } os_memset(uuid, 0, sizeof(uuid)); for (start = buf; start && *start; start = pos) { pos = os_strchr(start, '\n'); if (pos) { if (pos[-1] == '\r') pos[-1] = '\0'; *pos++ = '\0'; } if (os_strstr(start, "schemas-wifialliance-org:device:" "WFADevice:1")) wfa = 1; if (os_strstr(start, "schemas-wifialliance-org:service:" "WFAWLANConfig:1")) wfa = 1; if (os_strncasecmp(start, "LOCATION:", 9) == 0) { start += 9; while (*start == ' ') start++; location = start; } else if (os_strncasecmp(start, "NTS:", 4) == 0) { if (os_strstr(start, "ssdp:byebye")) byebye = 1; } else if (os_strncasecmp(start, "CACHE-CONTROL:", 14) == 0) { start += 9; while (*start == ' ') start++; pos2 = os_strstr(start, "max-age="); if (pos2 == NULL) continue; pos2 += 8; max_age = atoi(pos2); } else if (os_strncasecmp(start, "USN:", 4) == 0) { start += 4; pos2 = os_strstr(start, "uuid:"); if (pos2) { pos2 += 5; while (*pos2 == ' ') pos2++; if (uuid_str2bin(pos2, uuid) < 0) { wpa_printf(MSG_DEBUG, "WPS ER: " "Invalid UUID in USN: %s", pos2); return; } } } } if (!wfa) return; /* Not WPS advertisement/reply */ if (byebye) { wps_er_ap_cache_settings(er, &addr.sin_addr); wps_er_ap_remove(er, &addr.sin_addr); return; } if (!location) return; /* Unknown location */ if (max_age < 1) return; /* No max-age reported */ wpa_printf(MSG_DEBUG, "WPS ER: AP discovered: %s " "(packet source: %s max-age: %d)", location, inet_ntoa(addr.sin_addr), max_age); wps_er_ap_add(er, uuid, &addr.sin_addr, location, max_age); }
int autoscan_init(struct wpa_supplicant *wpa_s, int req_scan) { const char *name = wpa_s->conf->autoscan; const char *params; size_t nlen; int i; const struct autoscan_ops *ops = NULL; if (wpa_s->autoscan && wpa_s->autoscan_priv) return 0; if (name == NULL) return 0; params = os_strchr(name, ':'); if (params == NULL) { params = ""; nlen = os_strlen(name); } else { nlen = params - name; params++; } for (i = 0; autoscan_modules[i]; i++) { if (os_strncmp(name, autoscan_modules[i]->name, nlen) == 0) { ops = autoscan_modules[i]; break; } } if (ops == NULL) { wpa_printf(MSG_ERROR, "autoscan: Could not find module " "matching the parameter '%s'", name); return -1; } wpa_s->autoscan_params = NULL; wpa_s->autoscan_priv = ops->init(wpa_s, params); if (wpa_s->autoscan_priv == NULL) return -1; wpa_s->autoscan = ops; wpa_printf(MSG_DEBUG, "autoscan: Initialized module '%s' with " "parameters '%s'", ops->name, params); if (!req_scan) return 0; /* * Cancelling existing scan requests, if any. */ wpa_supplicant_cancel_sched_scan(wpa_s); wpa_supplicant_cancel_scan(wpa_s); /* * Firing first scan, which will lead to call autoscan_notify_scan. */ request_scan(wpa_s); return 0; }
static int wpa_driver_privsep_set_param(void *priv, const char *param) { struct wpa_driver_privsep_data *drv = priv; const char *pos; char *own_dir, *priv_dir; static unsigned int counter = 0; size_t len; struct sockaddr_un addr; wpa_printf(MSG_DEBUG, "%s: param='%s'", __func__, param); if (param == NULL) pos = NULL; else pos = os_strstr(param, "own_dir="); if (pos) { char *end; own_dir = os_strdup(pos + 8); if (own_dir == NULL) return -1; end = os_strchr(own_dir, ' '); if (end) *end = '\0'; } else { own_dir = os_strdup("/tmp"); if (own_dir == NULL) return -1; } if (param == NULL) pos = NULL; else pos = os_strstr(param, "priv_dir="); if (pos) { char *end; priv_dir = os_strdup(pos + 9); if (priv_dir == NULL) { os_free(own_dir); return -1; } end = os_strchr(priv_dir, ' '); if (end) *end = '\0'; } else { priv_dir = os_strdup("/var/run/wpa_priv"); if (priv_dir == NULL) { os_free(own_dir); return -1; } } len = os_strlen(own_dir) + 50; drv->own_socket_path = os_malloc(len); if (drv->own_socket_path == NULL) { os_free(priv_dir); os_free(own_dir); return -1; } os_snprintf(drv->own_socket_path, len, "%s/wpa_privsep-%d-%d", own_dir, getpid(), counter++); len = os_strlen(own_dir) + 50; drv->own_cmd_path = os_malloc(len); if (drv->own_cmd_path == NULL) { os_free(drv->own_socket_path); drv->own_socket_path = NULL; os_free(priv_dir); os_free(own_dir); return -1; } os_snprintf(drv->own_cmd_path, len, "%s/wpa_privsep-%d-%d", own_dir, getpid(), counter++); os_free(own_dir); drv->priv_addr.sun_family = AF_UNIX; os_snprintf(drv->priv_addr.sun_path, sizeof(drv->priv_addr.sun_path), "%s/%s", priv_dir, drv->ifname); os_free(priv_dir); drv->priv_socket = socket(PF_UNIX, SOCK_DGRAM, 0); if (drv->priv_socket < 0) { wpa_printf(MSG_ERROR, "socket(PF_UNIX): %s", strerror(errno)); os_free(drv->own_socket_path); drv->own_socket_path = NULL; return -1; } os_memset(&addr, 0, sizeof(addr)); addr.sun_family = AF_UNIX; os_strlcpy(addr.sun_path, drv->own_socket_path, sizeof(addr.sun_path)); if (bind(drv->priv_socket, (struct sockaddr *) &addr, sizeof(addr)) < 0) { wpa_printf(MSG_ERROR, "privsep-set-params priv-sock: bind(PF_UNIX): %s", strerror(errno)); close(drv->priv_socket); drv->priv_socket = -1; unlink(drv->own_socket_path); os_free(drv->own_socket_path); drv->own_socket_path = NULL; return -1; } eloop_register_read_sock(drv->priv_socket, wpa_driver_privsep_receive, drv, NULL); drv->cmd_socket = socket(PF_UNIX, SOCK_DGRAM, 0); if (drv->cmd_socket < 0) { wpa_printf(MSG_ERROR, "socket(PF_UNIX): %s", strerror(errno)); os_free(drv->own_cmd_path); drv->own_cmd_path = NULL; return -1; } os_memset(&addr, 0, sizeof(addr)); addr.sun_family = AF_UNIX; os_strlcpy(addr.sun_path, drv->own_cmd_path, sizeof(addr.sun_path)); if (bind(drv->cmd_socket, (struct sockaddr *) &addr, sizeof(addr)) < 0) { wpa_printf(MSG_ERROR, "privsep-set-params cmd-sock: bind(PF_UNIX): %s", strerror(errno)); close(drv->cmd_socket); drv->cmd_socket = -1; unlink(drv->own_cmd_path); os_free(drv->own_cmd_path); drv->own_cmd_path = NULL; return -1; } if (wpa_priv_reg_cmd(drv, PRIVSEP_CMD_REGISTER) < 0) { wpa_printf(MSG_ERROR, "Failed to register with wpa_priv"); return -1; } return 0; }
static int wpa_supplicant_global_iface_add(struct wpa_global *global, char *cmd) { struct wpa_interface iface; char *pos; /* * <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB<driver_param> * TAB<bridge_ifname> */ wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_ADD '%s'", cmd); os_memset(&iface, 0, sizeof(iface)); do { iface.ifname = pos = cmd; pos = os_strchr(pos, '\t'); if (pos) *pos++ = '\0'; if (iface.ifname[0] == '\0') return -1; if (pos == NULL) break; iface.confname = pos; pos = os_strchr(pos, '\t'); if (pos) *pos++ = '\0'; if (iface.confname[0] == '\0') iface.confname = NULL; if (pos == NULL) break; iface.driver = pos; pos = os_strchr(pos, '\t'); if (pos) *pos++ = '\0'; if (iface.driver[0] == '\0') iface.driver = NULL; if (pos == NULL) break; iface.ctrl_interface = pos; pos = os_strchr(pos, '\t'); if (pos) *pos++ = '\0'; if (iface.ctrl_interface[0] == '\0') iface.ctrl_interface = NULL; if (pos == NULL) break; iface.driver_param = pos; pos = os_strchr(pos, '\t'); if (pos) *pos++ = '\0'; if (iface.driver_param[0] == '\0') iface.driver_param = NULL; if (pos == NULL) break; iface.bridge_ifname = pos; pos = os_strchr(pos, '\t'); if (pos) *pos++ = '\0'; if (iface.bridge_ifname[0] == '\0') iface.bridge_ifname = NULL; if (pos == NULL) break; } while (0); if (wpa_supplicant_get_iface(global, iface.ifname)) return -1; return wpa_supplicant_add_iface(global, &iface) ? 0 : -1; }
static void clean_past_ated(){ pid_t pid = getpid(); pid_t fork_pid; int pipefd[2];//0:reading, 1:writing pipe(pipefd); ate_printf(MSG_INFO,"Pid of ated: %d\n",pid); fork_pid = fork(); if(fork_pid==0){ char *argv[] = {"ps",NULL/*"-AL"*/,NULL}; close(pipefd[0]); //children only DO write data dup2(pipefd[1],1); dup2(pipefd[1],2); execvp("ps", argv); exit(0); }else{ /* Wait exec finish */ char buffer[2048]; char line[256]; char ate_pid[16]; unsigned char exist_ate = 0; close(pipefd[1]); while(read(pipefd[0],buffer, sizeof(buffer)) != 0){ char *eol = os_strchr(buffer, '\n'); char *tmp = buffer; while(eol){ int dif = eol - tmp + 1; os_memset(line, '\0', 256); os_memcpy(line, tmp, dif); if(os_strstr(line, "ated")){ int distance = 0; int dif2 = 0; char *l; ate_printf(MSG_DEBUG,"Parsing line: %s\n", line); repeat_parse: l = os_strchr(line+distance,' '); if(!l) break; ate_printf(MSG_DEBUG,"Line: 0x%x, l: 0x%x\n", line, l); dif2 = l - line -distance; distance += dif2; /* The first char is space */ if(dif2 == 0){ distance += 1; goto repeat_parse; } if((dif2) > 16){ ate_printf(MSG_DEBUG,"String too long for pid, continue to parse, [%s]\n",ate_pid); goto repeat_parse; } os_memset(ate_pid, 0, 16); os_memcpy(ate_pid, l - dif2, dif2); //For delete appending space ate_printf(MSG_DEBUG,"ate_pid: %s\n",ate_pid); exist_ate = 1; do{ int pid_found = 0; int ret = -1; sscanf(ate_pid,"%d", &pid_found); if(pid_found != pid){ ate_printf(MSG_DEBUG,"!pid_found: %d\n",pid_found); ret = kill((pid_t)pid_found, SIGHUP); if(ret) ate_printf(MSG_ERROR,"kill process %d fail\n",pid_found); else ate_printf(MSG_INFO, "kill process %d success\n",pid_found); } }while(0); } tmp += dif; eol = os_strchr(tmp, '\n'); } } close(pipefd[0]); waitpid(fork_pid, 0, 0); close(pipefd[1]); } }
static int plmn_id_match(struct wpabuf *anqp, const char *imsi) { const char *sep; u8 plmn[3]; const u8 *pos, *end; u8 udhl; sep = os_strchr(imsi, '-'); if (sep == NULL || (sep - imsi != 5 && sep - imsi != 6)) return 0; /* See Annex A of 3GPP TS 24.234 v8.1.0 for description */ plmn[0] = (imsi[0] - '0') | ((imsi[1] - '0') << 4); plmn[1] = imsi[2] - '0'; if (sep - imsi == 6) plmn[1] |= (imsi[5] - '0') << 4; else plmn[1] |= 0xf0; plmn[2] = (imsi[3] - '0') | ((imsi[4] - '0') << 4); if (anqp == NULL) return 0; pos = wpabuf_head_u8(anqp); end = pos + wpabuf_len(anqp); if (pos + 2 > end) return 0; if (*pos != 0) { wpa_printf(MSG_DEBUG, "Unsupported GUD version 0x%x", *pos); return 0; } pos++; udhl = *pos++; if (pos + udhl > end) { wpa_printf(MSG_DEBUG, "Invalid UDHL"); return 0; } end = pos + udhl; while (pos + 2 <= end) { u8 iei, len; const u8 *l_end; iei = *pos++; len = *pos++ & 0x7f; if (pos + len > end) break; l_end = pos + len; if (iei == 0 && len > 0) { /* PLMN List */ u8 num, i; num = *pos++; for (i = 0; i < num; i++) { if (pos + 3 > end) break; if (os_memcmp(pos, plmn, 3) == 0) return 1; /* Found matching PLMN */ } } pos = l_end; } return 0; }
struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path) { struct wpa_ctrl *ctrl; char buf[128]; size_t len; #ifdef CONFIG_CTRL_IFACE_UDP_REMOTE struct hostent *h; #endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */ ctrl = os_malloc(sizeof(*ctrl)); if (ctrl == NULL) return NULL; os_memset(ctrl, 0, sizeof(*ctrl)); #ifdef CONFIG_CTRL_IFACE_UDP_IPV6 ctrl->s = socket(PF_INET6, SOCK_DGRAM, 0); #else /* CONFIG_CTRL_IFACE_UDP_IPV6 */ ctrl->s = socket(PF_INET, SOCK_DGRAM, 0); #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */ if (ctrl->s < 0) { perror("socket"); os_free(ctrl); return NULL; } #ifdef CONFIG_CTRL_IFACE_UDP_IPV6 ctrl->local.sin6_family = AF_INET6; #ifdef CONFIG_CTRL_IFACE_UDP_REMOTE ctrl->local.sin6_addr = in6addr_any; #else /* CONFIG_CTRL_IFACE_UDP_REMOTE */ inet_pton(AF_INET6, "::1", &ctrl->local.sin6_addr); #endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */ #else /* CONFIG_CTRL_IFACE_UDP_IPV6 */ ctrl->local.sin_family = AF_INET; #ifdef CONFIG_CTRL_IFACE_UDP_REMOTE ctrl->local.sin_addr.s_addr = INADDR_ANY; #else /* CONFIG_CTRL_IFACE_UDP_REMOTE */ ctrl->local.sin_addr.s_addr = htonl((127 << 24) | 1); #endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */ #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */ if (bind(ctrl->s, (struct sockaddr *) &ctrl->local, sizeof(ctrl->local)) < 0) { close(ctrl->s); os_free(ctrl); return NULL; } #ifdef CONFIG_CTRL_IFACE_UDP_IPV6 ctrl->dest.sin6_family = AF_INET6; inet_pton(AF_INET6, "::1", &ctrl->dest.sin6_addr); ctrl->dest.sin6_port = htons(WPA_CTRL_IFACE_PORT); #else /* CONFIG_CTRL_IFACE_UDP_IPV6 */ ctrl->dest.sin_family = AF_INET; ctrl->dest.sin_addr.s_addr = htonl((127 << 24) | 1); ctrl->dest.sin_port = htons(WPA_CTRL_IFACE_PORT); #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */ #ifdef CONFIG_CTRL_IFACE_UDP_REMOTE if (ctrl_path) { char *port, *name; int port_id; #ifdef CONFIG_CTRL_IFACE_UDP_IPV6 char *scope; int scope_id = 0; #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */ name = os_strdup(ctrl_path); if (name == NULL) { close(ctrl->s); os_free(ctrl); return NULL; } #ifdef CONFIG_CTRL_IFACE_UDP_IPV6 port = os_strchr(name, ','); #else /* CONFIG_CTRL_IFACE_UDP_IPV6 */ port = os_strchr(name, ':'); #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */ if (port) { port_id = atoi(&port[1]); port[0] = '\0'; } else port_id = WPA_CTRL_IFACE_PORT; #ifdef CONFIG_CTRL_IFACE_UDP_IPV6 scope = os_strchr(name, '%'); if (scope) { scope_id = if_nametoindex(&scope[1]); scope[0] = '\0'; } h = gethostbyname2(name, AF_INET6); #else /* CONFIG_CTRL_IFACE_UDP_IPV6 */ h = gethostbyname(name); #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */ ctrl->remote_ip = os_strdup(name); os_free(name); if (h == NULL) { perror("gethostbyname"); close(ctrl->s); os_free(ctrl->remote_ip); os_free(ctrl); return NULL; } #ifdef CONFIG_CTRL_IFACE_UDP_IPV6 ctrl->dest.sin6_scope_id = scope_id; ctrl->dest.sin6_port = htons(port_id); os_memcpy(&ctrl->dest.sin6_addr, h->h_addr, h->h_length); #else /* CONFIG_CTRL_IFACE_UDP_IPV6 */ ctrl->dest.sin_port = htons(port_id); os_memcpy(&ctrl->dest.sin_addr.s_addr, h->h_addr, h->h_length); #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */ } else ctrl->remote_ip = os_strdup("localhost"); #endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */ if (connect(ctrl->s, (struct sockaddr *) &ctrl->dest, sizeof(ctrl->dest)) < 0) { #ifdef CONFIG_CTRL_IFACE_UDP_IPV6 char addr[INET6_ADDRSTRLEN]; wpa_printf(MSG_ERROR, "connect(%s:%d) failed: %s", inet_ntop(AF_INET6, &ctrl->dest.sin6_addr, addr, sizeof(ctrl->dest)), ntohs(ctrl->dest.sin6_port), strerror(errno)); #else /* CONFIG_CTRL_IFACE_UDP_IPV6 */ wpa_printf(MSG_ERROR, "connect(%s:%d) failed: %s", inet_ntoa(ctrl->dest.sin_addr), ntohs(ctrl->dest.sin_port), strerror(errno)); #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */ close(ctrl->s); os_free(ctrl->remote_ip); os_free(ctrl); return NULL; } len = sizeof(buf) - 1; if (wpa_ctrl_request(ctrl, "GET_COOKIE", 10, buf, &len, NULL) == 0) { buf[len] = '\0'; ctrl->cookie = os_strdup(buf); } if (wpa_ctrl_request(ctrl, "IFNAME", 6, buf, &len, NULL) == 0) { buf[len] = '\0'; ctrl->remote_ifname = os_strdup(buf); } return ctrl; }
static int wpa_supplicant_ctrl_iface_set_network( struct wpa_supplicant *wpa_s, char *cmd) { int id; struct wpa_ssid *ssid; char *name, *value; /* cmd: "<network id> <variable name> <value>" */ name = os_strchr(cmd, ' '); if (name == NULL) return -1; *name++ = '\0'; value = os_strchr(name, ' '); if (value == NULL) return -1; *value++ = '\0'; id = atoi(cmd); wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_NETWORK id=%d name='%s'", id, name); wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value", (u8 *) value, os_strlen(value)); ssid = wpa_config_get_network(wpa_s->conf, id); if (ssid == NULL) { wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network " "id=%d", id); return -1; } #ifdef ANDROID_IBSS_HACK if (os_strcmp(name, "ssid") == 0) { // check prefix if ((value[0] == '"') && (os_strncmp(value+1, ANDROID_IBSS_PREFIX, ANDROID_IBSS_PREFIX_LEN) == 0)) { if (wpa_config_set(ssid, "mode", "1", 0) < 0) { wpa_printf(MSG_DEBUG, "CTRL_IFACE: failed to set IBSS on '%s'", value); return -1; } value += ANDROID_IBSS_PREFIX_LEN; value[0] = '"'; } } #endif if (wpa_config_set(ssid, name, value, 0) < 0) { wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set network " "variable '%s'", name); return -1; } else { if (os_strcmp(name, "priority") == 0) { wpa_config_update_prio_list(wpa_s->conf); } } if (wpa_s->current_ssid == ssid) { /* * Invalidate the EAP session cache if anything in the current * configuration changes. */ eapol_sm_invalidate_cached_session(wpa_s->eapol); } if ((os_strcmp(name, "psk") == 0 && value[0] == '"' && ssid->ssid_len) || (os_strcmp(name, "ssid") == 0 && ssid->passphrase)) wpa_config_update_psk(ssid); return 0; }
struct wpa_config * wpa_config_read(const char *name) { FILE *f; char buf[512], *pos; int errors = 0, line = 0; struct wpa_ssid *ssid, *tail = NULL, *head = NULL; struct wpa_cred *cred, *cred_tail = NULL, *cred_head = NULL; struct wpa_config *config; int id = 0; int cred_id = 0; config = wpa_config_alloc_empty(NULL, NULL); if (config == NULL) return NULL; wpa_printf(MSG_DEBUG, "Reading configuration file '%s'", name); f = fopen(name, "r"); if (f == NULL) { os_free(config); return NULL; } while (wpa_config_get_line(buf, sizeof(buf), f, &line, &pos)) { if (os_strcmp(pos, "network={") == 0) { ssid = wpa_config_read_network(f, &line, id++); if (ssid == NULL) { wpa_printf(MSG_ERROR, "Line %d: failed to " "parse network block.", line); errors++; continue; } if (head == NULL) { head = tail = ssid; } else { tail->next = ssid; tail = ssid; } if (wpa_config_add_prio_network(config, ssid)) { wpa_printf(MSG_ERROR, "Line %d: failed to add " "network block to priority list.", line); errors++; continue; } } else if (os_strcmp(pos, "cred={") == 0) { cred = wpa_config_read_cred(f, &line, cred_id++); if (cred == NULL) { wpa_printf(MSG_ERROR, "Line %d: failed to " "parse cred block.", line); errors++; continue; } if (cred_head == NULL) { cred_head = cred_tail = cred; } else { cred_tail->next = cred; cred_tail = cred; } #ifndef CONFIG_NO_CONFIG_BLOBS } else if (os_strncmp(pos, "blob-base64-", 12) == 0) { if (wpa_config_process_blob(config, f, &line, pos + 12) < 0) { errors++; continue; } #endif /* CONFIG_NO_CONFIG_BLOBS */ #ifdef CONFIG_P2P } else if (os_strncmp(buf, "wme_ac_", 7) == 0 || os_strncmp(buf, "wmm_ac_", 7) == 0) { pos = os_strchr(buf, '='); if (pos == NULL) { wpa_printf(MSG_ERROR, "Line %d: invalid line '%s'", line, buf); errors++; continue; } *pos = '\0'; pos++; if (wpa_config_wmm_ac(config->wmm_ac_params, buf, pos)) { wpa_printf(MSG_ERROR, "Line %d: invalid WMM " "ac item", line); errors++; } #endif /* CONFIG_P2P */ } else if (wpa_config_process_global(config, pos, line) < 0) { wpa_printf(MSG_ERROR, "Line %d: Invalid configuration " "line '%s'.", line, pos); errors++; continue; } } fclose(f); config->ssid = head; wpa_config_debug_dump_networks(config); config->cred = cred_head; #ifndef WPA_IGNORE_CONFIG_ERRORS if (errors) { wpa_config_free(config); config = NULL; head = NULL; } #endif /* WPA_IGNORE_CONFIG_ERRORS */ return config; }
//============================================================================= bool ICACHE_FLASH_ATTR websock_rx_data(TCP_SERV_CONN *ts_conn) { // HTTP_CONN *CurHTTP; WEB_SRV_CONN *web_conn = (WEB_SRV_CONN *)ts_conn->linkd; if(web_conn == NULL) return false; WS_FRSTAT *ws = &web_conn->ws; uint16 len; uint8 *pstr; #if DEBUGSOO > 3 os_printf("ws_rx[%u]%u ", ts_conn->sizei, ts_conn->cntri); #endif if(ts_conn->sizei == 0) return true; // докачивать tcpsrv_unrecved_win(ts_conn); if((ws->flg & WS_FLG_CLOSE) != 0) { // убить буфер ts_conn->pbufi, конец давно :) web_feee_bufi(ts_conn); SetSCB(SCB_DISCONNECT); return false; } if(ts_conn->sizei > MAX_RX_BUF_SIZE) { #if DEBUGSOO > 0 os_printf("ws:rxbuf_full! "); #endif // убить буфер ts_conn->pbufi и ответить ошибкой WS_CLOSE_UNEXPECTED_ERROR web_feee_bufi(ts_conn); websock_tx_close_err(ts_conn, WS_CLOSE_MESSAGE_TOO_BIG); // WS_CLOSE_UNEXPECTED_ERROR); SetSCB(SCB_DISCONNECT); return false; } pstr = ts_conn->pbufi;// + ts_conn->cntri; len = ts_conn->sizei;// - ts_conn->cntri; while(ts_conn->cntri < ts_conn->sizei || (ws->flg & WS_FLG_FIN) != 0) { pstr = ts_conn->pbufi;// + ts_conn->cntri; len = ts_conn->sizei;// - ts_conn->cntri; if((ws->flg & WS_FLG_FIN) != 0 // обработка || ws->frame_len > ws->cur_len) { ws->flg &= ~WS_FLG_FIN; len = mMIN(ws->frame_len - ws->cur_len, mMIN(MAX_WS_DATA_BLK_SIZE, len)); // размаскировать if((ws->flg & WS_FLG_MASK) != 0) WebsocketMask(ws, pstr, len); #if DEBUGSOO > 3 os_printf("wsfr[%u]blk[%u]at:%u ", ws->frame_len, len, ws->cur_len); #endif switch(ws->status) { case sw_frs_binary: #if DEBUGSOO > 1 os_printf("ws:bin "); #endif if(ws->frame_len != 0) { // пока просто эхо uint32 opcode = WS_OPCODE_BINARY; if(ws->cur_len != 0) opcode = WS_OPCODE_CONTINUE; if(ws->frame_len == ws->cur_len + len) opcode |= WS_FRAGMENT_FIN; if(websock_tx_frame(ts_conn, opcode, pstr, len) != ERR_OK) { return false; // не докачивать, ошибка или закрытие } } ws->cur_len += len; ts_conn->cntri += len; break; case sw_frs_text: #if DEBUGSOO > 1 os_printf("ws:txt "); #if DEBUGSOO > 2 if(ws->frame_len != 0) { uint8 tt = pstr[len]; pstr[len] = 0; os_printf("'%s' ", pstr); pstr[len] = tt; } #endif #endif if(ws->frame_len == ws->cur_len + len && ws->frame_len != 0) { // полное соо web_conn->msgbufsize = tcp_sndbuf(ts_conn->pcb); // сколько можем выввести сейчас? if (web_conn->msgbufsize < MIN_SEND_SIZE) { #if DEBUGSOO > 0 os_printf("ws:sndbuf=%u! ", web_conn->msgbufsize); #endif websock_tx_close_err(ts_conn, WS_CLOSE_UNEXPECTED_ERROR); SetSCB(SCB_FCLOSE|SCB_DISCONNECT); return false; } if(ws->frame_len == (sizeof(txt_wsping)-1) && rom_xstrcmp(pstr, txt_wsping) != 0){ copy_s4d1(pstr, (void *)txt_wspong, sizeof(txt_wspong) - 1); if(websock_tx_frame(ts_conn, WS_OPCODE_TEXT | WS_FRAGMENT_FIN, pstr, sizeof(txt_wspong) - 1) != ERR_OK) { return false; // не докачивать, ошибка или закрытие } } else { web_conn->msgbuf = (uint8 *) os_malloc(web_conn->msgbufsize); if (web_conn->msgbuf == NULL) { #if DEBUGSOO > 0 os_printf("ws:mem!\n"); #endif websock_tx_close_err(ts_conn, WS_CLOSE_UNEXPECTED_ERROR); SetSCB(SCB_FCLOSE|SCB_DISCONNECT); return false; }; web_conn->msgbuflen = 0; uint32 opcode; if(CheckSCB(SCB_RETRYCB)) { // повторный callback? да if(web_conn->func_web_cb != NULL) web_conn->func_web_cb(ts_conn); if(!CheckSCB(SCB_RETRYCB)) { ClrSCB(SCB_FCLOSE | SCB_DISCONNECT); opcode = WS_OPCODE_CONTINUE | WS_FRAGMENT_FIN; } else opcode = WS_OPCODE_CONTINUE; } else { pstr[len] = '\0'; uint8 *vstr = os_strchr(pstr, '='); if(vstr != NULL) { *vstr++ = '\0'; web_int_vars(ts_conn, pstr, vstr); } else { web_conn->msgbuf[0] = 0; web_int_callback(ts_conn, pstr); } if(CheckSCB(SCB_RETRYCB)) opcode = WS_OPCODE_TEXT; else { ClrSCB(SCB_FCLOSE | SCB_DISCONNECT); opcode = WS_OPCODE_TEXT | WS_FRAGMENT_FIN; } } if(web_conn->msgbuflen != 0) { if(websock_tx_frame(ts_conn, opcode, web_conn->msgbuf, web_conn->msgbuflen) != ERR_OK) { os_free(web_conn->msgbuf); web_conn->msgbuf = NULL; return false; // не докачивать, ошибка или закрытие } } os_free(web_conn->msgbuf); web_conn->msgbuf = NULL; if(CheckSCB(SCB_RETRYCB)) return false; } } /* if(0) { uint32 opcode = WS_OPCODE_TEXT; if(ws->cur_len != 0) opcode = WS_OPCODE_CONTINUE; if(ws->frame_len == ws->cur_len + len) opcode |= WS_FRAGMENT_FIN; if(websock_tx_frame(ts_conn, opcode, pstr, len) != ERR_OK) { return false; // не докачивать, ошибка или закрытие } } */ ws->cur_len += len; ts_conn->cntri += len; return true; // докачивать // break; // break; case sw_frs_ping: #if DEBUGSOO > 1 os_printf("ws:ping "); #endif { uint32 opcode = WS_OPCODE_PONG; if(ws->cur_len != 0) opcode = WS_OPCODE_CONTINUE; if(ws->frame_len == ws->cur_len + len) opcode |= WS_FRAGMENT_FIN; if(websock_tx_frame(ts_conn, opcode, pstr, len) != ERR_OK) { return false; // не докачивать, ошибка или закрытие } } ws->cur_len += len; ts_conn->cntri += len; return true; // докачивать // break; case sw_frs_pong: #if DEBUGSOO > 1 os_printf("ws:pong "); #endif ws->cur_len += len; ts_conn->cntri += len; break; // return true; case sw_frs_close: #if DEBUGSOO > 1 os_printf("ws:close "); #endif // if((ws->flg & WS_FLG_CLOSE) == 0) { { if(len >= 2) { uint32 close_code = (pstr[0]<<8) | pstr[1]; #if DEBUGSOO > 1 os_printf("code:%d ", close_code); #endif if(close_code == WS_CLOSE_NORMAL) websock_tx_close_err(ts_conn, WS_CLOSE_NORMAL); // else websock_tx_frame(ts_conn, WS_OPCODE_CLOSE | WS_FRAGMENT_FIN, NULL, 0); } else { websock_tx_close_err(ts_conn, WS_CLOSE_NORMAL); // websock_tx_frame(ts_conn, WS_OPCODE_CLOSE | WS_FRAGMENT_FIN, NULL, 0); } } ts_conn->flag.pcb_time_wait_free = 1; SetSCB(SCB_DISCONNECT); // ts_conn->cntri = ts_conn->sizei; /* ws->cur_len += len; ts_conn->cntri += len; */ return false; default: #if DEBUGSOO > 0 os_printf("ws:f?! "); #endif websock_tx_close_err(ts_conn, WS_CLOSE_UNEXPECTED_ERROR); SetSCB(SCB_DISCONNECT); // ts_conn->cntri = ts_conn->sizei; return false; } } else if(ws->cur_len >= ws->frame_len) { // прием и разбор нового фрейма if((ws->flg & WS_FLG_FIN) != 0) { // обработка #if DEBUGSOO > 3 os_printf("ws_rx:fin=%u ", ws->cur_len); #endif } else { uint32 ret = WebsocketHead(ws, pstr, len); if(ret >= WS_CLOSE_NORMAL) { // error или close #if DEBUGSOO > 0 os_printf("ws:txerr=%u ", ret); #endif websock_tx_close_err(ts_conn, ret); // ts_conn->cntri = ts_conn->sizei; // убить буфер ts_conn->pbufi return false; // error } else if(ret == 0) { #if DEBUGSOO > 3 os_printf("ws_rx... "); #endif return true; // докачивать } ts_conn->cntri += ws->head_len; // вычесть заголовок /* switch(ws->status) { case sw_frs_binary: break; case sw_frs_text: if(ws->frame_len > MAX_RX_BUF_SIZE) { websock_tx_close_err(ts_conn, WS_CLOSE_MESSAGE_TOO_BIG); return false; } break; } */ } } #if DEBUGSOO > 3 os_printf("trim%u-%u ", ts_conn->sizei, ts_conn->sizei - ts_conn->cntri ); #endif if(!web_trim_bufi(ts_conn, &ts_conn->pbufi[ts_conn->cntri], ts_conn->sizei - ts_conn->cntri)) { #if DEBUGSOO > 0 os_printf("ws:trim_err! "); #endif // убить буфер ts_conn->pbufi и ответить ошибкой WS_CLOSE_UNEXPECTED_ERROR websock_tx_close_err(ts_conn, WS_CLOSE_UNEXPECTED_ERROR); SetSCB(SCB_DISCONNECT); // ts_conn->cntri = ts_conn->sizei; return false; }; } return false; // не докачивать, ошибка или закрытие }
static char * wpa_cli_get_default_ifname(void) { char *ifname = NULL; #ifdef CONFIG_CTRL_IFACE_UNIX struct dirent *dent; DIR *dir = opendir(ctrl_iface_dir); if (!dir) { #ifdef ANDROID char ifprop[PROPERTY_VALUE_MAX]; if (property_get("wifi.interface", ifprop, NULL) != 0) { ifname = os_strdup(ifprop); printf("Using interface '%s'\n", ifname); return ifname; } #endif return NULL; } while ((dent = readdir(dir))) { #ifdef _DIRENT_HAVE_D_TYPE /* * Skip the file if it is not a socket. Also accept * DT_UNKNOWN (0) in case the C library or underlying * file system does not support d_type. */ if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN) continue; #endif /* _DIRENT_HAVE_D_TYPE */ if (os_strcmp(dent->d_name, ".") == 0 || os_strcmp(dent->d_name, "..") == 0) continue; printf("Selected interface '%s'\n", dent->d_name); ifname = os_strdup(dent->d_name); break; } closedir(dir); #endif /* CONFIG_CTRL_IFACE_UNIX */ #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE #ifdef ANDROID char buf[4096], #else char buf[2048], #endif *pos; size_t len; struct wpa_ctrl *ctrl; int ret; ctrl = wpa_ctrl_open(NULL); if (ctrl == NULL) return NULL; len = sizeof(buf) - 1; ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL); if (ret >= 0) { buf[len] = '\0'; pos = os_strchr(buf, '\n'); if (pos) *pos = '\0'; ifname = os_strdup(buf); } wpa_ctrl_close(ctrl); #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */ return ifname; }
static void wpa_cli_action_process(const char *msg) { const char *pos; char *copy = NULL, *id, *pos2; pos = msg; if (*pos == '<') { /* skip priority */ pos = os_strchr(pos, '>'); if (pos) pos++; else pos = msg; } if (str_match(pos, WPA_EVENT_CONNECTED)) { int new_id = -1; os_unsetenv("WPA_ID"); os_unsetenv("WPA_ID_STR"); os_unsetenv("WPA_CTRL_DIR"); pos = os_strstr(pos, "[id="); if (pos) copy = os_strdup(pos + 4); if (copy) { pos2 = id = copy; while (*pos2 && *pos2 != ' ') pos2++; *pos2++ = '\0'; new_id = atoi(id); os_setenv("WPA_ID", id, 1); while (*pos2 && *pos2 != '=') pos2++; if (*pos2 == '=') pos2++; id = pos2; while (*pos2 && *pos2 != ']') pos2++; *pos2 = '\0'; os_setenv("WPA_ID_STR", id, 1); os_free(copy); } os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1); if (!wpa_cli_connected || new_id != wpa_cli_last_id) { wpa_cli_connected = 1; wpa_cli_last_id = new_id; wpa_cli_exec(action_file, ctrl_ifname, "CONNECTED"); } } else if (str_match(pos, WPA_EVENT_DISCONNECTED)) { if (wpa_cli_connected) { wpa_cli_connected = 0; wpa_cli_exec(action_file, ctrl_ifname, "DISCONNECTED"); } } else if (str_match(pos, WPA_EVENT_TERMINATING)) { printf("wpa_supplicant is terminating - stop monitoring\n"); wpa_cli_quit = 1; } }
struct wps_er * wps_er_init(struct wps_context *wps, const char *ifname, const char *filter) { struct wps_er *er; struct in_addr addr; er = os_zalloc(sizeof(*er)); if (er == NULL) return NULL; dl_list_init(&er->ap); dl_list_init(&er->ap_unsubscribing); dl_list_init(&er->ap_settings); er->multicast_sd = -1; er->ssdp_sd = -1; os_strlcpy(er->ifname, ifname, sizeof(er->ifname)); er->wps = wps; if (os_get_random((unsigned char *) &er->event_id, sizeof(er->event_id)) < 0) { wps_er_deinit(er, NULL, NULL); return NULL; } /* Limit event_id to < 32 bits to avoid issues with atoi() */ er->event_id &= 0x0fffffff; if (filter && os_strncmp(filter, "ifname=", 7) == 0) { const char *pos, *end; pos = filter + 7; end = os_strchr(pos, ' '); if (end) { size_t len = end - pos; os_strlcpy(er->ifname, pos, len < sizeof(er->ifname) ? len + 1 : sizeof(er->ifname)); filter = end + 1; } else { os_strlcpy(er->ifname, pos, sizeof(er->ifname)); filter = NULL; } er->forced_ifname = 1; } if (filter) { if (inet_aton(filter, &er->filter_addr) == 0) { wpa_printf(MSG_INFO, "WPS UPnP: Invalid filter " "address %s", filter); wps_er_deinit(er, NULL, NULL); return NULL; } wpa_printf(MSG_DEBUG, "WPS UPnP: Only accepting connections " "with %s", filter); } if (get_netif_info(er->ifname, &er->ip_addr, &er->ip_addr_text, er->mac_addr)) { wpa_printf(MSG_INFO, "WPS UPnP: Could not get IP/MAC address " "for %s. Does it have IP address?", er->ifname); wps_er_deinit(er, NULL, NULL); return NULL; } if (wps_er_ssdp_init(er) < 0) { wpa_printf(MSG_INFO, "WPS UPnP: SSDP initialization failed"); wps_er_deinit(er, NULL, NULL); return NULL; } addr.s_addr = er->ip_addr; er->http_srv = http_server_init(&addr, -1, wps_er_http_req, er); if (er->http_srv == NULL) { wpa_printf(MSG_INFO, "WPS UPnP: HTTP initialization failed"); wps_er_deinit(er, NULL, NULL); return NULL; } er->http_port = http_server_get_port(er->http_srv); wpa_printf(MSG_DEBUG, "WPS ER: Start (ifname=%s ip_addr=%s)", er->ifname, er->ip_addr_text); return er; }
int main(int argc, char *argv[]) { struct hapd_interfaces interfaces; int ret = 1; size_t i, j; int c, debug = 0, daemonize = 0; char *pid_file = NULL; const char *log_file = NULL; const char *entropy_file = NULL; char **bss_config = NULL, **tmp_bss; size_t num_bss_configs = 0; #ifdef CONFIG_DEBUG_LINUX_TRACING int enable_trace_dbg = 0; #endif /* CONFIG_DEBUG_LINUX_TRACING */ if (os_program_init()) return -1; os_memset(&interfaces, 0, sizeof(interfaces)); interfaces.reload_config = hostapd_reload_config; interfaces.config_read_cb = hostapd_config_read; interfaces.for_each_interface = hostapd_for_each_interface; interfaces.ctrl_iface_init = hostapd_ctrl_iface_init; interfaces.ctrl_iface_deinit = hostapd_ctrl_iface_deinit; interfaces.driver_init = hostapd_driver_init; interfaces.global_iface_path = NULL; interfaces.global_iface_name = NULL; interfaces.global_ctrl_sock = -1; for (;;) { c = getopt(argc, argv, "b:Bde:f:hKP:Ttu:vg:G:"); if (c < 0) break; switch (c) { case 'h': usage(); break; case 'd': debug++; if (wpa_debug_level > 0) wpa_debug_level--; break; case 'B': daemonize++; break; case 'e': entropy_file = optarg; break; case 'f': log_file = optarg; break; case 'K': wpa_debug_show_keys++; break; case 'P': os_free(pid_file); pid_file = os_rel2abs_path(optarg); break; case 't': wpa_debug_timestamp++; break; #ifdef CONFIG_DEBUG_LINUX_TRACING case 'T': enable_trace_dbg = 1; break; #endif /* CONFIG_DEBUG_LINUX_TRACING */ case 'v': show_version(); exit(1); break; case 'g': if (hostapd_get_global_ctrl_iface(&interfaces, optarg)) return -1; break; case 'G': if (hostapd_get_ctrl_iface_group(&interfaces, optarg)) return -1; break; case 'b': tmp_bss = os_realloc_array(bss_config, num_bss_configs + 1, sizeof(char *)); if (tmp_bss == NULL) goto out; bss_config = tmp_bss; bss_config[num_bss_configs++] = optarg; break; #ifdef CONFIG_WPS case 'u': return gen_uuid(optarg); #endif /* CONFIG_WPS */ default: usage(); break; } } if (optind == argc && interfaces.global_iface_path == NULL && num_bss_configs == 0) usage(); wpa_msg_register_ifname_cb(hostapd_msg_ifname_cb); if (log_file) wpa_debug_open_file(log_file); #ifdef CONFIG_DEBUG_LINUX_TRACING if (enable_trace_dbg) { int tret = wpa_debug_open_linux_tracing(); if (tret) { wpa_printf(MSG_ERROR, "Failed to enable trace logging"); return -1; } } #endif /* CONFIG_DEBUG_LINUX_TRACING */ interfaces.count = argc - optind; if (interfaces.count || num_bss_configs) { interfaces.iface = os_calloc(interfaces.count + num_bss_configs, sizeof(struct hostapd_iface *)); if (interfaces.iface == NULL) { wpa_printf(MSG_ERROR, "malloc failed"); return -1; } } if (hostapd_global_init(&interfaces, entropy_file)) { wpa_printf(MSG_ERROR, "Failed to initilize global context"); return -1; } /* Allocate and parse configuration for full interface files */ for (i = 0; i < interfaces.count; i++) { interfaces.iface[i] = hostapd_interface_init(&interfaces, argv[optind + i], debug); if (!interfaces.iface[i]) { wpa_printf(MSG_ERROR, "Failed to initialize interface"); goto out; } } /* Allocate and parse configuration for per-BSS files */ for (i = 0; i < num_bss_configs; i++) { struct hostapd_iface *iface; char *fname; wpa_printf(MSG_INFO, "BSS config: %s", bss_config[i]); fname = os_strchr(bss_config[i], ':'); if (fname == NULL) { wpa_printf(MSG_ERROR, "Invalid BSS config identifier '%s'", bss_config[i]); goto out; } *fname++ = '\0'; iface = hostapd_interface_init_bss(&interfaces, bss_config[i], fname, debug); if (iface == NULL) goto out; for (j = 0; j < interfaces.count; j++) { if (interfaces.iface[j] == iface) break; } if (j == interfaces.count) { struct hostapd_iface **tmp; tmp = os_realloc_array(interfaces.iface, interfaces.count + 1, sizeof(struct hostapd_iface *)); if (tmp == NULL) { hostapd_interface_deinit_free(iface); goto out; } interfaces.iface = tmp; interfaces.iface[interfaces.count++] = iface; } } /* * Enable configured interfaces. Depending on channel configuration, * this may complete full initialization before returning or use a * callback mechanism to complete setup in case of operations like HT * co-ex scans, ACS, or DFS are needed to determine channel parameters. * In such case, the interface will be enabled from eloop context within * hostapd_global_run(). */ interfaces.terminate_on_error = interfaces.count; for (i = 0; i < interfaces.count; i++) { if (hostapd_driver_init(interfaces.iface[i]) || hostapd_setup_interface(interfaces.iface[i])) goto out; } hostapd_global_ctrl_iface_init(&interfaces); if (hostapd_global_run(&interfaces, daemonize, pid_file)) { wpa_printf(MSG_ERROR, "Failed to start eloop"); goto out; } ret = 0; out: hostapd_global_ctrl_iface_deinit(&interfaces); /* Deinitialize all interfaces */ for (i = 0; i < interfaces.count; i++) { if (!interfaces.iface[i]) continue; interfaces.iface[i]->driver_ap_teardown = !!(interfaces.iface[i]->drv_flags & WPA_DRIVER_FLAGS_AP_TEARDOWN_SUPPORT); hostapd_interface_deinit_free(interfaces.iface[i]); } os_free(interfaces.iface); hostapd_global_deinit(pid_file); os_free(pid_file); if (log_file) wpa_debug_close_file(); wpa_debug_close_linux_tracing(); os_free(bss_config); os_program_deinit(); return ret; }
static int eap_wsc_new_ap_settings(struct wps_credential *cred, const char *params) { const char *pos, *end; size_t len; os_memset(cred, 0, sizeof(*cred)); pos = os_strstr(params, "new_ssid="); if (pos == NULL) return 0; pos += 9; end = os_strchr(pos, ' '); if (end == NULL) len = os_strlen(pos); else len = end - pos; if ((len & 1) || len > 2 * sizeof(cred->ssid) || hexstr2bin(pos, cred->ssid, len / 2)) return -1; cred->ssid_len = len / 2; pos = os_strstr(params, "new_auth="); if (pos == NULL) return -1; if (os_strncmp(pos + 9, "OPEN", 4) == 0) cred->auth_type = WPS_AUTH_OPEN; else if (os_strncmp(pos + 9, "WPAPSK", 6) == 0) cred->auth_type = WPS_AUTH_WPAPSK; else if (os_strncmp(pos + 9, "WPA2PSK", 7) == 0) cred->auth_type = WPS_AUTH_WPA2PSK; else return -1; pos = os_strstr(params, "new_encr="); if (pos == NULL) return -1; if (os_strncmp(pos + 9, "NONE", 4) == 0) cred->encr_type = WPS_ENCR_NONE; else if (os_strncmp(pos + 9, "WEP", 3) == 0) cred->encr_type = WPS_ENCR_WEP; else if (os_strncmp(pos + 9, "TKIP", 4) == 0) cred->encr_type = WPS_ENCR_TKIP; else if (os_strncmp(pos + 9, "CCMP", 4) == 0) cred->encr_type = WPS_ENCR_AES; else return -1; pos = os_strstr(params, "new_key="); if (pos == NULL) return 0; pos += 8; end = os_strchr(pos, ' '); if (end == NULL) len = os_strlen(pos); else len = end - pos; if ((len & 1) || len > 2 * sizeof(cred->key) || hexstr2bin(pos, cred->key, len / 2)) return -1; cred->key_len = len / 2; return 1; }
static int eap_mschapv2_failure_txt(struct eap_sm *sm, struct eap_mschapv2_data *data, char *txt) { char *pos; //char *msg = ""; int retry = 1; struct eap_peer_config *config = eap_get_config(sm); pos = txt; if (pos && os_strncmp(pos, "E=", 2) == 0) { pos += 2; data->prev_error = atoi(pos); pos = (char *)os_strchr(pos, ' '); if (pos) pos++; } if (pos && os_strncmp(pos, "R=", 2) == 0) { pos += 2; retry = atoi(pos); pos = (char *)os_strchr(pos, ' '); if (pos) pos++; } if (pos && os_strncmp(pos, "C=", 2) == 0) { int hex_len; pos += 2; hex_len = (char *)os_strchr(pos, ' ') - (char *)pos; if (hex_len == PASSWD_CHANGE_CHAL_LEN * 2) { if (hexstr2bin(pos, data->passwd_change_challenge, PASSWD_CHANGE_CHAL_LEN)) { wpa_printf(MSG_ERROR, "EAP-MSCHAPV2: invalid failure challenge\n"); } else { data->passwd_change_challenge_valid = 1; } } else { wpa_printf(MSG_ERROR, "EAP-MSCHAPV2: required challenge field " "was not present in failure message\n"); } } if (pos && os_strncmp(pos, "V=", 2) == 0) { pos += 2; data->passwd_change_version = atoi(pos); pos = (char *)os_strchr(pos, ' '); if (pos) pos++; } if (pos && os_strncmp(pos, "M=", 2) == 0) { pos += 2; //msg = pos; } #if 0 wpa_printf(MSG_WARNING, "EAP-MSCHAPV2: failure message: '%s' (retry %sallowed, error %d)", msg, retry == 1? "" : "not ", data->prev_error); #endif if (data->prev_error == ERROR_PASSWD_EXPIRED && data->passwd_change_version == 3 && config) { if (config->new_password == NULL) { wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Password expired - " "password change reqired\n"); //eap_sm_request_new_password(sm); } } else if (retry == 1 && config) { if (!config->mschapv2_retry) //eap_sm_request_identity(sm); //eap_sm_request_password(sm); config->mschapv2_retry = 1; } else if (config) { config->mschapv2_retry = 0; } return retry == 1; }
static int test_nist_key_wrap_ad(const char *fname) { FILE *f; int ret = 0; char buf[15000], *pos, *pos2; u8 bin[2000], k[32], p[1024], c[1024 + 8], result[1024 + 8]; size_t bin_len, k_len = 0, p_len = 0, c_len = 0; int ok = 0; int fail; printf("NIST KW AD tests from %s\n", fname); f = fopen(fname, "r"); if (f == NULL) { printf("%s does not exist - cannot validate test vectors\n", fname); return 1; } while (fgets(buf, sizeof(buf), f)) { if (buf[0] == '#') continue; fail = 0; pos = os_strchr(buf, '='); if (pos == NULL) { if (os_strncmp(buf, "FAIL", 4) == 0) { fail = 1; goto skip_val_parse; } continue; } pos2 = pos - 1; while (pos2 >= buf && *pos2 == ' ') *pos2-- = '\0'; *pos++ = '\0'; while (*pos == ' ') *pos++ = '\0'; pos2 = os_strchr(pos, '\r'); if (!pos2) pos2 = os_strchr(pos, '\n'); if (pos2) *pos2 = '\0'; else pos2 = pos + os_strlen(pos); if (buf[0] == '[') { printf("%s = %s\n", buf, pos); continue; } if (os_strcmp(buf, "COUNT") == 0) { printf("Test %s - ", pos); continue; } bin_len = os_strlen(pos); if (bin_len > sizeof(bin) * 2) { printf("Too long binary data (%s)\n", buf); return 1; } if (bin_len & 0x01) { printf("Odd number of hexstring values (%s)\n", buf); return 1; } bin_len /= 2; if (hexstr2bin(pos, bin, bin_len) < 0) { printf("Invalid hex string '%s' (%s)\n", pos, buf); return 1; } if (os_strcmp(buf, "K") == 0) { if (bin_len > sizeof(k)) { printf("Too long K (%u)\n", (unsigned) bin_len); return 1; } os_memcpy(k, bin, bin_len); k_len = bin_len; continue; } if (os_strcmp(buf, "C") == 0) { if (bin_len > sizeof(c)) { printf("Too long C (%u)\n", (unsigned) bin_len); return 1; } os_memcpy(c, bin, bin_len); c_len = bin_len; continue; } skip_val_parse: if (!fail) { if (os_strcmp(buf, "P") != 0) { printf("Unexpected field '%s'\n", buf); continue; } if (bin_len > sizeof(p)) { printf("Too long P (%u)\n", (unsigned) bin_len); return 1; } os_memcpy(p, bin, bin_len); p_len = bin_len; if (p_len % 8 != 0 || c_len % 8 != 0 || c_len - p_len != 8) { printf("invalid parameter length (p_len=%u c_len=%u)\n", (unsigned) p_len, (unsigned) c_len); continue; } } if (aes_unwrap(k, k_len, (c_len / 8) - 1, c, result)) { if (fail) { printf("OK (fail reported)\n"); ok++; continue; } printf("aes_unwrap() failed\n"); ret++; continue; } if (fail) { printf("FAIL (mismatch not reported)\n"); ret++; } else if (os_memcmp(p, result, p_len) == 0) { printf("OK\n"); ok++; } else { printf("FAIL\n"); ret++; } } fclose(f); if (ret) printf("Test case failed\n"); else printf("%d test vectors OK\n", ok); return ret; }
/* Given that we have received a header w/ SUBSCRIBE, act upon it * * Format of SUBSCRIBE (case-insensitive): * * First line must be: * SUBSCRIBE /wps_event HTTP/1.1 * * Our response (if no error) which includes only required lines is: * HTTP/1.1 200 OK * Server: xx, UPnP/1.0, xx * SID: uuid:xxxxxxxxx * Timeout: Second-<n> * Content-Length: 0 * Date: xxxx * * Header lines must end with \r\n * Per RFC 2616, content-length: is not required but connection:close * would appear to be required (given that we will be closing it!). */ static void web_connection_parse_subscribe(struct upnp_wps_device_sm *sm, struct http_request *req, const char *filename) { struct wpabuf *buf; char *b; char *hdr = http_request_get_hdr(req); char *h; char *match; int match_len; char *end; int len; int got_nt = 0; u8 uuid[UUID_LEN]; int got_uuid = 0; char *callback_urls = NULL; struct subscription *s = NULL; enum http_reply_code ret = HTTP_INTERNAL_SERVER_ERROR; buf = wpabuf_alloc(1000); if (buf == NULL) { http_request_deinit(req); return; } /* Parse/validate headers */ h = hdr; /* First line: SUBSCRIBE /wps_event HTTP/1.1 * has already been parsed. */ if (os_strcasecmp(filename, UPNP_WPS_DEVICE_EVENT_FILE) != 0) { ret = HTTP_PRECONDITION_FAILED; goto error; } wpa_printf(MSG_DEBUG, "WPS UPnP: HTTP SUBSCRIBE for event"); end = os_strchr(h, '\n'); for (; end != NULL; h = end + 1) { /* Option line by option line */ h = end + 1; end = os_strchr(h, '\n'); if (end == NULL) break; /* no unterminated lines allowed */ /* NT assures that it is our type of subscription; * not used for a renewl. **/ match = "NT:"; match_len = os_strlen(match); if (os_strncasecmp(h, match, match_len) == 0) { h += match_len; while (*h == ' ' || *h == '\t') h++; match = "upnp:event"; match_len = os_strlen(match); if (os_strncasecmp(h, match, match_len) != 0) { ret = HTTP_BAD_REQUEST; goto error; } got_nt = 1; continue; } /* HOST should refer to us */ #if 0 match = "HOST:"; match_len = os_strlen(match); if (os_strncasecmp(h, match, match_len) == 0) { h += match_len; while (*h == ' ' || *h == '\t') h++; ..... } #endif /* CALLBACK gives one or more URLs for NOTIFYs * to be sent as a result of the subscription. * Each URL is enclosed in angle brackets. */ match = "CALLBACK:"; match_len = os_strlen(match); if (os_strncasecmp(h, match, match_len) == 0) { h += match_len; while (*h == ' ' || *h == '\t') h++; len = end - h; os_free(callback_urls); callback_urls = os_malloc(len + 1); if (callback_urls == NULL) { ret = HTTP_INTERNAL_SERVER_ERROR; goto error; } os_memcpy(callback_urls, h, len); callback_urls[len] = 0; continue; } /* SID is only for renewal */ match = "SID:"; match_len = os_strlen(match); if (os_strncasecmp(h, match, match_len) == 0) { h += match_len; while (*h == ' ' || *h == '\t') h++; match = "uuid:"; match_len = os_strlen(match); if (os_strncasecmp(h, match, match_len) != 0) { ret = HTTP_BAD_REQUEST; goto error; } h += match_len; while (*h == ' ' || *h == '\t') h++; if (uuid_str2bin(h, uuid)) { ret = HTTP_BAD_REQUEST; goto error; } got_uuid = 1; continue; } /* TIMEOUT is requested timeout, but apparently we can * just ignore this. */ }
struct wpa_config * wpa_config_read(const char *name) { FILE *f; char buf[256], *pos; int errors = 0, line = 0; struct wpa_ssid *ssid, *tail = NULL, *head = NULL; struct wpa_config *config; int id = 0; config = wpa_config_alloc_empty(NULL, NULL); if (config == NULL) return NULL; wpa_printf(MSG_DEBUG, "Reading configuration file '%s'", name); f = fopen(name, "r"); if (f == NULL) { os_free(config); return NULL; } while (wpa_config_get_line(buf, sizeof(buf), f, &line, &pos)) { if (os_strcmp(pos, "network={") == 0) { ssid = wpa_config_read_network(f, &line, id++); if (ssid == NULL) { wpa_printf(MSG_ERROR, "Line %d: failed to " "parse network block.", line); #ifndef WPA_IGNORE_CONFIG_ERRORS errors++; #endif continue; } if (head == NULL) { head = tail = ssid; } else { tail->next = ssid; tail = ssid; } if (wpa_config_add_prio_network(config, ssid)) { wpa_printf(MSG_ERROR, "Line %d: failed to add " "network block to priority list.", line); errors++; continue; } } else if (os_strncmp(pos, "blob-base64-", 12) == 0) { char *bname = pos + 12, *name_end; struct wpa_config_blob *blob; name_end = os_strchr(bname, '='); if (name_end == NULL) { wpa_printf(MSG_ERROR, "Line %d: no blob name " "terminator", line); errors++; continue; } *name_end = '\0'; blob = wpa_config_read_blob(f, &line, bname); if (blob == NULL) { wpa_printf(MSG_ERROR, "Line %d: failed to read" " blob %s", line, bname); errors++; continue; } wpa_config_set_blob(config, blob); #ifdef CONFIG_CTRL_IFACE } else if (os_strncmp(pos, "ctrl_interface=", 15) == 0) { os_free(config->ctrl_interface); config->ctrl_interface = os_strdup(pos + 15); wpa_printf(MSG_DEBUG, "ctrl_interface='%s'", config->ctrl_interface); } else if (os_strncmp(pos, "ctrl_interface_group=", 21) == 0) { os_free(config->ctrl_interface_group); config->ctrl_interface_group = os_strdup(pos + 21); wpa_printf(MSG_DEBUG, "ctrl_interface_group='%s' " "(DEPRECATED)", config->ctrl_interface_group); #endif /* CONFIG_CTRL_IFACE */ } else if (os_strncmp(pos, "eapol_version=", 14) == 0) { config->eapol_version = atoi(pos + 14); if (config->eapol_version < 1 || config->eapol_version > 2) { wpa_printf(MSG_ERROR, "Line %d: Invalid EAPOL " "version (%d): '%s'.", line, config->eapol_version, pos); errors++; continue; } wpa_printf(MSG_DEBUG, "eapol_version=%d", config->eapol_version); } else if (os_strncmp(pos, "ap_scan=", 8) == 0) { config->ap_scan = atoi(pos + 8); wpa_printf(MSG_DEBUG, "ap_scan=%d", config->ap_scan); } else if (os_strncmp(pos, "fast_reauth=", 12) == 0) { config->fast_reauth = atoi(pos + 12); wpa_printf(MSG_DEBUG, "fast_reauth=%d", config->fast_reauth); } else if (os_strncmp(pos, "opensc_engine_path=", 19) == 0) { os_free(config->opensc_engine_path); config->opensc_engine_path = os_strdup(pos + 19); wpa_printf(MSG_DEBUG, "opensc_engine_path='%s'", config->opensc_engine_path); } else if (os_strncmp(pos, "pkcs11_engine_path=", 19) == 0) { os_free(config->pkcs11_engine_path); config->pkcs11_engine_path = os_strdup(pos + 19); wpa_printf(MSG_DEBUG, "pkcs11_engine_path='%s'", config->pkcs11_engine_path); } else if (os_strncmp(pos, "pkcs11_module_path=", 19) == 0) { os_free(config->pkcs11_module_path); config->pkcs11_module_path = os_strdup(pos + 19); wpa_printf(MSG_DEBUG, "pkcs11_module_path='%s'", config->pkcs11_module_path); } else if (os_strncmp(pos, "driver_param=", 13) == 0) { os_free(config->driver_param); config->driver_param = os_strdup(pos + 13); wpa_printf(MSG_DEBUG, "driver_param='%s'", config->driver_param); } else if (os_strncmp(pos, "dot11RSNAConfigPMKLifetime=", 27) == 0) { config->dot11RSNAConfigPMKLifetime = atoi(pos + 27); wpa_printf(MSG_DEBUG, "dot11RSNAConfigPMKLifetime=%d", config->dot11RSNAConfigPMKLifetime); } else if (os_strncmp(pos, "dot11RSNAConfigPMKReauthThreshold=", 34) == 0) { config->dot11RSNAConfigPMKReauthThreshold = atoi(pos + 34); wpa_printf(MSG_DEBUG, "dot11RSNAConfigPMKReauthThreshold=%d", config->dot11RSNAConfigPMKReauthThreshold); } else if (os_strncmp(pos, "dot11RSNAConfigSATimeout=", 25) == 0) { config->dot11RSNAConfigSATimeout = atoi(pos + 25); wpa_printf(MSG_DEBUG, "dot11RSNAConfigSATimeout=%d", config->dot11RSNAConfigSATimeout); } else if (os_strncmp(pos, "update_config=", 14) == 0) { config->update_config = atoi(pos + 14); wpa_printf(MSG_DEBUG, "update_config=%d", config->update_config); } else if (os_strncmp(pos, "load_dynamic_eap=", 17) == 0) { char *so = pos + 17; int ret; wpa_printf(MSG_DEBUG, "load_dynamic_eap=%s", so); ret = eap_peer_method_load(so); if (ret == -2) { wpa_printf(MSG_DEBUG, "This EAP type was " "already loaded - not reloading."); } else if (ret) { wpa_printf(MSG_ERROR, "Line %d: Failed to " "load dynamic EAP method '%s'.", line, so); errors++; } } else { wpa_printf(MSG_ERROR, "Line %d: Invalid configuration " "line '%s'.", line, pos); errors++; continue; } } fclose(f); config->ssid = head; wpa_config_debug_dump_networks(config); #ifndef WPA_IGNORE_CONFIG_ERRORS if (errors) { wpa_config_free(config); config = NULL; head = NULL; } #endif return config; }
static struct wpa_priv_interface * wpa_priv_interface_init(const char *dir, const char *params) { struct wpa_priv_interface *iface; char *pos; size_t len; struct sockaddr_un addr; int i; pos = os_strchr(params, ':'); if (pos == NULL) return NULL; iface = os_zalloc(sizeof(*iface)); if (iface == NULL) return NULL; iface->fd = -1; len = pos - params; iface->driver_name = dup_binstr(params, len); if (iface->driver_name == NULL) { wpa_priv_interface_deinit(iface); return NULL; } for (i = 0; wpa_drivers[i]; i++) { if (os_strcmp(iface->driver_name, wpa_drivers[i]->name) == 0) { iface->driver = wpa_drivers[i]; break; } } if (iface->driver == NULL) { wpa_printf(MSG_ERROR, "Unsupported driver '%s'", iface->driver_name); wpa_priv_interface_deinit(iface); return NULL; } pos++; iface->ifname = os_strdup(pos); if (iface->ifname == NULL) { wpa_priv_interface_deinit(iface); return NULL; } len = os_strlen(dir) + 1 + os_strlen(iface->ifname); iface->sock_name = os_malloc(len + 1); if (iface->sock_name == NULL) { wpa_priv_interface_deinit(iface); return NULL; } os_snprintf(iface->sock_name, len + 1, "%s/%s", dir, iface->ifname); if (os_strlen(iface->sock_name) >= sizeof(addr.sun_path)) { wpa_priv_interface_deinit(iface); return NULL; } iface->fd = socket(PF_UNIX, SOCK_DGRAM, 0); if (iface->fd < 0) { wpa_printf(MSG_ERROR, "socket(PF_UNIX): %s", strerror(errno)); wpa_priv_interface_deinit(iface); return NULL; } os_memset(&addr, 0, sizeof(addr)); addr.sun_family = AF_UNIX; os_strlcpy(addr.sun_path, iface->sock_name, sizeof(addr.sun_path)); if (bind(iface->fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) { wpa_printf(MSG_DEBUG, "bind(PF_UNIX) failed: %s", strerror(errno)); if (connect(iface->fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) { wpa_printf(MSG_DEBUG, "Socket exists, but does not " "allow connections - assuming it was " "leftover from forced program termination"); if (unlink(iface->sock_name) < 0) { wpa_printf(MSG_ERROR, "Could not unlink existing ctrl_iface socket '%s': %s", iface->sock_name, strerror(errno)); goto fail; } if (bind(iface->fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) { wpa_printf(MSG_ERROR, "wpa-priv-iface-init: bind(PF_UNIX): %s", strerror(errno)); goto fail; } wpa_printf(MSG_DEBUG, "Successfully replaced leftover " "socket '%s'", iface->sock_name); } else { wpa_printf(MSG_INFO, "Socket exists and seems to be " "in use - cannot override it"); wpa_printf(MSG_INFO, "Delete '%s' manually if it is " "not used anymore", iface->sock_name); goto fail; } } if (chmod(iface->sock_name, S_IRWXU | S_IRWXG | S_IRWXO) < 0) { wpa_printf(MSG_ERROR, "chmod: %s", strerror(errno)); goto fail; } eloop_register_read_sock(iface->fd, wpa_priv_receive, iface, NULL); return iface; fail: wpa_priv_interface_deinit(iface); return NULL; }
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 int wpa_supplicant_ctrl_iface_ctrl_rsp(struct wpa_supplicant *wpa_s, char *rsp) { #ifdef IEEE8021X_EAPOL char *pos, *id_pos; int id; struct wpa_ssid *ssid; pos = os_strchr(rsp, '-'); if (pos == NULL) return -1; *pos++ = '\0'; id_pos = pos; pos = os_strchr(pos, ':'); if (pos == NULL) return -1; *pos++ = '\0'; id = atoi(id_pos); wpa_printf(MSG_DEBUG, "CTRL_IFACE: field=%s id=%d", rsp, id); wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value", (u8 *) pos, os_strlen(pos)); ssid = wpa_config_get_network(wpa_s->conf, id); if (ssid == NULL) { wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d " "to update", id); return -1; } if (os_strcmp(rsp, "IDENTITY") == 0) { os_free(ssid->identity); ssid->identity = (u8 *) os_strdup(pos); ssid->identity_len = os_strlen(pos); ssid->pending_req_identity = 0; if (ssid == wpa_s->current_ssid) wpa_s->reassociate = 1; } else if (os_strcmp(rsp, "PASSWORD") == 0) { os_free(ssid->password); ssid->password = (u8 *) os_strdup(pos); ssid->password_len = os_strlen(pos); ssid->pending_req_password = 0; if (ssid == wpa_s->current_ssid) wpa_s->reassociate = 1; } else if (os_strcmp(rsp, "NEW_PASSWORD") == 0) { os_free(ssid->new_password); ssid->new_password = (u8 *) os_strdup(pos); ssid->new_password_len = os_strlen(pos); ssid->pending_req_new_password = 0; if (ssid == wpa_s->current_ssid) wpa_s->reassociate = 1; } else if (os_strcmp(rsp, "PIN") == 0) { os_free(ssid->pin); ssid->pin = os_strdup(pos); ssid->pending_req_pin = 0; if (ssid == wpa_s->current_ssid) wpa_s->reassociate = 1; } else if (os_strcmp(rsp, "OTP") == 0) { os_free(ssid->otp); ssid->otp = (u8 *) os_strdup(pos); ssid->otp_len = os_strlen(pos); os_free(ssid->pending_req_otp); ssid->pending_req_otp = NULL; ssid->pending_req_otp_len = 0; } else if (os_strcmp(rsp, "PASSPHRASE") == 0) { os_free(ssid->private_key_passwd); ssid->private_key_passwd = (u8 *) os_strdup(pos); ssid->pending_req_passphrase = 0; if (ssid == wpa_s->current_ssid) wpa_s->reassociate = 1; } else { wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown field '%s'", rsp); return -1; } return 0; #else /* IEEE8021X_EAPOL */ wpa_printf(MSG_DEBUG, "CTRL_IFACE: 802.1X not included"); return -1; #endif /* IEEE8021X_EAPOL */ }
static int eap_wsc_new_ap_settings(struct wps_credential *cred, const char *params) { const char *pos, *end; size_t len; os_memset(cred, 0, sizeof(*cred)); pos = os_strstr(params, "new_ssid="); if (pos == NULL) return 0; pos += 9; end = os_strchr(pos, ' '); if (end == NULL) len = os_strlen(pos); else len = end - pos; if ((len & 1) || len > 2 * sizeof(cred->ssid) || hexstr2bin(pos, cred->ssid, len / 2)) { wpa_printf(MSG_DEBUG, "EAP-WSC: Invalid new_ssid"); return -1; } cred->ssid_len = len / 2; pos = os_strstr(params, "new_auth="); if (pos == NULL) { wpa_printf(MSG_DEBUG, "EAP-WSC: Missing new_auth"); return -1; } if (os_strncmp(pos + 9, "OPEN", 4) == 0) cred->auth_type = WPS_AUTH_OPEN; else if (os_strncmp(pos + 9, "WPAPSK", 6) == 0) cred->auth_type = WPS_AUTH_WPAPSK; else if (os_strncmp(pos + 9, "WPA2PSK", 7) == 0) cred->auth_type = WPS_AUTH_WPA2PSK; else { wpa_printf(MSG_DEBUG, "EAP-WSC: Unknown new_auth"); return -1; } pos = os_strstr(params, "new_encr="); if (pos == NULL) { wpa_printf(MSG_DEBUG, "EAP-WSC: Missing new_encr"); return -1; } if (os_strncmp(pos + 9, "NONE", 4) == 0) cred->encr_type = WPS_ENCR_NONE; #ifdef CONFIG_TESTING_OPTIONS else if (os_strncmp(pos + 9, "WEP", 3) == 0) cred->encr_type = WPS_ENCR_WEP; #endif /* CONFIG_TESTING_OPTIONS */ else if (os_strncmp(pos + 9, "TKIP", 4) == 0) cred->encr_type = WPS_ENCR_TKIP; else if (os_strncmp(pos + 9, "CCMP", 4) == 0) cred->encr_type = WPS_ENCR_AES; else { wpa_printf(MSG_DEBUG, "EAP-WSC: Unknown new_encr"); return -1; } pos = os_strstr(params, "new_key="); if (pos == NULL) return 0; pos += 8; end = os_strchr(pos, ' '); if (end == NULL) len = os_strlen(pos); else len = end - pos; if ((len & 1) || len > 2 * sizeof(cred->key) || hexstr2bin(pos, cred->key, len / 2)) { wpa_printf(MSG_DEBUG, "EAP-WSC: Invalid new_key"); return -1; } cred->key_len = len / 2; return 1; }
static int wpa_supplicant_ctrl_iface_get_capability( struct wpa_supplicant *wpa_s, const char *_field, char *buf, size_t buflen) { struct wpa_driver_capa capa; int res, first = 1, ret; char *pos, *end, *strict; char field[30]; /* Determine whether or not strict checking was requested */ os_snprintf(field, sizeof(field), "%s", _field); field[sizeof(field) - 1] = '\0'; strict = os_strchr(field, ' '); if (strict != NULL) { *strict++ = '\0'; if (os_strcmp(strict, "strict") != 0) return -1; } wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CAPABILITY '%s' %s", field, strict ? strict : ""); if (os_strcmp(field, "eap") == 0) { return eap_get_names(buf, buflen); } res = wpa_drv_get_capa(wpa_s, &capa); pos = buf; end = pos + buflen; if (os_strcmp(field, "pairwise") == 0) { if (res < 0) { if (strict) return 0; ret = os_snprintf(buf, buflen, "CCMP TKIP NONE"); if (ret < 0 || (size_t) ret >= buflen) return -1; return ret; } if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) { ret = os_snprintf(pos, end - pos, "%sCCMP", first ? "" : " "); if (ret < 0 || ret >= end - pos) return pos - buf; pos += ret; first = 0; } if (capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) { ret = os_snprintf(pos, end - pos, "%sTKIP", first ? "" : " "); if (ret < 0 || ret >= end - pos) return pos - buf; pos += ret; first = 0; } if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) { ret = os_snprintf(pos, end - pos, "%sNONE", first ? "" : " "); if (ret < 0 || ret >= end - pos) return pos - buf; pos += ret; first = 0; } return pos - buf; } if (os_strcmp(field, "group") == 0) { if (res < 0) { if (strict) return 0; ret = os_snprintf(buf, buflen, "CCMP TKIP WEP104 WEP40"); if (ret < 0 || (size_t) ret >= buflen) return -1; return ret; } if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) { ret = os_snprintf(pos, end - pos, "%sCCMP", first ? "" : " "); if (ret < 0 || ret >= end - pos) return pos - buf; pos += ret; first = 0; } if (capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) { ret = os_snprintf(pos, end - pos, "%sTKIP", first ? "" : " "); if (ret < 0 || ret >= end - pos) return pos - buf; pos += ret; first = 0; } if (capa.enc & WPA_DRIVER_CAPA_ENC_WEP104) { ret = os_snprintf(pos, end - pos, "%sWEP104", first ? "" : " "); if (ret < 0 || ret >= end - pos) return pos - buf; pos += ret; first = 0; } if (capa.enc & WPA_DRIVER_CAPA_ENC_WEP40) { ret = os_snprintf(pos, end - pos, "%sWEP40", first ? "" : " "); if (ret < 0 || ret >= end - pos) return pos - buf; pos += ret; first = 0; } return pos - buf; } if (os_strcmp(field, "key_mgmt") == 0) { if (res < 0) { if (strict) return 0; ret = os_snprintf(buf, buflen, "WPA-PSK WPA-EAP " "IEEE8021X WPA-NONE NONE"); if (ret < 0 || (size_t) ret >= buflen) return -1; return ret; } ret = os_snprintf(pos, end - pos, "NONE IEEE8021X"); if (ret < 0 || ret >= end - pos) return pos - buf; pos += ret; if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA | WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) { ret = os_snprintf(pos, end - pos, " WPA-EAP"); if (ret < 0 || ret >= end - pos) return pos - buf; pos += ret; } if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK | WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) { ret = os_snprintf(pos, end - pos, " WPA-PSK"); if (ret < 0 || ret >= end - pos) return pos - buf; pos += ret; } if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) { ret = os_snprintf(pos, end - pos, " WPA-NONE"); if (ret < 0 || ret >= end - pos) return pos - buf; pos += ret; } return pos - buf; } if (os_strcmp(field, "proto") == 0) { if (res < 0) { if (strict) return 0; ret = os_snprintf(buf, buflen, "RSN WPA"); if (ret < 0 || (size_t) ret >= buflen) return -1; return ret; } if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 | WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) { ret = os_snprintf(pos, end - pos, "%sRSN", first ? "" : " "); if (ret < 0 || ret >= end - pos) return pos - buf; pos += ret; first = 0; } if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA | WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) { ret = os_snprintf(pos, end - pos, "%sWPA", first ? "" : " "); if (ret < 0 || ret >= end - pos) return pos - buf; pos += ret; first = 0; } return pos - buf; } if (os_strcmp(field, "auth_alg") == 0) { if (res < 0) { if (strict) return 0; ret = os_snprintf(buf, buflen, "OPEN SHARED LEAP"); if (ret < 0 || (size_t) ret >= buflen) return -1; return ret; } if (capa.auth & (WPA_DRIVER_AUTH_OPEN)) { ret = os_snprintf(pos, end - pos, "%sOPEN", first ? "" : " "); if (ret < 0 || ret >= end - pos) return pos - buf; pos += ret; first = 0; } if (capa.auth & (WPA_DRIVER_AUTH_SHARED)) { ret = os_snprintf(pos, end - pos, "%sSHARED", first ? "" : " "); if (ret < 0 || ret >= end - pos) return pos - buf; pos += ret; first = 0; } if (capa.auth & (WPA_DRIVER_AUTH_LEAP)) { ret = os_snprintf(pos, end - pos, "%sLEAP", first ? "" : " "); if (ret < 0 || ret >= end - pos) return pos - buf; pos += ret; first = 0; } return pos - buf; } wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown GET_CAPABILITY field '%s'", field); return -1; }
/** * eap_peer_select_phase2_methods - Select phase 2 EAP method * @config: Pointer to the network configuration * @prefix: 'phase2' configuration prefix, e.g., "auth=" * @types: Buffer for returning allocated list of allowed EAP methods * @num_types: Buffer for returning number of allocated EAP methods * Returns: 0 on success, -1 on failure * * This function is used to parse EAP method list and select allowed methods * for Phase2 authentication. */ int eap_peer_select_phase2_methods(struct eap_peer_config *config, const char *prefix, struct eap_method_type **types, size_t *num_types) { char *start, *pos, *buf; struct eap_method_type *methods = NULL, *_methods; u32 method; size_t num_methods = 0, prefix_len; if (config == NULL || config->phase2 == NULL) goto get_defaults; start = buf = os_strdup(config->phase2); if (buf == NULL) return -1; prefix_len = os_strlen(prefix); while (start && *start != '\0') { int vendor; pos = os_strstr(start, prefix); if (pos == NULL) break; if (start != pos && *(pos - 1) != ' ') { start = pos + prefix_len; continue; } start = pos + prefix_len; pos = os_strchr(start, ' '); if (pos) *pos++ = '\0'; method = eap_get_phase2_type(start, &vendor); if (vendor == EAP_VENDOR_IETF && method == EAP_TYPE_NONE) { wpa_printf(MSG_ERROR, "TLS: Unsupported Phase2 EAP " "method '%s'", start); } else { num_methods++; _methods = os_realloc_array(methods, num_methods, sizeof(*methods)); if (_methods == NULL) { os_free(methods); os_free(buf); return -1; } methods = _methods; methods[num_methods - 1].vendor = vendor; methods[num_methods - 1].method = method; } start = pos; } os_free(buf); get_defaults: if (methods == NULL) methods = eap_get_phase2_types(config, &num_methods); if (methods == NULL) { wpa_printf(MSG_ERROR, "TLS: No Phase2 EAP methods available"); return -1; } wpa_hexdump(MSG_DEBUG, "TLS: Phase2 EAP types", (u8 *) methods, num_methods * sizeof(struct eap_method_type)); *types = methods; *num_types = num_methods; return 0; }
/* subscr_addr_add_url -- add address(es) for one url to subscription */ static void subscr_addr_add_url(struct subscription *s, const char *url, size_t url_len) { int alloc_len; char *scratch_mem = NULL; char *mem; char *domain_and_port; char *delim; char *path; char *domain; int port = 80; /* port to send to (default is port 80) */ struct addrinfo hints; struct addrinfo *result = NULL; struct addrinfo *rp; int rerr; /* url MUST begin with http: */ if (url_len < 7 || os_strncasecmp(url, "http://", 7)) goto fail; url += 7; url_len -= 7; /* allocate memory for the extra stuff we need */ alloc_len = 2 * (url_len + 1); scratch_mem = os_zalloc(alloc_len); if (scratch_mem == NULL) goto fail; mem = scratch_mem; os_strncpy(mem, url, url_len); wpa_printf(MSG_DEBUG, "WPS UPnP: Adding URL '%s'", mem); domain_and_port = mem; mem += 1 + os_strlen(mem); delim = os_strchr(domain_and_port, '/'); if (delim) { *delim++ = 0; /* null terminate domain and port */ path = delim; } else { path = domain_and_port + os_strlen(domain_and_port); } domain = mem; strcpy(domain, domain_and_port); delim = os_strchr(domain, ':'); if (delim) { *delim++ = 0; /* null terminate domain */ if (isdigit(*delim)) port = atol(delim); } /* * getaddrinfo does the right thing with dotted decimal notations, or * will resolve domain names. Resolving domain names will unfortunately * hang the entire program until it is resolved or it times out * internal to getaddrinfo; fortunately we think that the use of actual * domain names (vs. dotted decimal notations) should be uncommon. */ os_memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = AF_INET; /* IPv4 */ hints.ai_socktype = SOCK_STREAM; #if NO_DOMAIN_NAME_RESOLUTION /* Suppress domain name resolutions that would halt * the program for periods of time */ hints.ai_flags = AI_NUMERICHOST; #else /* Allow domain name resolution. */ hints.ai_flags = 0; #endif hints.ai_protocol = 0; /* Any protocol? */ rerr = getaddrinfo(domain, NULL /* fill in port ourselves */, &hints, &result); if (rerr) { wpa_printf(MSG_INFO, "WPS UPnP: Resolve error %d (%s) on: %s", rerr, gai_strerror(rerr), domain); goto fail; } for (rp = result; rp; rp = rp->ai_next) { struct subscr_addr *a; /* Limit no. of address to avoid denial of service attack */ if (dl_list_len(&s->addr_list) >= MAX_ADDR_PER_SUBSCRIPTION) { wpa_printf(MSG_INFO, "WPS UPnP: subscr_addr_add_url: " "Ignoring excessive addresses"); break; } a = os_zalloc(sizeof(*a) + alloc_len); if (a == NULL) continue; mem = (void *) (a + 1); a->domain_and_port = mem; strcpy(mem, domain_and_port); mem += 1 + strlen(mem); a->path = mem; if (path[0] != '/') *mem++ = '/'; strcpy(mem, path); mem += 1 + os_strlen(mem); os_memcpy(&a->saddr, rp->ai_addr, sizeof(a->saddr)); a->saddr.sin_port = htons(port); dl_list_add(&s->addr_list, &a->list); } fail: if (result) freeaddrinfo(result); os_free(scratch_mem); }
int testing_test_fail(void) { const char *func[WPA_TRACE_LEN]; size_t i, res, len; char *pos, *next; int match; if (!wpa_trace_test_fail_after) return 0; res = wpa_trace_calling_func(func, WPA_TRACE_LEN); i = 0; if (i < res && os_strcmp(func[i], __func__) == 0) i++; pos = wpa_trace_test_fail_func; match = 0; while (i < res) { int allow_skip = 1; int maybe = 0; if (*pos == '=') { allow_skip = 0; pos++; } else if (*pos == '?') { maybe = 1; pos++; } next = os_strchr(pos, ';'); if (next) len = next - pos; else len = os_strlen(pos); if (os_memcmp(pos, func[i], len) != 0) { if (maybe && next) { pos = next + 1; continue; } if (allow_skip) { i++; continue; } return 0; } if (!next) { match = 1; break; } pos = next + 1; i++; } if (!match) return 0; wpa_trace_test_fail_after--; if (wpa_trace_test_fail_after == 0) { wpa_printf(MSG_INFO, "TESTING: fail at %s", wpa_trace_test_fail_func); for (i = 0; i < res; i++) wpa_printf(MSG_INFO, "backtrace[%d] = %s", (int) i, func[i]); return 1; } return 0; }
int main(int argc, char *argv[]) { struct wpa_supplicant wpa_s; int c, ret = 1, wait_for_monitor = 0, save_config = 0; char *as_addr = "127.0.0.1"; int as_port = 1812; char *as_secret = "radius"; char *cli_addr = NULL; char *conf = NULL; int timeout = 30; char *pos; struct extra_radius_attr *p = NULL, *p1; if (os_program_init()) return -1; hostapd_logger_register_cb(hostapd_logger_cb); os_memset(&eapol_test, 0, sizeof(eapol_test)); eapol_test.connect_info = "CONNECT 11Mbps 802.11b"; os_memcpy(eapol_test.own_addr, "\x02\x00\x00\x00\x00\x01", ETH_ALEN); wpa_debug_level = 0; wpa_debug_show_keys = 1; for (;;) { c = getopt(argc, argv, "a:A:c:C:M:nN:p:r:s:St:W"); if (c < 0) break; switch (c) { case 'a': as_addr = optarg; break; case 'A': cli_addr = optarg; break; case 'c': conf = optarg; break; case 'C': eapol_test.connect_info = optarg; break; case 'M': if (hwaddr_aton(optarg, eapol_test.own_addr)) { usage(); return -1; } break; case 'n': eapol_test.no_mppe_keys++; break; case 'p': as_port = atoi(optarg); break; case 'r': eapol_test.eapol_test_num_reauths = atoi(optarg); break; case 's': as_secret = optarg; break; case 'S': save_config++; break; case 't': timeout = atoi(optarg); break; case 'W': wait_for_monitor++; break; case 'N': p1 = os_zalloc(sizeof(p1)); if (p1 == NULL) break; if (!p) eapol_test.extra_attrs = p1; else p->next = p1; p = p1; p->type = atoi(optarg); pos = os_strchr(optarg, ':'); if (pos == NULL) { p->syntax = 'n'; p->data = NULL; break; } pos++; if (pos[0] == '\0' || pos[1] != ':') { printf("Incorrect format of attribute " "specification\n"); break; } p->syntax = pos[0]; p->data = pos + 2; break; default: usage(); return -1; } } if (argc > optind && os_strcmp(argv[optind], "scard") == 0) { return scard_test(); } if (argc > optind && os_strcmp(argv[optind], "sim") == 0) { return scard_get_triplets(argc - optind - 1, &argv[optind + 1]); } if (conf == NULL) { usage(); printf("Configuration file is required.\n"); return -1; } if (eap_register_methods()) { wpa_printf(MSG_ERROR, "Failed to register EAP methods"); return -1; } if (eloop_init()) { wpa_printf(MSG_ERROR, "Failed to initialize event loop"); return -1; } os_memset(&wpa_s, 0, sizeof(wpa_s)); eapol_test.wpa_s = &wpa_s; wpa_s.conf = wpa_config_read(conf); if (wpa_s.conf == NULL) { printf("Failed to parse configuration file '%s'.\n", conf); return -1; } if (wpa_s.conf->ssid == NULL) { printf("No networks defined.\n"); return -1; } wpa_init_conf(&eapol_test, &wpa_s, as_addr, as_port, as_secret, cli_addr); wpa_s.ctrl_iface = wpa_supplicant_ctrl_iface_init(&wpa_s); if (wpa_s.ctrl_iface == NULL) { printf("Failed to initialize control interface '%s'.\n" "You may have another eapol_test process already " "running or the file was\n" "left by an unclean termination of eapol_test in " "which case you will need\n" "to manually remove this file before starting " "eapol_test again.\n", wpa_s.conf->ctrl_interface); return -1; } if (wpa_supplicant_scard_init(&wpa_s, wpa_s.conf->ssid)) return -1; if (test_eapol(&eapol_test, &wpa_s, wpa_s.conf->ssid)) return -1; if (wait_for_monitor) wpa_supplicant_ctrl_iface_wait(wpa_s.ctrl_iface); eloop_register_timeout(timeout, 0, eapol_test_timeout, &eapol_test, NULL); eloop_register_timeout(0, 0, send_eap_request_identity, &wpa_s, NULL); eloop_register_signal_terminate(eapol_test_terminate, &wpa_s); eloop_register_signal_reconfig(eapol_test_terminate, &wpa_s); eloop_run(); eloop_cancel_timeout(eapol_test_timeout, &eapol_test, NULL); eloop_cancel_timeout(eapol_sm_reauth, &eapol_test, NULL); if (eapol_test_compare_pmk(&eapol_test) == 0 || eapol_test.no_mppe_keys) ret = 0; if (eapol_test.auth_timed_out) ret = -2; if (eapol_test.radius_access_reject_received) ret = -3; if (save_config) wpa_config_write(conf, wpa_s.conf); test_eapol_clean(&eapol_test, &wpa_s); eap_peer_unregister_methods(); eloop_destroy(); printf("MPPE keys OK: %d mismatch: %d\n", eapol_test.num_mppe_ok, eapol_test.num_mppe_mismatch); if (eapol_test.num_mppe_mismatch) ret = -4; if (ret) printf("FAILURE\n"); else printf("SUCCESS\n"); os_program_deinit(); return ret; }
static int cavp_rsa_sig_ver(const char *fname) { FILE *f; int ret = 0; char buf[15000], *pos, *pos2; u8 msg[200], n[512], s[512], em[512], e[512]; size_t msg_len = 0, n_len = 0, s_len = 0, em_len, e_len = 0; size_t tmp_len; char sha_alg[20]; int ok = 0; printf("CAVP RSA SigVer test vectors from %s\n", fname); f = fopen(fname, "r"); if (f == NULL) { printf("%s does not exist - cannot validate CAVP RSA SigVer test vectors\n", fname); return 0; } while (fgets(buf, sizeof(buf), f)) { pos = os_strchr(buf, '='); if (pos == NULL) continue; pos2 = pos - 1; while (pos2 >= buf && *pos2 == ' ') *pos2-- = '\0'; *pos++ = '\0'; while (*pos == ' ') *pos++ = '\0'; pos2 = os_strchr(pos, '\r'); if (!pos2) pos2 = os_strchr(pos, '\n'); if (pos2) *pos2 = '\0'; else pos2 = pos + os_strlen(pos); if (os_strcmp(buf, "SHAAlg") == 0) { os_strlcpy(sha_alg, pos, sizeof(sha_alg)); } else if (os_strcmp(buf, "Msg") == 0) { tmp_len = os_strlen(pos); if (tmp_len > sizeof(msg) * 2) { printf("Too long Msg\n"); return -1; } msg_len = tmp_len / 2; if (hexstr2bin(pos, msg, msg_len) < 0) { printf("Invalid hex string '%s'\n", pos); ret++; break; } } else if (os_strcmp(buf, "n") == 0) { tmp_len = os_strlen(pos); if (tmp_len > sizeof(n) * 2) { printf("Too long n\n"); return -1; } n_len = tmp_len / 2; if (hexstr2bin(pos, n, n_len) < 0) { printf("Invalid hex string '%s'\n", pos); ret++; break; } } else if (os_strcmp(buf, "e") == 0) { tmp_len = os_strlen(pos); if (tmp_len > sizeof(e) * 2) { printf("Too long e\n"); return -1; } e_len = tmp_len / 2; if (hexstr2bin(pos, e, e_len) < 0) { printf("Invalid hex string '%s'\n", pos); ret++; break; } } else if (os_strcmp(buf, "S") == 0) { tmp_len = os_strlen(pos); if (tmp_len > sizeof(s) * 2) { printf("Too long S\n"); return -1; } s_len = tmp_len / 2; if (hexstr2bin(pos, s, s_len) < 0) { printf("Invalid hex string '%s'\n", pos); ret++; break; } } else if (os_strncmp(buf, "EM", 2) == 0) { tmp_len = os_strlen(pos); if (tmp_len > sizeof(em) * 2) return -1; em_len = tmp_len / 2; if (hexstr2bin(pos, em, em_len) < 0) { printf("Invalid hex string '%s'\n", pos); ret++; break; } } else if (os_strcmp(buf, "Result") == 0) { const u8 *addr[1]; size_t len[1]; struct crypto_public_key *pk; int res; u8 hash[32]; size_t hash_len; const struct asn1_oid *alg; addr[0] = msg; len[0] = msg_len; if (os_strcmp(sha_alg, "SHA1") == 0) { if (sha1_vector(1, addr, len, hash) < 0) return -1; hash_len = 20; alg = &asn1_sha1_oid; } else if (os_strcmp(sha_alg, "SHA256") == 0) { if (sha256_vector(1, addr, len, hash) < 0) return -1; hash_len = 32; alg = &asn1_sha256_oid; } else { continue; } printf("\nExpected result: %s\n", pos); wpa_hexdump(MSG_INFO, "Hash(Msg)", hash, hash_len); pk = crypto_public_key_import_parts(n, n_len, e, e_len); if (pk == NULL) { printf("Failed to import public key\n"); ret++; continue; } res = pkcs1_v15_sig_ver(pk, s, s_len, alg, hash, hash_len); crypto_public_key_free(pk); if ((*pos == 'F' && !res) || (*pos != 'F' && res)) { printf("FAIL\n"); ret++; continue; } printf("PASS\n"); ok++; } } fclose(f); if (ret) printf("Test case failed\n"); else printf("%d test vectors OK\n", ok); return ret; }