bool WiFiClientSecure::verify(const char* fp, const char* url) { if (!_ssl) return false; uint8_t sha1[20]; int len = strlen(fp); int pos = 0; for (int i = 0; i < sizeof(sha1); ++i) { while (pos < len && fp[pos] == ' ') { ++pos; } if (pos > len - 2) { DEBUGV("pos:%d len:%d fingerprint too short\r\n", pos, len); return false; } uint8_t high, low; if (!parseHexNibble(fp[pos], &high) || !parseHexNibble(fp[pos+1], &low)) { DEBUGV("pos:%d len:%d invalid hex sequence: %c%c\r\n", pos, len, fp[pos], fp[pos+1]); return false; } pos += 2; sha1[i] = low | (high << 4); } if (ssl_match_fingerprint(*_ssl, sha1) != 0) { DEBUGV("fingerprint doesn't match\r\n"); return false; } //TODO: check URL against certificate return true; }
bool WiFiClientSecure::_verifyDN(const char* domain_name) { DEBUGV("domain name: '%s'\r\n", (domain_name)?domain_name:"(null)"); String domain_name_str(domain_name); domain_name_str.toLowerCase(); const char* san = nullptr; int i = 0; while ((san = ssl_get_cert_subject_alt_dnsname(*_ssl, i)) != nullptr) { String san_str(san); san_str.toLowerCase(); if (matchName(san_str, domain_name_str)) { return true; } DEBUGV("SAN %d: '%s', no match\r\n", i, san); ++i; } const char* common_name = ssl_get_cert_dn(*_ssl, SSL_X509_CERT_COMMON_NAME); String common_name_str(common_name); common_name_str.toLowerCase(); if (common_name && matchName(common_name_str, domain_name_str)) { return true; } DEBUGV("CN: '%s', no match\r\n", (common_name)?common_name:"(null)"); return false; }
bool WiFiClientSecure::verify(const char* fp, const char* domain_name) { if (!_ssl) { return false; } uint8_t sha1[20]; int len = strlen(fp); int pos = 0; for (size_t i = 0; i < sizeof(sha1); ++i) { while (pos < len && ((fp[pos] == ' ') || (fp[pos] == ':'))) { ++pos; } if (pos > len - 2) { DEBUGV("pos:%d len:%d fingerprint too short\r\n", pos, len); return false; } uint8_t high, low; if (!parseHexNibble(fp[pos], &high) || !parseHexNibble(fp[pos+1], &low)) { DEBUGV("pos:%d len:%d invalid hex sequence: %c%c\r\n", pos, len, fp[pos], fp[pos+1]); return false; } pos += 2; sha1[i] = low | (high << 4); } if (ssl_match_fingerprint(*_ssl, sha1) != 0) { DEBUGV("fingerprint doesn't match\r\n"); return false; } return _verifyDN(domain_name); }
void WiFiUDP::stopAll() { for (WiFiUDP* it = _s_first; it; it = it->_next) { DEBUGV("%s %08x %08x\n", __func__, (uint32_t) it, (uint32_t) _s_first); it->stop(); } }
bool loadObject(int type, Stream& stream, size_t size) { std::unique_ptr<uint8_t[]> buf(new uint8_t[size]); if (!buf.get()) { DEBUGV("loadObject: failed to allocate memory\n"); return false; } size_t cb = stream.readBytes(buf.get(), size); if (cb != size) { DEBUGV("loadObject: reading %u bytes, got %u\n", size, cb); return false; } return loadObject(type, buf.get(), size); }
void WiFiUDP::stopAll() { for (WiFiUDP* it = _s_first; it; it = it->_next) { DEBUGV("%s %p %p\n", __func__, it, _s_first); it->stop(); } }
void WiFiUDP::stopAllExcept(WiFiUDP * exC) { for (WiFiUDP* it = _s_first; it; it = it->_next) { if (it->_ctx != exC->_ctx) { DEBUGV("%s %08x %08x\n", __func__, (uint32_t) it, (uint32_t) _s_first); it->stop(); } } }
void WiFiUDP::stopAllExcept(WiFiUDP * exC) { for (WiFiUDP* it = _s_first; it; it = it->_next) { if (it->_ctx != exC->_ctx) { DEBUGV("%s %p %p\n", __func__, it, _s_first); it->stop(); } } }
int32_t spiffs_hal_erase(uint32_t addr, uint32_t size) { if ((size & (SPI_FLASH_SEC_SIZE - 1)) != 0 || (addr & (SPI_FLASH_SEC_SIZE - 1)) != 0) { DEBUGV("_spif_erase called with addr=%x, size=%d\r\n", addr, size); abort(); } const uint32_t sector = addr / SPI_FLASH_SEC_SIZE; const uint32_t sectorCount = size / SPI_FLASH_SEC_SIZE; for (uint32_t i = 0; i < sectorCount; ++i) { optimistic_yield(10000); if (!ESP.flashEraseSector(sector + i)) { DEBUGV("_spif_erase addr=%x size=%d i=%d\r\n", addr, size, i); return SPIFFS_ERR_INTERNAL; } } return SPIFFS_OK; }
/** * WPS callback * @param status wps_cb_status */ void wifi_wps_status_cb(wps_cb_status status) { DEBUGV("wps cb status: %d\r\n", status); switch(status) { case WPS_CB_ST_SUCCESS: if(!wifi_wps_disable()) { DEBUGV("wps disable failed\n"); } wifi_station_connect(); break; case WPS_CB_ST_FAILED: DEBUGV("wps FAILED\n"); break; case WPS_CB_ST_TIMEOUT: DEBUGV("wps TIMEOUT\n"); break; case WPS_CB_ST_WEP: DEBUGV("wps WEP\n"); break; case WPS_CB_ST_UNK: DEBUGV("wps UNKNOWN\n"); if(!wifi_wps_disable()) { DEBUGV("wps disable failed\n"); } break; } // TODO user function to get status esp_schedule(); // resume the beginWPSConfig function }
void ESP8266WiFiClass::_eventCallback(void* arg) { System_Event_t* event = reinterpret_cast<System_Event_t*>(arg); DEBUGV("wifi evt: %d\r\n", event->event); if (event->event == EVENT_STAMODE_DISCONNECTED) { WiFiClient::stopAll(); } }
int8_t WiFiServer::_accept(tcp_pcb* apcb, int8_t err) { DEBUGV("WS:ac\r\n"); ClientContext* client = new ClientContext(apcb, &WiFiServer::_s_discard, this); _unclaimed = slist_append_tail(_unclaimed, client); tcp_accepted(_pcb); // printf("WiFiServer::_accept\r\n"); return ERR_OK; }
bool loadObject(int type, const uint8_t* data, size_t size) { int rc = ssl_obj_memory_load(_ssl_ctx, type, data, static_cast<int>(size), nullptr); if (rc != SSL_OK) { DEBUGV("loadObject: ssl_obj_memory_load returned %d\n", rc); return false; } return true; }
int32_t spiffs_hal_read(uint32_t addr, uint32_t size, uint8_t *dst) { optimistic_yield(10000); uint32_t result = SPIFFS_OK; uint32_t alignedBegin = (addr + 3) & (~3); uint32_t alignedEnd = (addr + size) & (~3); if (alignedEnd < alignedBegin) { alignedEnd = alignedBegin; } if (addr < alignedBegin) { uint32_t nb = alignedBegin - addr; uint32_t tmp; if (!ESP.flashRead(alignedBegin - 4, &tmp, 4)) { DEBUGV("_spif_read(%d) addr=%x size=%x ab=%x ae=%x\r\n", __LINE__, addr, size, alignedBegin, alignedEnd); return SPIFFS_ERR_INTERNAL; } memcpy(dst, &tmp + 4 - nb, nb); } if (alignedEnd != alignedBegin) { if (!ESP.flashRead(alignedBegin, (uint32_t*) (dst + alignedBegin - addr), alignedEnd - alignedBegin)) { DEBUGV("_spif_read(%d) addr=%x size=%x ab=%x ae=%x\r\n", __LINE__, addr, size, alignedBegin, alignedEnd); return SPIFFS_ERR_INTERNAL; } } if (addr + size > alignedEnd) { uint32_t nb = addr + size - alignedEnd; uint32_t tmp; if (!ESP.flashRead(alignedEnd, &tmp, 4)) { DEBUGV("_spif_read(%d) addr=%x size=%x ab=%x ae=%x\r\n", __LINE__, addr, size, alignedBegin, alignedEnd); return SPIFFS_ERR_INTERNAL; } memcpy(dst + size - nb, &tmp, nb); } return result; }
void ESP8266WiFiClass::softAP(const char* ssid, const char* passphrase, int channel, int ssid_hidden) { _useApMode = true; if(_useClientMode) { // turn on AP+STA mode _mode(WIFI_AP_STA); } else { // turn on STA mode _mode(WIFI_AP); } if(!ssid || *ssid == 0 || strlen(ssid) > 31) { // fail SSID too long or missing! return; } if(passphrase && strlen(passphrase) > 63) { // fail passphrase to long! return; } struct softap_config conf; wifi_softap_get_config(&conf); strcpy(reinterpret_cast<char*>(conf.ssid), ssid); conf.channel = channel; conf.ssid_len = strlen(ssid); conf.ssid_hidden = ssid_hidden; conf.max_connection = 4; conf.beacon_interval = 100; if (!passphrase || strlen(passphrase) == 0) { conf.authmode = AUTH_OPEN; *conf.password = 0; } else { conf.authmode = AUTH_WPA2_PSK; strcpy(reinterpret_cast<char*>(conf.password), passphrase); } struct softap_config conf_current; wifi_softap_get_config(&conf_current); if (softap_config_equal(conf, conf_current)) { DEBUGV("softap config unchanged"); return; } ETS_UART_INTR_DISABLE(); if (_persistent) wifi_softap_set_config(&conf); else wifi_softap_set_config_current(&conf); ETS_UART_INTR_ENABLE(); }
bool ESP8266WiFiClass::beginWPSConfig(void) { _useClientMode = true; if(_useApMode) { // turn on AP+STA mode mode(WIFI_AP_STA); } else { // turn on STA mode mode(WIFI_STA); } disconnect(); DEBUGV("wps begin\n"); if(!wifi_wps_disable()) { DEBUGV("wps disable faild\n"); return false; } // so far only WPS_TYPE_PBC is supported (SDK 1.2.0) if(!wifi_wps_enable(WPS_TYPE_PBC)) { DEBUGV("wps enable faild\n"); return false; } if(!wifi_set_wps_cb(&wifi_wps_status_cb)) { DEBUGV("wps cb faild\n"); return false; } if(!wifi_wps_start()) { DEBUGV("wps start faild\n"); return false; } esp_yield(); // will return here when wifi_wps_status_cb fires return true; }
uint64_t *exec_behaviour( uint64_t *message_ptr ) { buffer_ptr = &buffer_pool_ptr->ring[ ++idx & RING_ENTRY_MASK ].buffer; // Receive message from socket buffer_ptr->size = read( fd, buffer_ptr->data, RAW_MSG_SIZE_MAX ); buffer_ptr->data[ buffer_ptr->size ] = 0; DEBUGV( printf( "Publishing message: %s\n", buffer_to_string( buffer_ptr ) ) ); *message_ptr = ( uint64_t )buffer_ptr; return message_ptr;; }
void wifi_wps_status_cb(WPS_CB_STATUS_t status) { DEBUGV("wps cb status: %d\r\n", status); switch (status) { case WPS_CB_ST_SUCCESS: if(!wifi_wps_disable()) { DEBUGV("wps disable faild\n"); } wifi_station_connect(); break; case WPS_CB_ST_FAILED: DEBUGV("wps FAILD\n"); break; case WPS_CB_ST_TIMEOUT: DEBUGV("wps TIMEOUT\n"); break; } // todo user function to get status esp_schedule(); // resume the beginWPSConfig function }
bool WiFiClientSecure::verifyCertChain(const char* domain_name) { if (!_ssl) { return false; } int rc = ssl_verify_cert(*_ssl); if (rc != SSL_OK) { DEBUGV("ssl_verify_cert returned %d\n", rc); return false; } return _verifyDN(domain_name); }
uint64_t *exec_behaviour( uint64_t *message_ptr ) { event_ptr = ( event_t* )*message_ptr; DEBUGV( printf( "Consume message: %s\n", event_to_string( event_ptr ) ) ); if( order_ptr = event_ptr->order_ptr ) { // Existing event DEBUGV( printf( "Update existing event order\n" ) ); order_ptr->value = process_order(); } else { // New event DEBUGV( printf( "Create new event order\n" ) ); order_ptr = event_ptr->order_ptr = &order_pool_ptr->ring[ ++idx & RING_ENTRY_MASK ]; order_ptr->value = 0; } DEBUGV( printf( "Republishing message: %s\n", event_to_string( event_ptr ) ) ); *message_ptr = ( uint64_t )event_ptr; return message_ptr; }
/** * WPS config * so far only WPS_TYPE_PBC is supported (SDK 1.2.0) * @return ok */ bool ESP8266WiFiSTAClass::beginWPSConfig(void) { if(!WiFi.enableSTA(true)) { // enable STA failed return false; } disconnect(); DEBUGV("wps begin\n"); if(!wifi_wps_disable()) { DEBUGV("wps disable failed\n"); return false; } // so far only WPS_TYPE_PBC is supported (SDK 1.2.0) if(!wifi_wps_enable(WPS_TYPE_PBC)) { DEBUGV("wps enable failed\n"); return false; } if(!wifi_set_wps_cb((wps_st_cb_t) &wifi_wps_status_cb)) { DEBUGV("wps cb failed\n"); return false; } if(!wifi_wps_start()) { DEBUGV("wps start failed\n"); return false; } esp_yield(); // will return here when wifi_wps_status_cb fires return true; }
uint64_t *exec_behaviour( uint64_t *message_ptr ) { buffer_ptr = &buffer_pool_ptr->ring[ ++idx & RING_ENTRY_MASK ].buffer;; // Read next message from file buffer_ptr->size = read( fd, buffer_ptr->data, RAW_MSG_SIZE_MAX ); if( buffer_ptr->data[ buffer_ptr->size - 1 ] == '\n' ) buffer_ptr->data[ buffer_ptr->size - 1 ] = 0; else buffer_ptr->data[ buffer_ptr->size ] = 0; DEBUGV( printf( "Publishing message: %a\n", buffer_to_string( buffer_ptr ) ) ); *message_ptr = ( uint64_t )buffer_ptr; return message_ptr; }
/* Get a reply to one gtp command. Return the gtp command id, * or -1 if error. reply must have at least CMDS_SIZE bytes. * The ascii reply ends with an empty line; if the first line * contains "@size", a binary reply of size bytes follows the * empty line. @size is not standard gtp, it is only used * internally by Pachi for the genmoves command; it must be the * last parameter on the line. * *bin_size is the maximum size upon entry, actual size on return. * slave_lock is not held on either entry or exit of this function. */ static int get_reply(FILE *f, struct in_addr client, char *reply, void *bin_reply, int *bin_size) { double start = time_now(); int reply_id = -1; *reply = '\0'; if (!fgets(reply, CMDS_SIZE, f)) return -1; /* Check for binary reply. */ char *s = strchr(reply, '@'); int size = 0; if (s) size = atoi(s+1); assert(size <= *bin_size); *bin_size = size; if (DEBUGV(s, 2)) logline(&client, "<<", reply); if ((*reply == '=' || *reply == '?') && isdigit(reply[1])) reply_id = atoi(reply+1); /* Read the rest of the ascii reply */ char *line = reply + strlen(reply); while (fgets(line, reply + CMDS_SIZE - line, f) && *line != '\n') { if (DEBUGL(3)) logline(&client, "<<", line); line += strlen(line); } if (*line != '\n') return -1; /* Read the binary reply if any. */ int len; while (size && (len = fread(bin_reply, 1, size, f)) > 0) { bin_reply = (char *)bin_reply + len; size -= len; } if (*bin_size && DEBUGVV(2)) { char buf[1024]; snprintf(buf, sizeof(buf), "read reply %d+%d bytes in %.4fms\n", (int)strlen(reply), *bin_size, (time_now() - start)*1000); logline(&client, "= ", buf); } return size ? -1 : reply_id; }
WiFiClient WiFiServer::available(byte* status) { static uint32_t lastPollTime = 0; if (_unclaimed) { WiFiClient result(_unclaimed); _unclaimed = _unclaimed->next(); DEBUGV("WS:av\r\n"); return result; } if (lastPollTime > esp_micros_at_task_start()) yield(); lastPollTime = micros(); return WiFiClient(); }
/* Send the gtp command to_send and get a reply from the slave machine. * Write the reply in buf which must have at least CMDS_SIZE bytes. * If *bin_size > 0, send bin_buf after the gtp command. * Return any binary reply in bin_buf and set its size in bin_size. * bin_buf is private to the slave and need not be copied. * Return the gtp command id, or -1 if error. * slave_lock is held on both entry and exit of this function. */ static int send_command(char *to_send, void *bin_buf, int *bin_size, FILE *f, struct slave_state *sstate, char *buf) { assert(to_send && gtp_cmd && bin_buf && bin_size); strncpy(buf, to_send, CMDS_SIZE); bool resend = to_send != gtp_cmd; pthread_mutex_unlock(&slave_lock); if (DEBUGL(1) && resend) logline(&sstate->client, "? ", to_send == gtp_cmds ? "resend all\n" : "partial resend\n"); double start = time_now(); fputs(buf, f); if (*bin_size) fwrite(bin_buf, 1, *bin_size, f); fflush(f); if (DEBUGV(strchr(buf, '@'), 2)) { double ms = (time_now() - start) * 1000.0; if (!DEBUGL(3)) { char *s = strchr(buf, '\n'); if (s) s[1] = '\0'; } logline(&sstate->client, ">>", buf); if (*bin_size) { char b[1024]; snprintf(b, sizeof(b), "sent cmd %d+%d bytes in %.4fms\n", (int)strlen(buf), *bin_size, ms); logline(&sstate->client, "= ", b); } } /* Reuse the buffers for the reply. */ *bin_size = sstate->max_buf_size; int reply_id = get_reply(f, sstate->client, buf, bin_buf, bin_size); pthread_mutex_lock(&slave_lock); return reply_id; }
int _readAll() { if (!_ssl) return 0; optimistic_yield(100); uint8_t* data; int rc = ssl_read(_ssl, &data); if (rc <= 0) { if (rc < SSL_OK && rc != SSL_CLOSE_NOTIFY && rc != SSL_ERROR_CONN_LOST) { ssl_free(_ssl); _ssl = nullptr; } return 0; } DEBUGV(":wcs ra %d", rc); _read_ptr = data; _available = rc; return _available; }
bool WiFiClientSecure::verify(const char* fp, const char* domain_name) { if (!_ssl) return false; uint8_t sha1[20]; int len = strlen(fp); int pos = 0; for (size_t i = 0; i < sizeof(sha1); ++i) { while (pos < len && ((fp[pos] == ' ') || (fp[pos] == ':'))) { ++pos; } if (pos > len - 2) { DEBUGV("pos:%d len:%d fingerprint too short\r\n", pos, len); return false; } uint8_t high, low; if (!parseHexNibble(fp[pos], &high) || !parseHexNibble(fp[pos+1], &low)) { DEBUGV("pos:%d len:%d invalid hex sequence: %c%c\r\n", pos, len, fp[pos], fp[pos+1]); return false; } pos += 2; sha1[i] = low | (high << 4); } if (ssl_match_fingerprint(*_ssl, sha1) != 0) { DEBUGV("fingerprint doesn't match\r\n"); return false; } DEBUGV("domain name: '%s'\r\n", (domain_name)?domain_name:"(null)"); String domain_name_str(domain_name); domain_name_str.toLowerCase(); const char* san = NULL; int i = 0; while((san = ssl_get_cert_subject_alt_dnsname(*_ssl, i)) != NULL) { if (matchName(String(san), domain_name_str)) { return true; } DEBUGV("SAN %d: '%s', no match\r\n", i, san); ++i; } const char* common_name = ssl_get_cert_dn(*_ssl, SSL_X509_CERT_COMMON_NAME); if (common_name && matchName(String(common_name), domain_name_str)) { return true; } DEBUGV("CN: '%s', no match\r\n", (common_name)?common_name:"(null)"); return false; }
int WiFiClient::connect(IPAddress ip, uint16_t port) { ip_addr_t addr; addr.addr = ip; if (_client) stop(); // if the default interface is down, tcp_connect exits early without // ever calling tcp_err // http://lists.gnu.org/archive/html/lwip-devel/2010-05/msg00001.html netif* interface = ip_route(&addr); if (!interface) { DEBUGV("no route to host\r\n"); return 0; } tcp_pcb* pcb = tcp_new(); if (!pcb) return 0; if (_localPort > 0) { pcb->local_port = _localPort++; } tcp_arg(pcb, this); tcp_err(pcb, &WiFiClient::_s_err); tcp_connect(pcb, &addr, port, reinterpret_cast<tcp_connected_fn>(&WiFiClient::_s_connected)); esp_yield(); if (_client) return 1; // if tcp_error was called, pcb has already been destroyed. // tcp_abort(pcb); return 0; }
/** * Start Wifi connection * if passphrase is set the most secure supported mode will be automatically selected * @param ssid const char* Pointer to the SSID string. * @param passphrase const char * Optional. Passphrase. Valid characters in a passphrase must be between ASCII 32-126 (decimal). * @param bssid uint8_t[6] Optional. BSSID / MAC of AP * @param channel Optional. Channel of AP * @param connect Optional. call connect * @return */ wl_status_t ESP8266WiFiSTAClass::begin(const char* ssid, const char *passphrase, int32_t channel, const uint8_t* bssid, bool connect) { if(!WiFi.enableSTA(true)) { // enable STA failed return WL_CONNECT_FAILED; } if(!ssid || *ssid == 0x00 || strlen(ssid) > 32) { // fail SSID too long or missing! return WL_CONNECT_FAILED; } int passphraseLen = passphrase == nullptr ? 0 : strlen(passphrase); if(passphraseLen > 64) { // fail passphrase too long! return WL_CONNECT_FAILED; } struct station_config conf; conf.threshold.authmode = (passphraseLen == 0) ? AUTH_OPEN : (_useInsecureWEP ? AUTH_WEP : AUTH_WPA_PSK); if(strlen(ssid) == 32) memcpy(reinterpret_cast<char*>(conf.ssid), ssid, 32); //copied in without null term else strcpy(reinterpret_cast<char*>(conf.ssid), ssid); if(passphrase) { if (passphraseLen == 64) // it's not a passphrase, is the PSK, which is copied into conf.password without null term memcpy(reinterpret_cast<char*>(conf.password), passphrase, 64); else strcpy(reinterpret_cast<char*>(conf.password), passphrase); } else { *conf.password = 0; } conf.threshold.rssi = -127; conf.open_and_wep_mode_disable = !(_useInsecureWEP || *conf.password == 0); if(bssid) { conf.bssid_set = 1; memcpy((void *) &conf.bssid[0], (void *) bssid, 6); } else { conf.bssid_set = 0; } struct station_config conf_compare; if(WiFi._persistent){ wifi_station_get_config_default(&conf_compare); } else { wifi_station_get_config(&conf_compare); } if(sta_config_equal(conf_compare, conf)) { DEBUGV("sta config unchanged"); } else { ETS_UART_INTR_DISABLE(); if(WiFi._persistent) { wifi_station_set_config(&conf); } else { wifi_station_set_config_current(&conf); } ETS_UART_INTR_ENABLE(); } ETS_UART_INTR_DISABLE(); if(connect) { wifi_station_connect(); } ETS_UART_INTR_ENABLE(); if(channel > 0 && channel <= 13) { wifi_set_channel(channel); } if(!_useStaticIp) { wifi_station_dhcpc_start(); } return status(); }
void WiFiClient::_err(int8_t err) { DEBUGV(":err %d\r\n", err); esp_schedule(); }