mirror of
https://github.com/warmcat/libwebsockets.git
synced 2025-03-09 00:00:04 +01:00
acme: adaptations through plat for esp32
This commit is contained in:
parent
d7b6c04aaf
commit
d58d749b30
21 changed files with 830 additions and 274 deletions
|
@ -19,12 +19,12 @@ endif
|
|||
build:
|
||||
cd $(COMPONENT_BUILD_DIR) ; \
|
||||
echo "doing lws cmake" ; \
|
||||
cmake $(COMPONENT_PATH) -DLWS_C_FLAGS="$(CFLAGS) " \
|
||||
cmake $(COMPONENT_PATH) -DLWS_C_FLAGS="$(CFLAGS) -DNDEBUG=1" \
|
||||
-DIDF_PATH=$(IDF_PATH) \
|
||||
-DCROSS_PATH=$(CROSS_PATH) \
|
||||
-DBUILD_DIR_BASE=$(BUILD_DIR_BASE) \
|
||||
-DCMAKE_TOOLCHAIN_FILE=$(COMPONENT_PATH)/contrib/cross-esp32.cmake \
|
||||
-DCMAKE_BUILD_TYPE=DEBUG \
|
||||
-DCMAKE_BUILD_TYPE=RELEASE \
|
||||
-DLWS_MBEDTLS_INCLUDE_DIRS="${IDF_PATH}/components/openssl/include;${IDF_PATH}/components/mbedtls/include;${IDF_PATH}/components/mbedtls/port/include" \
|
||||
-DLWS_WITH_STATS=0 \
|
||||
-DLWS_WITH_HTTP2=1 \
|
||||
|
|
|
@ -52,8 +52,8 @@ static void *_realloc(void *ptr, size_t size, const char *reason)
|
|||
{
|
||||
if (size) {
|
||||
#if defined(LWS_WITH_ESP32)
|
||||
lwsl_notice("%s: size %lu: %s\n", __func__,
|
||||
(unsigned long)size, reason);
|
||||
lwsl_notice("%s: size %lu: %s (free heap %d)\n", __func__,
|
||||
(unsigned long)size, reason, (unsigned int)esp_get_free_heap_size() - (int)size);
|
||||
#else
|
||||
lwsl_debug("%s: size %lu: %s\n", __func__,
|
||||
(unsigned long)size, reason);
|
||||
|
|
|
@ -838,12 +838,12 @@ lws_create_vhost(struct lws_context *context,
|
|||
vh->log_fd = (int)LWS_INVALID_FILE;
|
||||
#endif
|
||||
if (lws_context_init_server_ssl(info, vh))
|
||||
goto bail;
|
||||
goto bail1;
|
||||
if (lws_context_init_client_ssl(info, vh))
|
||||
goto bail;
|
||||
goto bail1;
|
||||
if (lws_context_init_server(info, vh)) {
|
||||
lwsl_err("init server failed\n");
|
||||
goto bail;
|
||||
goto bail1;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
|
@ -858,12 +858,19 @@ lws_create_vhost(struct lws_context *context,
|
|||
|
||||
if (context->protocol_init_done)
|
||||
if (lws_protocol_init(context))
|
||||
goto bail;
|
||||
goto bail1;
|
||||
|
||||
return vh;
|
||||
|
||||
bail1:
|
||||
lws_vhost_destroy(vh);
|
||||
|
||||
return NULL;
|
||||
|
||||
#ifdef LWS_WITH_ACCESS_LOG
|
||||
bail:
|
||||
lws_free(vh);
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -1496,7 +1496,7 @@ lws_h2_parser(struct lws *wsi, unsigned char *in, lws_filepos_t inlen,
|
|||
h2n->inside += n;
|
||||
h2n->count += n - 1;
|
||||
|
||||
lwsl_notice("%s: count %d len %d\n", __func__, (int)h2n->count, (int)h2n->length);
|
||||
// lwsl_notice("%s: count %d len %d\n", __func__, (int)h2n->count, (int)h2n->length);
|
||||
|
||||
break;
|
||||
|
||||
|
|
|
@ -571,6 +571,8 @@ struct lws_esp32 {
|
|||
char access_pw[16];
|
||||
char hostname[32];
|
||||
char mac[20];
|
||||
char le_dns[64];
|
||||
char le_email[64];
|
||||
mdns_server_t *mdns;
|
||||
char region;
|
||||
char inet;
|
||||
|
@ -584,6 +586,8 @@ struct lws_esp32 {
|
|||
struct lws_group_member *first;
|
||||
int extant_group_members;
|
||||
|
||||
char acme;
|
||||
|
||||
volatile char button_is_down;
|
||||
};
|
||||
|
||||
|
@ -836,6 +840,45 @@ struct lws_ssl_info {
|
|||
int ret;
|
||||
};
|
||||
|
||||
enum lws_cert_update_state {
|
||||
LWS_CUS_IDLE,
|
||||
LWS_CUS_STARTING,
|
||||
LWS_CUS_SUCCESS,
|
||||
LWS_CUS_FAILED,
|
||||
|
||||
LWS_CUS_CREATE_KEYS,
|
||||
LWS_CUS_REG,
|
||||
LWS_CUS_AUTH,
|
||||
LWS_CUS_CHALLENGE,
|
||||
LWS_CUS_CREATE_REQ,
|
||||
LWS_CUS_REQ,
|
||||
LWS_CUS_CONFIRM,
|
||||
LWS_CUS_ISSUE,
|
||||
};
|
||||
|
||||
enum {
|
||||
LWS_TLS_REQ_ELEMENT_COUNTRY,
|
||||
LWS_TLS_REQ_ELEMENT_STATE,
|
||||
LWS_TLS_REQ_ELEMENT_LOCALITY,
|
||||
LWS_TLS_REQ_ELEMENT_ORGANIZATION,
|
||||
LWS_TLS_REQ_ELEMENT_COMMON_NAME,
|
||||
LWS_TLS_REQ_ELEMENT_EMAIL,
|
||||
|
||||
LWS_TLS_REQ_ELEMENT_COUNT,
|
||||
|
||||
LWS_TLS_SET_DIR_URL = LWS_TLS_REQ_ELEMENT_COUNT,
|
||||
LWS_TLS_SET_AUTH_PATH,
|
||||
LWS_TLS_SET_CERT_PATH,
|
||||
LWS_TLS_SET_KEY_PATH,
|
||||
|
||||
LWS_TLS_TOTAL_COUNT
|
||||
};
|
||||
|
||||
struct lws_acme_cert_aging_args {
|
||||
struct lws_vhost *vh;
|
||||
const char *element_overrides[LWS_TLS_TOTAL_COUNT]; /* NULL = use pvo */
|
||||
};
|
||||
|
||||
/*
|
||||
* NOTE: These public enums are part of the abi. If you want to add one,
|
||||
* add it at where specified so existing users are unaffected.
|
||||
|
@ -1352,14 +1395,25 @@ enum lws_callback_reasons {
|
|||
/**< When a vhost TLS cert has its expiry checked, this callback
|
||||
* is broadcast to every protocol of every vhost in case the
|
||||
* protocol wants to take some action with this information.
|
||||
* \p in is the lws_vhost and \p len is the number of days left
|
||||
* before it expires, as a (ssize_t) */
|
||||
* \p in is a pointer to a struct lws_acme_cert_aging_args,
|
||||
* and \p len is the number of days left before it expires, as
|
||||
* a (ssize_t). In the struct lws_acme_cert_aging_args, vh
|
||||
* points to the vhost the cert aging information applies to,
|
||||
* and element_overrides[] is an optional way to update information
|
||||
* from the pvos... NULL in an index means use the information from
|
||||
* from the pvo for the cert renewal, non-NULL in the array index
|
||||
* means use that pointer instead for the index. */
|
||||
LWS_CALLBACK_TIMER = 73,
|
||||
/**< When the time elapsed after a call to lws_set_timer(wsi, secs)
|
||||
* is up, the wsi will get one of these callbacks. The deadline
|
||||
* can be continuously extended into the future by later calls
|
||||
* to lws_set_timer() before the deadline expires, or cancelled by
|
||||
* lws_set_timer(wsi, -1); */
|
||||
LWS_CALLBACK_VHOST_CERT_UPDATE = 74,
|
||||
/**< When a vhost TLS cert is being updated, progress is
|
||||
* reported to the vhost in question here, including completion
|
||||
* and failure. in points to optional JSON, and len represents the
|
||||
* connection state using enum lws_cert_update_state */
|
||||
|
||||
/****** add new things just above ---^ ******/
|
||||
|
||||
|
@ -5492,6 +5546,17 @@ lws_is_ssl(struct lws *wsi);
|
|||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_is_cgi(struct lws *wsi);
|
||||
|
||||
|
||||
struct lws_wifi_scan { /* generic wlan scan item */
|
||||
struct lws_wifi_scan *next;
|
||||
char ssid[32];
|
||||
int32_t rssi; /* divide by .count to get db */
|
||||
uint8_t bssid[6];
|
||||
uint8_t count;
|
||||
uint8_t channel;
|
||||
uint8_t authmode;
|
||||
};
|
||||
|
||||
#if defined(LWS_OPENSSL_SUPPORT) && !defined(LWS_WITH_MBEDTLS)
|
||||
/**
|
||||
* lws_get_ssl() - Return wsi's SSL context structure
|
||||
|
@ -5601,23 +5666,6 @@ LWS_VISIBLE LWS_EXTERN int
|
|||
lws_tls_acme_sni_cert_create(struct lws_vhost *vhost, const char *san_a,
|
||||
const char *san_b);
|
||||
|
||||
enum {
|
||||
LWS_TLS_REQ_ELEMENT_COUNTRY,
|
||||
LWS_TLS_REQ_ELEMENT_STATE,
|
||||
LWS_TLS_REQ_ELEMENT_LOCALITY,
|
||||
LWS_TLS_REQ_ELEMENT_ORGANIZATION,
|
||||
LWS_TLS_REQ_ELEMENT_COMMON_NAME,
|
||||
LWS_TLS_REQ_ELEMENT_EMAIL,
|
||||
|
||||
LWS_TLS_REQ_ELEMENT_COUNT,
|
||||
LWS_TLS_SET_DIR_URL = LWS_TLS_REQ_ELEMENT_COUNT,
|
||||
LWS_TLS_SET_AUTH_PATH,
|
||||
LWS_TLS_SET_CERT_PATH,
|
||||
LWS_TLS_SET_KEY_PATH,
|
||||
|
||||
LWS_TLS_TOTAL_COUNT
|
||||
};
|
||||
|
||||
/**
|
||||
* lws_tls_acme_sni_csr_create() - creates a CSR and related private key PEM
|
||||
*
|
||||
|
@ -6614,31 +6662,31 @@ struct lejp_ctx {
|
|||
/* arrays */
|
||||
|
||||
struct _lejp_stack st[LEJP_MAX_DEPTH];
|
||||
unsigned short i[LEJP_MAX_INDEX_DEPTH]; /* index array */
|
||||
unsigned short wild[LEJP_MAX_INDEX_DEPTH]; /* index array */
|
||||
uint16_t i[LEJP_MAX_INDEX_DEPTH]; /* index array */
|
||||
uint16_t wild[LEJP_MAX_INDEX_DEPTH]; /* index array */
|
||||
char path[LEJP_MAX_PATH];
|
||||
char buf[LEJP_STRING_CHUNK];
|
||||
|
||||
/* int */
|
||||
|
||||
unsigned int line;
|
||||
uint32_t line;
|
||||
|
||||
/* short */
|
||||
|
||||
unsigned short uni;
|
||||
uint16_t uni;
|
||||
|
||||
/* char */
|
||||
|
||||
unsigned char npos;
|
||||
unsigned char dcount;
|
||||
unsigned char f;
|
||||
unsigned char sp; /* stack head */
|
||||
unsigned char ipos; /* index stack depth */
|
||||
unsigned char ppos;
|
||||
unsigned char count_paths;
|
||||
unsigned char path_match;
|
||||
unsigned char path_match_len;
|
||||
unsigned char wildcount;
|
||||
uint8_t npos;
|
||||
uint8_t dcount;
|
||||
uint8_t f;
|
||||
uint8_t sp; /* stack head */
|
||||
uint8_t ipos; /* index stack depth */
|
||||
uint8_t ppos;
|
||||
uint8_t count_paths;
|
||||
uint8_t path_match;
|
||||
uint8_t path_match_len;
|
||||
uint8_t wildcount;
|
||||
};
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
|
|
|
@ -110,7 +110,7 @@ lws_poll_listen_fd(struct lws_pollfd *fd)
|
|||
|
||||
LWS_VISIBLE void lwsl_emit_syslog(int level, const char *line)
|
||||
{
|
||||
printf("%d: %s", level, line);
|
||||
lwsl_emit_stderr(level, line);
|
||||
}
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
|
@ -709,7 +709,7 @@ static const char *gapss_str[] = {
|
|||
};
|
||||
|
||||
static romfs_t lws_esp32_romfs;
|
||||
static TimerHandle_t leds_timer, scan_timer, debounce_timer
|
||||
static TimerHandle_t leds_timer, scan_timer, debounce_timer, association_timer
|
||||
#if !defined(CONFIG_LWS_IS_FACTORY_APPLICATION)
|
||||
, mdns_timer
|
||||
#endif
|
||||
|
@ -811,6 +811,28 @@ static void lws_esp32_scan_timer_cb(TimerHandle_t th)
|
|||
lwsl_err("scan start failed %d\n", n);
|
||||
}
|
||||
|
||||
static void lws_esp32_assoc_timer_cb(TimerHandle_t th)
|
||||
{
|
||||
int n;
|
||||
|
||||
xTimerStop(association_timer, 0);
|
||||
|
||||
if (gapss == LWS_GAPSS_STAT_HAPPY) {
|
||||
lwsl_debug("%s: saw we were happy\n", __func__);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
lwsl_notice("%s: forcing rescan\n", __func__);
|
||||
|
||||
lws_gapss_to(LWS_GAPSS_SCAN);
|
||||
scan_ongoing = 0;
|
||||
n = esp_wifi_scan_start(&scan_config, false);
|
||||
if (n != ESP_OK)
|
||||
lwsl_err("scan start failed %d\n", n);
|
||||
}
|
||||
|
||||
|
||||
#if !defined(CONFIG_LWS_IS_FACTORY_APPLICATION)
|
||||
|
||||
void __attribute__(( weak ))
|
||||
|
@ -1018,7 +1040,7 @@ end_scan()
|
|||
goto passthru;
|
||||
|
||||
if (gapss != LWS_GAPSS_SCAN) {
|
||||
lwsl_notice("ignoring scan as gapss %s\n", gapss_str[gapss]);
|
||||
lwsl_info("ignoring scan as gapss %s\n", gapss_str[gapss]);
|
||||
goto passthru;
|
||||
}
|
||||
|
||||
|
@ -1029,14 +1051,14 @@ end_scan()
|
|||
!lws_esp32.ssid[3][0])
|
||||
goto passthru;
|
||||
|
||||
lwsl_notice("checking %d scan records\n", count_ap_records);
|
||||
lwsl_info("checking %d scan records\n", count_ap_records);
|
||||
|
||||
for (n = 0; n < 4; n++) {
|
||||
|
||||
if (!lws_esp32.ssid[(n + try_slot + 1) & 3][0])
|
||||
continue;
|
||||
|
||||
lwsl_notice("looking for %s\n",
|
||||
lwsl_debug("looking for %s\n",
|
||||
lws_esp32.ssid[(n + try_slot + 1) & 3]);
|
||||
|
||||
/* this ssid appears in scan results? */
|
||||
|
@ -1053,7 +1075,7 @@ end_scan()
|
|||
hit:
|
||||
m = (n + try_slot + 1) & 3;
|
||||
try_slot = m;
|
||||
lwsl_notice("Attempting connection with slot %d: %s:\n", m,
|
||||
lwsl_info("Attempting connection with slot %d: %s:\n", m,
|
||||
lws_esp32.ssid[m]);
|
||||
/* set the ssid we last tried to connect to */
|
||||
strncpy(lws_esp32.active_ssid, lws_esp32.ssid[m],
|
||||
|
@ -1068,6 +1090,8 @@ hit:
|
|||
tcpip_adapter_set_hostname(TCPIP_ADAPTER_IF_STA,
|
||||
(const char *)&config.ap.ssid[7]);
|
||||
lws_gapss_to(LWS_GAPSS_STAT);
|
||||
xTimerStop(association_timer, 0);
|
||||
xTimerStart(association_timer, 0);
|
||||
|
||||
esp_wifi_set_config(WIFI_IF_STA, &sta_config);
|
||||
esp_wifi_connect();
|
||||
|
@ -1484,6 +1508,8 @@ lws_esp32_wlan_config(void)
|
|||
};
|
||||
int n;
|
||||
|
||||
lwsl_debug("%s\n", __func__);
|
||||
|
||||
ledc_timer_config(&ledc_timer);
|
||||
|
||||
lws_set_genled(LWSESP32_GENLED__INIT);
|
||||
|
@ -1496,6 +1522,8 @@ lws_esp32_wlan_config(void)
|
|||
(TimerCallbackFunction_t)lws_esp32_scan_timer_cb);
|
||||
debounce_timer = xTimerCreate("lws_db", pdMS_TO_TICKS(100), 0, NULL,
|
||||
(TimerCallbackFunction_t)lws_esp32_debounce_timer_cb);
|
||||
association_timer = xTimerCreate("lws_assoc", pdMS_TO_TICKS(10000), 0, NULL,
|
||||
(TimerCallbackFunction_t)lws_esp32_assoc_timer_cb);
|
||||
|
||||
#if !defined(CONFIG_LWS_IS_FACTORY_APPLICATION)
|
||||
mdns_timer = xTimerCreate("lws_mdns", pdMS_TO_TICKS(5000), 0, NULL,
|
||||
|
@ -1667,13 +1695,13 @@ lws_esp32_set_creation_defaults(struct lws_context_creation_info *info)
|
|||
|
||||
info->vhost_name = "default";
|
||||
info->port = 443;
|
||||
info->fd_limit_per_thread = 30;
|
||||
info->max_http_header_pool = 16;
|
||||
info->max_http_header_data = 512;
|
||||
info->pt_serv_buf_size = 2048;
|
||||
info->fd_limit_per_thread = 16;
|
||||
info->max_http_header_pool = 5;
|
||||
info->max_http_header_data = 1024;
|
||||
info->pt_serv_buf_size = 4096;
|
||||
info->keepalive_timeout = 30;
|
||||
info->timeout_secs = 30;
|
||||
info->simultaneous_ssl_restriction = 4;
|
||||
info->simultaneous_ssl_restriction = 2;
|
||||
info->options = LWS_SERVER_OPTION_EXPLICIT_VHOSTS |
|
||||
LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
|
||||
}
|
||||
|
@ -1851,6 +1879,22 @@ fail:
|
|||
return -1;
|
||||
}
|
||||
|
||||
void
|
||||
lws_esp32_update_acme_info(void)
|
||||
{
|
||||
int n;
|
||||
|
||||
n = lws_plat_read_file("acme-email", lws_esp32.le_email,
|
||||
sizeof(lws_esp32.le_email) - 1);
|
||||
if (n >= 0)
|
||||
lws_esp32.le_email[n] = '\0';
|
||||
|
||||
n = lws_plat_read_file("acme-cn", lws_esp32.le_dns,
|
||||
sizeof(lws_esp32.le_dns) - 1);
|
||||
if (n >= 0)
|
||||
lws_esp32.le_dns[n] = '\0';
|
||||
}
|
||||
|
||||
struct lws_context *
|
||||
lws_esp32_init(struct lws_context_creation_info *info, struct lws_vhost **pvh)
|
||||
{
|
||||
|
@ -1893,6 +1937,8 @@ lws_esp32_init(struct lws_context_creation_info *info, struct lws_vhost **pvh)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
lws_esp32_update_acme_info();
|
||||
|
||||
lws_esp32_selfsigned(vhost);
|
||||
wsi.context = vhost->context;
|
||||
wsi.vhost = vhost;
|
||||
|
@ -1960,16 +2006,16 @@ lws_plat_write_file(const char *filename, void *buf, int len)
|
|||
|
||||
if (nvs_open("lws-station", NVS_READWRITE, &nvh)) {
|
||||
lwsl_notice("%s: failed to open nvs\n", __func__);
|
||||
return 1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
n = nvs_set_blob(nvh, filename, buf, len);
|
||||
if (n)
|
||||
if (n >= 0)
|
||||
nvs_commit(nvh);
|
||||
|
||||
nvs_close(nvh);
|
||||
|
||||
lwsl_notice("%s: wrote %s\n", __func__, filename);
|
||||
lwsl_notice("%s: wrote %s (%d)\n", __func__, filename, n);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
@ -1985,7 +2031,7 @@ lws_plat_write_cert(struct lws_vhost *vhost, int is_key, int fd, void *buf,
|
|||
if (is_key)
|
||||
name = vhost->key_path;
|
||||
|
||||
return lws_plat_write_file(name, buf, len);
|
||||
return lws_plat_write_file(name, buf, len) < 0;
|
||||
}
|
||||
|
||||
LWS_VISIBLE int
|
||||
|
|
|
@ -1000,6 +1000,7 @@ struct lws_vhost {
|
|||
unsigned int created_vhost_protocols:1;
|
||||
unsigned int being_destroyed:1;
|
||||
unsigned int skipped_certs:1;
|
||||
unsigned int acme_challenge:1;
|
||||
|
||||
unsigned char default_protocol_index;
|
||||
unsigned char raw_protocol_index;
|
||||
|
|
|
@ -2540,10 +2540,13 @@ try_pollout:
|
|||
case LWSCM_SERVER_LISTENER:
|
||||
|
||||
#if LWS_POSIX
|
||||
/* pollin means a client has connected to us then */
|
||||
/* pollin means a client has connected to us then
|
||||
* pollout is a hack on esp32 for background accepts signalling
|
||||
* they completed
|
||||
* */
|
||||
|
||||
do {
|
||||
if (!(pollfd->revents & LWS_POLLIN) ||
|
||||
if (!(pollfd->revents & (LWS_POLLIN |LWS_POLLOUT)) ||
|
||||
!(pollfd->events & LWS_POLLIN))
|
||||
break;
|
||||
|
||||
|
|
|
@ -88,9 +88,10 @@ lws_context_init_server_ssl(struct lws_context_creation_info *info,
|
|||
|
||||
lws_tls_server_client_cert_verify_config(vhost);
|
||||
|
||||
vhost->protocols[0].callback(&wsi,
|
||||
LWS_CALLBACK_OPENSSL_LOAD_EXTRA_SERVER_VERIFY_CERTS,
|
||||
vhost->ssl_ctx, vhost, 0);
|
||||
if (vhost->protocols[0].callback(&wsi,
|
||||
LWS_CALLBACK_OPENSSL_LOAD_EXTRA_SERVER_VERIFY_CERTS,
|
||||
vhost->ssl_ctx, vhost, 0))
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (vhost->use_ssl)
|
||||
|
@ -142,6 +143,11 @@ lws_server_socket_service_ssl(struct lws *wsi, lws_sockfd_type accept_fd)
|
|||
context->simultaneous_ssl_restriction)
|
||||
/* that was the last allowed SSL connection */
|
||||
lws_gate_accepts(context, 0);
|
||||
|
||||
//lwsl_notice("%s: ssl restr %d, simul %d\n", __func__,
|
||||
// context->simultaneous_ssl_restriction,
|
||||
// context->simultaneous_ssl);
|
||||
|
||||
#if defined(LWS_WITH_STATS)
|
||||
context->updated = 1;
|
||||
#endif
|
||||
|
|
|
@ -1000,7 +1000,7 @@ completed:
|
|||
if (user_callback_handle_rxflow(wsi->protocol->callback,
|
||||
wsi, LWS_CALLBACK_COMPLETED_CLIENT_HTTP,
|
||||
wsi->user_space, NULL, 0)) {
|
||||
lwsl_debug("Completed call returned -1\n");
|
||||
lwsl_debug("%s: Completed call returned nonzero (mode %d)\n", __func__, wsi->mode);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
|
@ -213,6 +213,7 @@ lws_tls_server_vhost_backend_init(struct lws_context_creation_info *info,
|
|||
const SSL_METHOD *method = TLS_server_method();
|
||||
uint8_t *p;
|
||||
lws_filepos_t flen;
|
||||
int n;
|
||||
|
||||
vhost->ssl_ctx = SSL_CTX_new(method); /* create context */
|
||||
if (!vhost->ssl_ctx) {
|
||||
|
@ -243,10 +244,13 @@ lws_tls_server_vhost_backend_init(struct lws_context_creation_info *info,
|
|||
free(p);
|
||||
}
|
||||
|
||||
return lws_tls_server_certs_load(vhost, wsi,
|
||||
info->ssl_cert_filepath,
|
||||
info->ssl_private_key_filepath,
|
||||
NULL, 0, NULL, 0);
|
||||
n = lws_tls_server_certs_load(vhost, wsi, info->ssl_cert_filepath,
|
||||
info->ssl_private_key_filepath, NULL,
|
||||
0, NULL, 0);
|
||||
if (n)
|
||||
return n;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -284,9 +288,17 @@ enum lws_ssl_capable_status
|
|||
lws_tls_server_accept(struct lws *wsi)
|
||||
{
|
||||
union lws_tls_cert_info_results ir;
|
||||
int m, n = SSL_accept(wsi->ssl);
|
||||
int m, n;
|
||||
|
||||
n = SSL_accept(wsi->ssl);
|
||||
if (n == 1) {
|
||||
|
||||
if (strstr(wsi->vhost->name, ".invalid")) {
|
||||
lwsl_notice("%s: vhost has .invalid, rejecting accept\n", __func__);
|
||||
|
||||
return LWS_SSL_CAPABLE_ERROR;
|
||||
}
|
||||
|
||||
n = lws_tls_peer_cert_info(wsi, LWS_TLS_CERT_INFO_COMMON_NAME, &ir,
|
||||
sizeof(ir.ns.name));
|
||||
if (!n)
|
||||
|
@ -298,6 +310,8 @@ lws_tls_server_accept(struct lws *wsi)
|
|||
}
|
||||
|
||||
m = SSL_get_error(wsi->ssl, n);
|
||||
lwsl_debug("%s: %p: accept SSL_get_error %d errno %d\n", __func__,
|
||||
wsi, m, errno);
|
||||
|
||||
// mbedtls wrapper only
|
||||
if (m == SSL_ERROR_SYSCALL && errno == 11)
|
||||
|
@ -439,7 +453,7 @@ lws_tls_acme_sni_cert_create(struct lws_vhost *vhost, const char *san_a,
|
|||
uint8_t digest[32];
|
||||
struct lws_genhash_ctx hash_ctx;
|
||||
int pkey_asn1_len = 3 * 1024;
|
||||
int n, keybits = lws_plat_recommended_rsa_bits(), adj;
|
||||
int n, m, keybits = lws_plat_recommended_rsa_bits(), adj;
|
||||
|
||||
if (!buf)
|
||||
return 1;
|
||||
|
@ -522,35 +536,35 @@ lws_tls_acme_sni_cert_create(struct lws_vhost *vhost, const char *san_a,
|
|||
if (!pkey_asn1)
|
||||
goto bail2;
|
||||
|
||||
n = lws_genrsa_render_pkey_asn1(&ctx, 1, pkey_asn1, pkey_asn1_len);
|
||||
if (n < 0) {
|
||||
m = lws_genrsa_render_pkey_asn1(&ctx, 1, pkey_asn1, pkey_asn1_len);
|
||||
if (m < 0) {
|
||||
lws_free(pkey_asn1);
|
||||
goto bail2;
|
||||
}
|
||||
lwsl_debug("private key\n");
|
||||
lwsl_hexdump_level(LLL_DEBUG, pkey_asn1, n);
|
||||
|
||||
/* and to use our generated private key */
|
||||
n = SSL_CTX_use_PrivateKey_ASN1(0, vhost->ssl_ctx, pkey_asn1, n);
|
||||
lws_free(pkey_asn1);
|
||||
// lwsl_hexdump_level(LLL_DEBUG, buf, lws_ptr_diff(p, buf));
|
||||
n = SSL_CTX_use_certificate_ASN1(vhost->ssl_ctx,
|
||||
lws_ptr_diff(p, buf), buf);
|
||||
if (n != 1) {
|
||||
lwsl_notice("%s: SSL_CTX_use_PrivateKey_ASN1 failed\n",
|
||||
__func__);
|
||||
lws_free(pkey_asn1);
|
||||
lwsl_err("%s: generated cert failed to load 0x%x\n",
|
||||
__func__, -n);
|
||||
} else {
|
||||
//lwsl_debug("private key\n");
|
||||
//lwsl_hexdump_level(LLL_DEBUG, pkey_asn1, n);
|
||||
|
||||
/* and to use our generated private key */
|
||||
n = SSL_CTX_use_PrivateKey_ASN1(0, vhost->ssl_ctx, pkey_asn1, m);
|
||||
lws_free(pkey_asn1);
|
||||
if (n != 1) {
|
||||
lwsl_err("%s: SSL_CTX_use_PrivateKey_ASN1 failed\n",
|
||||
__func__);
|
||||
}
|
||||
}
|
||||
|
||||
lws_genrsa_destroy(&ctx);
|
||||
lws_jwk_destroy_genrsa_elements(&el);
|
||||
|
||||
if (n == 1) {
|
||||
lwsl_hexdump_level(LLL_DEBUG, buf, lws_ptr_diff(p, buf));
|
||||
|
||||
n = SSL_CTX_use_certificate_ASN1(vhost->ssl_ctx,
|
||||
lws_ptr_diff(p, buf), buf);
|
||||
if (n != 1)
|
||||
lwsl_notice("%s: generated cert failed to load 0x%x\n",
|
||||
__func__, -n);
|
||||
}
|
||||
|
||||
lws_free(buf);
|
||||
|
||||
return n != 1;
|
||||
|
@ -579,6 +593,8 @@ _rngf(void *context, unsigned char *buf, size_t len)
|
|||
return -1;
|
||||
}
|
||||
|
||||
static const char *x5[] = { "C", "ST", "L", "O", "CN" };
|
||||
|
||||
/*
|
||||
* CSR is output formatted as b64url(DER)
|
||||
* Private key is output as a PEM in memory
|
||||
|
@ -589,9 +605,9 @@ lws_tls_acme_sni_csr_create(struct lws_context *context, const char *elements[],
|
|||
size_t *privkey_len)
|
||||
{
|
||||
mbedtls_x509write_csr csr;
|
||||
char subject[200];
|
||||
mbedtls_pk_context mpk;
|
||||
int buf_size = 4096, n;
|
||||
char subject[200], *p = subject, *end = p + sizeof(subject) - 1;
|
||||
uint8_t *buf = malloc(buf_size); /* malloc because given to user code */
|
||||
|
||||
if (!buf)
|
||||
|
@ -615,13 +631,14 @@ lws_tls_acme_sni_csr_create(struct lws_context *context, const char *elements[],
|
|||
|
||||
/* subject must be formatted like "C=TW,O=warmcat,CN=myserver" */
|
||||
|
||||
lws_snprintf(subject, sizeof(subject) - 1,
|
||||
"C=%s,ST=%s,L=%s,O=%s,CN=%s",
|
||||
elements[LWS_TLS_REQ_ELEMENT_COUNTRY],
|
||||
elements[LWS_TLS_REQ_ELEMENT_STATE],
|
||||
elements[LWS_TLS_REQ_ELEMENT_LOCALITY],
|
||||
elements[LWS_TLS_REQ_ELEMENT_ORGANIZATION],
|
||||
elements[LWS_TLS_REQ_ELEMENT_COMMON_NAME]);
|
||||
for (n = 0; n < ARRAY_SIZE(x5); n++) {
|
||||
if (p != subject)
|
||||
*p++ = ',';
|
||||
if (elements[n])
|
||||
p += lws_snprintf(p, end - p, "%s=%s", x5[n],
|
||||
elements[n]);
|
||||
}
|
||||
|
||||
if (mbedtls_x509write_csr_set_subject_name(&csr, subject))
|
||||
goto fail1;
|
||||
|
||||
|
|
|
@ -257,11 +257,16 @@ lws_ssl_close(struct lws *wsi)
|
|||
SSL_free(wsi->ssl);
|
||||
wsi->ssl = NULL;
|
||||
|
||||
if (wsi->context->simultaneous_ssl_restriction &&
|
||||
if (!(wsi->mode & LWSCM_FLAG_IMPLIES_CALLBACK_CLOSED_CLIENT_HTTP) &&
|
||||
wsi->context->simultaneous_ssl_restriction &&
|
||||
wsi->context->simultaneous_ssl-- ==
|
||||
wsi->context->simultaneous_ssl_restriction)
|
||||
/* we made space and can do an accept */
|
||||
lws_gate_accepts(wsi->context, 1);
|
||||
|
||||
//lwsl_notice("%s: ssl restr %d, simul %d\n", __func__,
|
||||
// wsi->context->simultaneous_ssl_restriction,
|
||||
// wsi->context->simultaneous_ssl);
|
||||
#if defined(LWS_WITH_STATS)
|
||||
wsi->context->updated = 1;
|
||||
#endif
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
#include "mbedtls/error.h"
|
||||
#include "mbedtls/certs.h"
|
||||
|
||||
#include <libwebsockets.h>
|
||||
|
||||
#define X509_INFO_STRING_LENGTH 8192
|
||||
|
||||
struct ssl_pm
|
||||
|
@ -64,7 +66,7 @@ unsigned int max_content_len;
|
|||
/*********************************************************************************************/
|
||||
/************************************ SSL arch interface *************************************/
|
||||
|
||||
#ifdef CONFIG_OPENSSL_LOWLEVEL_DEBUG
|
||||
//#ifdef CONFIG_OPENSSL_LOWLEVEL_DEBUG
|
||||
|
||||
/* mbedtls debug level */
|
||||
#define MBEDTLS_DEBUG_LEVEL 4
|
||||
|
@ -81,13 +83,13 @@ static void ssl_platform_debug(void *ctx, int level,
|
|||
This is a bit wasteful because the macros are compiled in with
|
||||
the full _FILE_ path in each case.
|
||||
*/
|
||||
char *file_sep = rindex(file, '/');
|
||||
if(file_sep)
|
||||
file = file_sep + 1;
|
||||
// char *file_sep = rindex(file, '/');
|
||||
// if(file_sep)
|
||||
// file = file_sep + 1;
|
||||
|
||||
SSL_DEBUG(SSL_DEBUG_ON, "%s:%d %s", file, line, str);
|
||||
printf("%s:%d %s", file, line, str);
|
||||
}
|
||||
#endif
|
||||
//#endif
|
||||
|
||||
/**
|
||||
* @brief create SSL low-level object
|
||||
|
@ -163,12 +165,12 @@ int ssl_pm_new(SSL *ssl)
|
|||
|
||||
mbedtls_ssl_conf_rng(&ssl_pm->conf, mbedtls_ctr_drbg_random, &ssl_pm->ctr_drbg);
|
||||
|
||||
#ifdef CONFIG_OPENSSL_LOWLEVEL_DEBUG
|
||||
mbedtls_debug_set_threshold(MBEDTLS_DEBUG_LEVEL);
|
||||
//#ifdef CONFIG_OPENSSL_LOWLEVEL_DEBUG
|
||||
// mbedtls_debug_set_threshold(MBEDTLS_DEBUG_LEVEL);
|
||||
// mbedtls_ssl_conf_dbg(&ssl_pm->conf, ssl_platform_debug, NULL);
|
||||
//#else
|
||||
mbedtls_ssl_conf_dbg(&ssl_pm->conf, ssl_platform_debug, NULL);
|
||||
#else
|
||||
mbedtls_ssl_conf_dbg(&ssl_pm->conf, NULL, NULL);
|
||||
#endif
|
||||
//#endif
|
||||
|
||||
ret = mbedtls_ssl_setup(&ssl_pm->ssl, &ssl_pm->conf);
|
||||
if (ret) {
|
||||
|
@ -265,7 +267,7 @@ static int mbedtls_handshake( mbedtls_ssl_context *ssl )
|
|||
while (ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER) {
|
||||
ret = mbedtls_ssl_handshake_step(ssl);
|
||||
|
||||
SSL_DEBUG(SSL_PLATFORM_DEBUG_LEVEL, "ssl ret %d state %d", ret, ssl->state);
|
||||
lwsl_notice("%s: ssl ret -%x state %d\n", __func__, -ret, ssl->state);
|
||||
|
||||
if (ret != 0)
|
||||
break;
|
||||
|
@ -274,14 +276,23 @@ static int mbedtls_handshake( mbedtls_ssl_context *ssl )
|
|||
return ret;
|
||||
}
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
int ssl_pm_handshake(SSL *ssl)
|
||||
{
|
||||
int ret;
|
||||
struct ssl_pm *ssl_pm = (struct ssl_pm *)ssl->ssl_pm;
|
||||
|
||||
lwsl_notice("%s\n", __func__);
|
||||
|
||||
ssl->err = 0;
|
||||
errno = 0;
|
||||
|
||||
ret = ssl_pm_reload_crt(ssl);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
printf("%s: cert reload failed\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ssl_pm->ssl.state != MBEDTLS_SSL_HANDSHAKE_OVER) {
|
||||
ssl_speed_up_enter();
|
||||
|
@ -302,6 +313,7 @@ int ssl_pm_handshake(SSL *ssl)
|
|||
* <0 = death
|
||||
*/
|
||||
if (ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE) {
|
||||
ssl->err = ret;
|
||||
SSL_DEBUG(SSL_PLATFORM_ERROR_LEVEL, "mbedtls_ssl_handshake() return -0x%x", -ret);
|
||||
return 0; /* OpenSSL: did not complete but may be retried */
|
||||
}
|
||||
|
@ -313,6 +325,14 @@ int ssl_pm_handshake(SSL *ssl)
|
|||
return 1; /* openssl successful */
|
||||
}
|
||||
|
||||
if (errno == 11) {
|
||||
ssl->err = ret == MBEDTLS_ERR_SSL_WANT_READ;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
printf("%s: mbedtls_ssl_handshake() returned -0x%x\n", __func__, -ret);
|
||||
|
||||
/* it's had it */
|
||||
|
||||
ssl->err = SSL_ERROR_SYSCALL;
|
||||
|
@ -377,7 +397,7 @@ int ssl_pm_read(SSL *ssl, void *buffer, int len)
|
|||
|
||||
ret = mbedtls_ssl_read(&ssl_pm->ssl, buffer, len);
|
||||
if (ret < 0) {
|
||||
//printf("%s: mbedtls_ssl_read says -0x%x\n", __func__, -ret);
|
||||
// lwsl_notice("%s: mbedtls_ssl_read says -0x%x\n", __func__, -ret);
|
||||
SSL_DEBUG(SSL_PLATFORM_ERROR_LEVEL, "mbedtls_ssl_read() return -0x%x", -ret);
|
||||
if (ret == MBEDTLS_ERR_NET_CONN_RESET ||
|
||||
ret <= MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE) /* fatal errors */
|
||||
|
|
|
@ -282,7 +282,7 @@ check_key:
|
|||
lwsl_err("%s: no extra certs\n", __func__);
|
||||
#endif
|
||||
if (!x) {
|
||||
lwsl_err("%s: x is NULL\n", __func__);
|
||||
//lwsl_err("%s: x is NULL\n", __func__);
|
||||
goto post_ecdh;
|
||||
}
|
||||
/* Get the public key from certificate */
|
||||
|
|
|
@ -401,6 +401,11 @@ lws_ssl_close(struct lws *wsi)
|
|||
wsi->context->simultaneous_ssl_restriction)
|
||||
/* we made space and can do an accept */
|
||||
lws_gate_accepts(wsi->context, 1);
|
||||
|
||||
// lwsl_notice("%s: ssl restr %d, simul %d\n", __func__,
|
||||
// wsi->context->simultaneous_ssl_restriction,
|
||||
// wsi->context->simultaneous_ssl);
|
||||
|
||||
#if defined(LWS_WITH_STATS)
|
||||
wsi->context->updated = 1;
|
||||
#endif
|
||||
|
|
|
@ -225,6 +225,7 @@ lws_tls_check_cert_lifetime(struct lws_vhost *v)
|
|||
{
|
||||
union lws_tls_cert_info_results ir;
|
||||
time_t now = (time_t)lws_now_secs(), life = 0;
|
||||
struct lws_acme_cert_aging_args caa;
|
||||
int n;
|
||||
|
||||
if (v->ssl_ctx && !v->skipped_certs) {
|
||||
|
@ -242,7 +243,9 @@ lws_tls_check_cert_lifetime(struct lws_vhost *v)
|
|||
} else
|
||||
lwsl_notice(" vhost %s: no cert\n", v->name);
|
||||
|
||||
lws_broadcast(v->context, LWS_CALLBACK_VHOST_CERT_AGING, v,
|
||||
memset(&caa, 0, sizeof(caa));
|
||||
caa.vh = v;
|
||||
lws_broadcast(v->context, LWS_CALLBACK_VHOST_CERT_AGING, (void *)&caa,
|
||||
(size_t)(ssize_t)life);
|
||||
|
||||
return 0;
|
||||
|
@ -446,7 +449,7 @@ lws_gate_accepts(struct lws_context *context, int on)
|
|||
{
|
||||
struct lws_vhost *v = context->vhost_list;
|
||||
|
||||
lwsl_info("gating accepts %d\n", on);
|
||||
lwsl_notice("%s: on = %d\n", __func__, on);
|
||||
context->ssl_gate_accepts = !on;
|
||||
#if defined(LWS_WITH_STATS)
|
||||
context->updated = 1;
|
||||
|
@ -456,7 +459,7 @@ lws_gate_accepts(struct lws_context *context, int on)
|
|||
if (v->use_ssl && v->lserv_wsi &&
|
||||
lws_change_pollfd(v->lserv_wsi, (LWS_POLLIN) * !on,
|
||||
(LWS_POLLIN) * on))
|
||||
lwsl_info("Unable to set accept POLLIN %d\n", on);
|
||||
lwsl_notice("Unable to set accept POLLIN %d\n", on);
|
||||
|
||||
v = v->vhost_next;
|
||||
}
|
||||
|
|
|
@ -56,6 +56,7 @@ struct acme_connection {
|
|||
char replay_nonce[64];
|
||||
char chall_token[64];
|
||||
char challenge_uri[256];
|
||||
char detail[64];
|
||||
char status[16];
|
||||
char san_a[100];
|
||||
char san_b[100];
|
||||
|
@ -105,6 +106,7 @@ struct per_vhost_data__lws_acme_client {
|
|||
|
||||
char *pvo_data;
|
||||
char *pvop[LWS_TLS_TOTAL_COUNT];
|
||||
const char *pvop_active[LWS_TLS_TOTAL_COUNT];
|
||||
int count_live_pss;
|
||||
char *dest;
|
||||
int pos;
|
||||
|
@ -191,6 +193,7 @@ static const char * const jauthz_tok[] = {
|
|||
"challenges[].status",
|
||||
"challenges[].uri",
|
||||
"challenges[].token",
|
||||
"detail"
|
||||
};
|
||||
enum enum_jauthz_tok {
|
||||
JAAZ_ID_TYPE,
|
||||
|
@ -201,6 +204,7 @@ enum enum_jauthz_tok {
|
|||
JAAZ_CHALLENGES_STATUS,
|
||||
JAAZ_CHALLENGES_URI,
|
||||
JAAZ_CHALLENGES_TOKEN,
|
||||
JAAZ_DETAIL,
|
||||
};
|
||||
static signed char
|
||||
cb_authz(struct lejp_ctx *ctx, char reason)
|
||||
|
@ -226,6 +230,9 @@ cb_authz(struct lejp_ctx *ctx, char reason)
|
|||
break;
|
||||
case JAAZ_EXPIRES:
|
||||
break;
|
||||
case JAAZ_DETAIL:
|
||||
lws_snprintf(s->detail, sizeof(s->detail), "%s", ctx->buf);
|
||||
break;
|
||||
case JAAZ_CHALLENGES_TYPE:
|
||||
if (s->is_sni_02)
|
||||
break;
|
||||
|
@ -263,12 +270,14 @@ static const char * const jchac_tok[] = {
|
|||
"status",
|
||||
"uri",
|
||||
"token",
|
||||
"error.detail"
|
||||
};
|
||||
enum enum_jchac_tok {
|
||||
JCAC_TYPE,
|
||||
JCAC_STATUS,
|
||||
JCAC_URI,
|
||||
JCAC_TOKEN,
|
||||
JCAC_DETAIL,
|
||||
};
|
||||
static signed char
|
||||
cb_chac(struct lejp_ctx *ctx, char reason)
|
||||
|
@ -300,6 +309,9 @@ cb_chac(struct lejp_ctx *ctx, char reason)
|
|||
sizeof(s->chall_token) - 1);
|
||||
s->yes |= 1;
|
||||
break;
|
||||
case JCAC_DETAIL:
|
||||
lws_snprintf(s->detail, sizeof(s->detail), "%s", ctx->buf);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -328,6 +340,14 @@ cb_chac(struct lejp_ctx *ctx, char reason)
|
|||
* (ie, just use new-cert instead of new-order, use the directory for links)
|
||||
*/
|
||||
|
||||
static int
|
||||
lws_acme_report_status(struct lws_vhost *v, int state, const char *json)
|
||||
{
|
||||
lws_callback_vhost_protocols_vhost(v, LWS_CALLBACK_VHOST_CERT_UPDATE,
|
||||
(void *)json, state);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Notice: trashes i and url
|
||||
|
@ -339,6 +359,7 @@ lws_acme_client_connect(struct lws_context *context, struct lws_vhost *vh,
|
|||
{
|
||||
const char *prot, *p;
|
||||
char path[200], _url[256];
|
||||
struct lws *wsi;
|
||||
|
||||
memset(i, 0, sizeof(*i));
|
||||
i->port = 443;
|
||||
|
@ -364,13 +385,21 @@ lws_acme_client_connect(struct lws_context *context, struct lws_vhost *vh,
|
|||
i->pwsi = pwsi;
|
||||
i->protocol = "lws-acme-client";
|
||||
|
||||
return lws_client_connect_via_info(i);
|
||||
wsi = lws_client_connect_via_info(i);
|
||||
if (!wsi) {
|
||||
lws_snprintf(path, sizeof(path) - 1,
|
||||
"Unable to connect to %s", url);
|
||||
lwsl_notice("%s: %s\n", __func__, path);
|
||||
lws_acme_report_status(vh, LWS_CUS_FAILED, path);
|
||||
}
|
||||
|
||||
return wsi;
|
||||
}
|
||||
|
||||
static void
|
||||
lws_acme_finished(struct per_vhost_data__lws_acme_client *vhd)
|
||||
{
|
||||
lwsl_notice("finishing up jws stuff\n");
|
||||
lwsl_debug("%s\n", __func__);
|
||||
|
||||
if (vhd->ac) {
|
||||
if (vhd->ac->vhost)
|
||||
|
@ -384,6 +413,9 @@ lws_acme_finished(struct per_vhost_data__lws_acme_client *vhd)
|
|||
lws_jwk_destroy(&vhd->jwk);
|
||||
|
||||
vhd->ac = NULL;
|
||||
#if defined(LWS_WITH_ESP32)
|
||||
lws_esp32.acme = 0; /* enable scanning */
|
||||
#endif
|
||||
}
|
||||
|
||||
static const char * const pvo_names[] = {
|
||||
|
@ -399,6 +431,113 @@ static const char * const pvo_names[] = {
|
|||
"key-path",
|
||||
};
|
||||
|
||||
static int
|
||||
lws_acme_load_create_auth_keys(struct per_vhost_data__lws_acme_client *vhd,
|
||||
int bits)
|
||||
{
|
||||
int n;
|
||||
|
||||
if (!lws_jwk_load(&vhd->jwk, vhd->pvop[LWS_TLS_SET_AUTH_PATH]))
|
||||
return 0;
|
||||
|
||||
strcpy(vhd->jwk.keytype, "RSA");
|
||||
lwsl_notice("Generating ACME %d-bit keypair... "
|
||||
"will take a little while\n", bits);
|
||||
n = lws_genrsa_new_keypair(vhd->context, &vhd->rsactx, &vhd->jwk.el,
|
||||
bits);
|
||||
if (n) {
|
||||
lwsl_notice("failed to create keypair\n");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
lwsl_notice("...keypair generated\n");
|
||||
|
||||
if (lws_jwk_save(&vhd->jwk,
|
||||
vhd->pvop[LWS_TLS_SET_AUTH_PATH])) {
|
||||
lwsl_notice("unable to save %s\n",
|
||||
vhd->pvop[LWS_TLS_SET_AUTH_PATH]);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
lws_acme_start_acquisition(struct per_vhost_data__lws_acme_client *vhd,
|
||||
struct lws_vhost *v)
|
||||
{
|
||||
char buf[128];
|
||||
|
||||
/* ...and we were given enough info to do the update? */
|
||||
|
||||
if (!vhd->pvop[LWS_TLS_REQ_ELEMENT_COMMON_NAME])
|
||||
return -1;
|
||||
|
||||
/*
|
||||
* ...well... we should try to do something about it then...
|
||||
*/
|
||||
lwsl_notice("%s: ACME cert needs creating / updating: "
|
||||
"vhost %s\n", __func__, lws_get_vhost_name(vhd->vhost));
|
||||
|
||||
vhd->ac = malloc(sizeof(*vhd->ac));
|
||||
memset(vhd->ac, 0, sizeof(*vhd->ac));
|
||||
|
||||
/*
|
||||
* So if we don't have it, the first job is get the directory.
|
||||
*
|
||||
* If we already have the directory, jump straight into trying
|
||||
* to register our key.
|
||||
*
|
||||
* We always try to register the keys... if it's not the first
|
||||
* time, we will get a JSON body in the (legal, nonfatal)
|
||||
* response like this
|
||||
*
|
||||
* {
|
||||
* "type": "urn:acme:error:malformed",
|
||||
* "detail": "Registration key is already in use",
|
||||
* "status": 409
|
||||
* }
|
||||
*/
|
||||
if (!vhd->ac->urls[0][0]) {
|
||||
vhd->ac->state = ACME_STATE_DIRECTORY;
|
||||
lws_snprintf(buf, sizeof(buf) - 1, "%s",
|
||||
vhd->pvop_active[LWS_TLS_SET_DIR_URL]);
|
||||
} else {
|
||||
vhd->ac->state = ACME_STATE_NEW_REG;
|
||||
lws_snprintf(buf, sizeof(buf) - 1, "%s",
|
||||
vhd->ac->urls[JAD_NEW_REG_URL]);
|
||||
}
|
||||
|
||||
vhd->ac->real_vh_port = lws_get_vhost_port(vhd->vhost);
|
||||
vhd->ac->real_vh_name = lws_get_vhost_name(vhd->vhost);
|
||||
vhd->ac->real_vh_iface = lws_get_vhost_iface(vhd->vhost);
|
||||
|
||||
lws_acme_report_status(vhd->vhost, LWS_CUS_STARTING, NULL);
|
||||
|
||||
#if defined(LWS_WITH_ESP32)
|
||||
lws_acme_report_status(vhd->vhost, LWS_CUS_CREATE_KEYS,
|
||||
"Generating keys, please wait");
|
||||
if (lws_acme_load_create_auth_keys(vhd, 2048))
|
||||
goto bail;
|
||||
lws_acme_report_status(vhd->vhost, LWS_CUS_CREATE_KEYS,
|
||||
"Auth keys created");
|
||||
#endif
|
||||
|
||||
if (lws_acme_client_connect(vhd->context, vhd->vhost,
|
||||
&vhd->ac->cwsi, &vhd->ac->i, buf, "GET"))
|
||||
return 0;
|
||||
|
||||
#if defined(LWS_WITH_ESP32)
|
||||
bail:
|
||||
#endif
|
||||
free(vhd->ac);
|
||||
vhd->ac = NULL;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason,
|
||||
void *user, void *in, size_t len)
|
||||
|
@ -408,10 +547,11 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason,
|
|||
lws_protocol_vh_priv_get(lws_get_vhost(wsi),
|
||||
lws_get_protocol(wsi));
|
||||
char buf[LWS_PRE + 2536], *start = buf + LWS_PRE, *p = start,
|
||||
*end = buf + sizeof(buf) - 1, digest[32];
|
||||
unsigned char **pp = (unsigned char **)in, *pend = in + len;
|
||||
const char *content_type = "application/jose+json";
|
||||
*end = buf + sizeof(buf) - 1, digest[32], *failreason = NULL;
|
||||
unsigned char **pp, *pend;
|
||||
const char *content_type;
|
||||
const struct lws_protocol_vhost_options *pvo;
|
||||
struct lws_acme_cert_aging_args *caa;
|
||||
struct acme_connection *ac = NULL;
|
||||
struct lws_genhash_ctx hctx;
|
||||
struct lws *cwsi;
|
||||
|
@ -420,7 +560,7 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason,
|
|||
if (vhd)
|
||||
ac = vhd->ac;
|
||||
|
||||
switch (reason) {
|
||||
switch ((int)reason) {
|
||||
case LWS_CALLBACK_PROTOCOL_INIT:
|
||||
vhd = lws_protocol_vh_priv_zalloc(lws_get_vhost(wsi),
|
||||
lws_get_protocol(wsi),
|
||||
|
@ -461,8 +601,9 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason,
|
|||
pvo_names[m]);
|
||||
n |= 1;
|
||||
} else
|
||||
lwsl_info(" %s: %s\n", pvo_names[m],
|
||||
vhd->pvop[m]);
|
||||
if (vhd->pvop[m])
|
||||
lwsl_info(" %s: %s\n", pvo_names[m],
|
||||
vhd->pvop[m]);
|
||||
if (n) {
|
||||
free(vhd->pvo_data);
|
||||
vhd->pvo_data = NULL;
|
||||
|
@ -470,30 +611,14 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason,
|
|||
return -1;
|
||||
}
|
||||
|
||||
#if !defined(LWS_WITH_ESP32)
|
||||
/*
|
||||
* load (or create) the registration keypair while we
|
||||
* still have root
|
||||
*/
|
||||
if (lws_jwk_load(&vhd->jwk,
|
||||
vhd->pvop[LWS_TLS_SET_AUTH_PATH])) {
|
||||
strcpy(vhd->jwk.keytype, "RSA");
|
||||
n = lws_genrsa_new_keypair(lws_get_context(wsi),
|
||||
&vhd->rsactx, &vhd->jwk.el,
|
||||
4096);
|
||||
if (n) {
|
||||
lwsl_notice("failed to create keypair\n");
|
||||
if (lws_acme_load_create_auth_keys(vhd, 4096))
|
||||
return 1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (lws_jwk_save(&vhd->jwk,
|
||||
vhd->pvop[LWS_TLS_SET_AUTH_PATH])) {
|
||||
lwsl_notice("unable to save %s\n",
|
||||
vhd->pvop[LWS_TLS_SET_AUTH_PATH]);
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* in case we do an update, open the update files while we
|
||||
* still have root
|
||||
|
@ -514,6 +639,7 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason,
|
|||
lwsl_err("unable to create update key file %s\n", buf);
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_PROTOCOL_DESTROY:
|
||||
|
@ -528,6 +654,8 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason,
|
|||
case LWS_CALLBACK_VHOST_CERT_AGING:
|
||||
if (!vhd)
|
||||
break;
|
||||
|
||||
caa = (struct lws_acme_cert_aging_args *)in;
|
||||
/*
|
||||
* Somebody is telling us about a cert some vhost is using.
|
||||
*
|
||||
|
@ -536,64 +664,23 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason,
|
|||
*/
|
||||
if ((int)(ssize_t)len > 14)
|
||||
break;
|
||||
|
||||
/*
|
||||
* ...is this a vhost we were configured on?
|
||||
*/
|
||||
if (vhd->vhost != (struct lws_vhost *)in)
|
||||
break;
|
||||
if (vhd->vhost != caa->vh)
|
||||
return 1;
|
||||
|
||||
/* ...and we were given enough info to do the update? */
|
||||
for (n = 0; n < (int)ARRAY_SIZE(vhd->pvop);n++)
|
||||
if (caa->element_overrides[n])
|
||||
vhd->pvop_active[n] = caa->element_overrides[n];
|
||||
else
|
||||
vhd->pvop_active[n] = vhd->pvop[n];
|
||||
|
||||
if (!vhd->pvop[LWS_TLS_REQ_ELEMENT_COUNTRY])
|
||||
break;
|
||||
lwsl_notice("starting acme acquisition on %s: %s\n",
|
||||
lws_get_vhost_name(caa->vh), vhd->pvop_active[LWS_TLS_SET_DIR_URL]);
|
||||
|
||||
/*
|
||||
* ...well... we should try to do something about it then...
|
||||
*/
|
||||
lwsl_notice("%s: ACME cert needs updating: "
|
||||
"vhost %s: %dd left\n", __func__,
|
||||
lws_get_vhost_name(in), (int)(ssize_t)len);
|
||||
|
||||
vhd->ac = ac = malloc(sizeof(*vhd->ac));
|
||||
memset(ac, 0, sizeof(*ac));
|
||||
|
||||
/*
|
||||
* So if we don't have it, the first job is get the directory.
|
||||
*
|
||||
* If we already have the directory, jump straight into trying
|
||||
* to register our key.
|
||||
*
|
||||
* We always try to register the keys... if it's not the first
|
||||
* time, we will get a JSON body in the (legal, nonfatal)
|
||||
* response like this
|
||||
*
|
||||
* {
|
||||
* "type": "urn:acme:error:malformed",
|
||||
* "detail": "Registration key is already in use",
|
||||
* "status": 409
|
||||
* }
|
||||
*/
|
||||
if (!ac->urls[0][0]) {
|
||||
ac->state = ACME_STATE_DIRECTORY;
|
||||
lws_snprintf(buf, sizeof(buf) - 1, "%s",
|
||||
vhd->pvop[LWS_TLS_SET_DIR_URL]);
|
||||
} else {
|
||||
ac->state = ACME_STATE_NEW_REG;
|
||||
lws_snprintf(buf, sizeof(buf) - 1, "%s",
|
||||
ac->urls[JAD_NEW_REG_URL]);
|
||||
}
|
||||
|
||||
ac->real_vh_port = lws_get_vhost_port((struct lws_vhost *)in);
|
||||
ac->real_vh_name = lws_get_vhost_name((struct lws_vhost *)in);
|
||||
ac->real_vh_iface = lws_get_vhost_iface((struct lws_vhost *)in);
|
||||
|
||||
cwsi = lws_acme_client_connect(vhd->context, vhd->vhost,
|
||||
&ac->cwsi, &ac->i, buf, "GET");
|
||||
if (!cwsi) {
|
||||
lwsl_notice("%s: acme connect failed\n", __func__);
|
||||
free(vhd->ac);
|
||||
vhd->ac = NULL;
|
||||
}
|
||||
lws_acme_start_acquisition(vhd, caa->vh);
|
||||
break;
|
||||
|
||||
/*
|
||||
|
@ -605,11 +692,15 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason,
|
|||
break;
|
||||
|
||||
case LWS_CALLBACK_CLIENT_CONNECTION_ERROR:
|
||||
lwsl_notice("%s: CLIENT_CONNECTION_ERROR\n", __func__);
|
||||
lwsl_notice("%s: CLIENT_CONNECTION_ERROR: %p\n", __func__, wsi);
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_CLOSED_CLIENT_HTTP:
|
||||
lwsl_notice("%s: CLOSED_CLIENT_HTTP\n", __func__);
|
||||
lwsl_notice("%s: CLOSED_CLIENT_HTTP: %p\n", __func__, wsi);
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_CLOSED:
|
||||
lwsl_notice("%s: CLOSED: %p\n", __func__, wsi);
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP:
|
||||
|
@ -625,7 +716,7 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason,
|
|||
WSI_TOKEN_REPLAY_NONCE) < 0) {
|
||||
lwsl_notice("%s: nonce too large\n", __func__);
|
||||
|
||||
return -1;
|
||||
goto failed;
|
||||
}
|
||||
|
||||
switch (ac->state) {
|
||||
|
@ -687,8 +778,10 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason,
|
|||
"\"mailto:%s\""
|
||||
"],\"agreement\":\"%s\""
|
||||
"}",
|
||||
vhd->pvop[LWS_TLS_REQ_ELEMENT_EMAIL],
|
||||
vhd->pvop_active[LWS_TLS_REQ_ELEMENT_EMAIL],
|
||||
ac->urls[JAD_TOS_URL]);
|
||||
|
||||
puts(start);
|
||||
pkt_add_hdrs:
|
||||
ac->len = lws_jws_create_packet(&vhd->jwk,
|
||||
start, p - start,
|
||||
|
@ -701,23 +794,33 @@ pkt_add_hdrs:
|
|||
lwsl_notice("lws_jws_create_packet failed\n");
|
||||
goto failed;
|
||||
}
|
||||
|
||||
pp = (unsigned char **)in;
|
||||
pend = (*pp) + len;
|
||||
|
||||
ac->pos = 0;
|
||||
content_type = "application/jose+json";
|
||||
if (ac->state == ACME_STATE_POLLING_CSR)
|
||||
content_type = "application/pkix-cert";
|
||||
|
||||
if (lws_add_http_header_by_token(wsi,
|
||||
WSI_TOKEN_HTTP_CONTENT_TYPE,
|
||||
(uint8_t *)content_type, 21, pp, pend))
|
||||
(uint8_t *)content_type, 21, pp, pend)) {
|
||||
lwsl_notice("could not add content type\n");
|
||||
goto failed;
|
||||
}
|
||||
|
||||
n = sprintf(buf, "%d", ac->len);
|
||||
if (lws_add_http_header_by_token(wsi,
|
||||
WSI_TOKEN_HTTP_CONTENT_LENGTH,
|
||||
(uint8_t *)buf, n, pp, pend))
|
||||
(uint8_t *)buf, n, pp, pend)) {
|
||||
lwsl_notice("could not add content length\n");
|
||||
goto failed;
|
||||
}
|
||||
|
||||
lws_client_http_body_pending(wsi, 1);
|
||||
lws_callback_on_writable(wsi);
|
||||
lwsl_notice("prepare to send ACME_STATE_NEW_REG\n");
|
||||
break;
|
||||
case ACME_STATE_NEW_AUTH:
|
||||
p += lws_snprintf(p, end - p,
|
||||
|
@ -727,7 +830,7 @@ pkt_add_hdrs:
|
|||
"\"type\":\"http-01\","
|
||||
"\"value\":\"%s\""
|
||||
"}"
|
||||
"}", ac->real_vh_name);
|
||||
"}", vhd->pvop_active[LWS_TLS_REQ_ELEMENT_COMMON_NAME]);
|
||||
goto pkt_add_hdrs;
|
||||
|
||||
case ACME_STATE_ACCEPT_CHALL:
|
||||
|
@ -842,8 +945,7 @@ pkt_add_hdrs:
|
|||
"{\"resource\":\"new-cert\","
|
||||
"\"csr\":\"");
|
||||
n = lws_tls_acme_sni_csr_create(vhd->context,
|
||||
(const char **)
|
||||
vhd->pvop,
|
||||
&vhd->pvop_active[0],
|
||||
(uint8_t *)p, end - p,
|
||||
&ac->alloc_privkey_pem,
|
||||
&ac->len_privkey_pem);
|
||||
|
@ -948,15 +1050,18 @@ pkt_add_hdrs:
|
|||
* not complete for some reason...
|
||||
*/
|
||||
ac->state = ACME_STATE_NEW_REG;
|
||||
lws_acme_report_status(vhd->vhost, LWS_CUS_REG, NULL);
|
||||
|
||||
strcpy(buf, ac->urls[JAD_NEW_REG_URL]);
|
||||
cwsi = lws_acme_client_connect(vhd->context, vhd->vhost,
|
||||
&ac->cwsi, &ac->i, buf,
|
||||
"POST");
|
||||
if (!cwsi)
|
||||
if (!cwsi) {
|
||||
lwsl_notice("%s: failed to connect to acme\n",
|
||||
__func__);
|
||||
break;
|
||||
goto failed;
|
||||
}
|
||||
return -1; /* close the completed client connection */
|
||||
|
||||
case ACME_STATE_NEW_REG:
|
||||
if ((ac->resp >= 200 && ac->resp < 299) ||
|
||||
|
@ -967,6 +1072,8 @@ pkt_add_hdrs:
|
|||
* Move on to requesting a cert auth.
|
||||
*/
|
||||
ac->state = ACME_STATE_NEW_AUTH;
|
||||
lws_acme_report_status(vhd->vhost, LWS_CUS_AUTH,
|
||||
NULL);
|
||||
|
||||
strcpy(buf, ac->urls[JAD_NEW_AUTHZ_URL]);
|
||||
cwsi = lws_acme_client_connect(vhd->context,
|
||||
|
@ -975,16 +1082,32 @@ pkt_add_hdrs:
|
|||
if (!cwsi)
|
||||
lwsl_notice("%s: failed to connect\n",
|
||||
__func__);
|
||||
break;
|
||||
return -1; /* close the completed client connection */
|
||||
} else {
|
||||
lwsl_notice("new-reg replied %d\n", ac->resp);
|
||||
goto failed;
|
||||
}
|
||||
break;
|
||||
return -1; /* close the completed client connection */
|
||||
|
||||
case ACME_STATE_NEW_AUTH:
|
||||
lejp_destruct(&ac->jctx);
|
||||
lwsl_notice("chall: %s\n", ac->chall_token);
|
||||
if (ac->resp / 100 == 4) {
|
||||
lws_snprintf(buf, sizeof(buf),
|
||||
"Auth failed: %s", ac->detail);
|
||||
failreason = buf;
|
||||
lwsl_notice("auth failed\n");
|
||||
goto failed;
|
||||
}
|
||||
lwsl_notice("chall: %s (%d)\n", ac->chall_token, ac->resp);
|
||||
if (!ac->chall_token[0]) {
|
||||
lwsl_notice("no challenge\n");
|
||||
goto failed;
|
||||
}
|
||||
|
||||
|
||||
ac->state = ACME_STATE_ACCEPT_CHALL;
|
||||
lws_acme_report_status(vhd->vhost, LWS_CUS_CHALLENGE,
|
||||
NULL);
|
||||
|
||||
/* tls-sni-01 ... what a mess.
|
||||
* The stuff in
|
||||
|
@ -1141,7 +1264,6 @@ pkt_add_hdrs:
|
|||
* server know we are ready to roll...
|
||||
*/
|
||||
|
||||
ac->state = ACME_STATE_ACCEPT_CHALL;
|
||||
ac->goes_around = 0;
|
||||
cwsi = lws_acme_client_connect(vhd->context, vhd->vhost,
|
||||
&ac->cwsi, &ac->i,
|
||||
|
@ -1152,7 +1274,7 @@ pkt_add_hdrs:
|
|||
__func__);
|
||||
goto failed;
|
||||
}
|
||||
break;
|
||||
return -1; /* close the completed client connection */
|
||||
|
||||
case ACME_STATE_ACCEPT_CHALL:
|
||||
/*
|
||||
|
@ -1176,23 +1298,18 @@ pkt_add_hdrs:
|
|||
__func__, ac->challenge_uri);
|
||||
poll_again:
|
||||
ac->state = ACME_STATE_POLLING;
|
||||
lws_acme_report_status(vhd->vhost, LWS_CUS_CHALLENGE, NULL);
|
||||
|
||||
if (ac->goes_around++ == 10) {
|
||||
if (ac->goes_around++ == 20) {
|
||||
lwsl_notice("%s: too many chall retries\n",
|
||||
__func__);
|
||||
|
||||
goto failed;
|
||||
}
|
||||
cwsi = lws_acme_client_connect(vhd->context, vhd->vhost,
|
||||
&ac->cwsi, &ac->i,
|
||||
ac->challenge_uri,
|
||||
"GET");
|
||||
if (!cwsi) {
|
||||
lwsl_notice("%s: failed to connect\n",
|
||||
__func__);
|
||||
goto failed;
|
||||
}
|
||||
break;
|
||||
|
||||
lws_timed_callback_vh_protocol(vhd->vhost, vhd->protocol,
|
||||
LWS_CALLBACK_USER + 0xac33, ac->goes_around == 1 ? 10 : 2);
|
||||
return -1; /* close the completed client connection */
|
||||
|
||||
case ACME_STATE_POLLING:
|
||||
|
||||
|
@ -1205,13 +1322,16 @@ poll_again:
|
|||
|
||||
if (!strcmp(ac->status, "invalid")) {
|
||||
lwsl_notice("%s: polling failed\n", __func__);
|
||||
lws_snprintf(buf, sizeof(buf),
|
||||
"Challenge Invalid: %s", ac->detail);
|
||||
failreason = buf;
|
||||
goto failed;
|
||||
}
|
||||
|
||||
lwsl_notice("Authorization accepted\n");
|
||||
lwsl_notice("Challenge passed\n");
|
||||
|
||||
/*
|
||||
* our authorization was validated... so delete the
|
||||
* The challenge was validated... so delete the
|
||||
* temp SNI vhost now its job is done
|
||||
*/
|
||||
if (ac->vhost)
|
||||
|
@ -1225,6 +1345,7 @@ poll_again:
|
|||
* server to request the actual certs.
|
||||
*/
|
||||
ac->state = ACME_STATE_POLLING_CSR;
|
||||
lws_acme_report_status(vhd->vhost, LWS_CUS_REQ, NULL);
|
||||
ac->goes_around = 0;
|
||||
|
||||
strcpy(buf, ac->urls[JAD_NEW_CERT_URL]);
|
||||
|
@ -1237,7 +1358,7 @@ poll_again:
|
|||
|
||||
goto failed;
|
||||
}
|
||||
break;
|
||||
return -1; /* close the completed client connection */
|
||||
|
||||
case ACME_STATE_POLLING_CSR:
|
||||
/*
|
||||
|
@ -1273,6 +1394,10 @@ poll_again:
|
|||
int max;
|
||||
|
||||
lwsl_notice("The cert was sent..\n");
|
||||
|
||||
lws_acme_report_status(vhd->vhost,
|
||||
LWS_CUS_ISSUE, NULL);
|
||||
|
||||
/*
|
||||
* That means we have the issued cert DER in
|
||||
* ac->buf, length in ac->cpos; and the key in
|
||||
|
@ -1334,7 +1459,7 @@ poll_again:
|
|||
lws_ptr_diff(p, start));
|
||||
free(start);
|
||||
if (n) {
|
||||
lwsl_err("unable to write ACME cert!\n");
|
||||
lwsl_err("unable to write ACME cert! %d\n", n);
|
||||
goto failed;
|
||||
}
|
||||
/*
|
||||
|
@ -1356,15 +1481,15 @@ poll_again:
|
|||
|
||||
lwsl_notice("%s: Updated certs written for %s "
|
||||
"to %s.upd and %s.upd\n", __func__,
|
||||
vhd->pvop[LWS_TLS_REQ_ELEMENT_COMMON_NAME],
|
||||
vhd->pvop[LWS_TLS_SET_CERT_PATH],
|
||||
vhd->pvop[LWS_TLS_SET_KEY_PATH]);
|
||||
vhd->pvop_active[LWS_TLS_REQ_ELEMENT_COMMON_NAME],
|
||||
vhd->pvop_active[LWS_TLS_SET_CERT_PATH],
|
||||
vhd->pvop_active[LWS_TLS_SET_KEY_PATH]);
|
||||
|
||||
/* notify lws there was a cert update */
|
||||
|
||||
if (lws_tls_cert_updated(vhd->context,
|
||||
vhd->pvop[LWS_TLS_SET_CERT_PATH],
|
||||
vhd->pvop[LWS_TLS_SET_KEY_PATH],
|
||||
vhd->pvop_active[LWS_TLS_SET_CERT_PATH],
|
||||
vhd->pvop_active[LWS_TLS_SET_KEY_PATH],
|
||||
ac->buf, ac->cpos,
|
||||
ac->alloc_privkey_pem,
|
||||
ac->len_privkey_pem)) {
|
||||
|
@ -1372,10 +1497,14 @@ poll_again:
|
|||
}
|
||||
|
||||
lws_acme_finished(vhd);
|
||||
lws_acme_report_status(vhd->vhost,
|
||||
LWS_CUS_SUCCESS, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
lws_acme_report_status(vhd->vhost, LWS_CUS_CONFIRM, NULL);
|
||||
|
||||
/* he is preparing the cert, go again with a GET */
|
||||
|
||||
if (ac->goes_around++ == 30) {
|
||||
|
@ -1395,13 +1524,24 @@ poll_again:
|
|||
|
||||
goto failed;
|
||||
}
|
||||
break;
|
||||
return -1; /* close the completed client connection */
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_USER + 0xac33:
|
||||
cwsi = lws_acme_client_connect(vhd->context, vhd->vhost,
|
||||
&ac->cwsi, &ac->i,
|
||||
ac->challenge_uri,
|
||||
"GET");
|
||||
if (!cwsi) {
|
||||
lwsl_notice("%s: failed to connect\n", __func__);
|
||||
goto failed;
|
||||
}
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_OPENSSL_LOAD_EXTRA_SERVER_VERIFY_CERTS:
|
||||
/*
|
||||
* This goes to vhost->protocols[0], but for our temp certs
|
||||
|
@ -1414,9 +1554,17 @@ poll_again:
|
|||
lwsl_debug("LWS_CALLBACK_OPENSSL_LOAD_EXTRA_SERVER_VERIFY_CERTS\n");
|
||||
ac = (struct acme_connection *)lws_get_vhost_user(
|
||||
(struct lws_vhost *)in);
|
||||
|
||||
lws_acme_report_status((struct lws_vhost *)in,
|
||||
LWS_CUS_CREATE_REQ,
|
||||
"creating challenge cert");
|
||||
|
||||
if (lws_tls_acme_sni_cert_create((struct lws_vhost *)in,
|
||||
ac->san_a, ac->san_b))
|
||||
ac->san_a, ac->san_b)) {
|
||||
lwsl_err("%s: creating the sni test cert failed\n", __func__);
|
||||
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -1427,6 +1575,7 @@ poll_again:
|
|||
|
||||
failed:
|
||||
lwsl_err("%s: failed out\n", __func__);
|
||||
lws_acme_report_status(vhd->vhost, LWS_CUS_FAILED, failreason);
|
||||
lws_acme_finished(vhd);
|
||||
|
||||
return -1;
|
||||
|
|
|
@ -72,7 +72,8 @@ lwsgs_handler_confirm(struct per_vhost_data__gs *vhd, struct lws *wsi,
|
|||
a.event = LWSGSE_CREATED;
|
||||
a.username = u.username;
|
||||
a.email = u.email;
|
||||
lws_callback_vhost_protocols(wsi, LWS_CALLBACK_GS_EVENT, &a, 0);
|
||||
lws_callback_vhost_protocols_vhost(lws_get_vhost(wsi),
|
||||
LWS_CALLBACK_GS_EVENT, &a, 0);
|
||||
|
||||
lws_snprintf(pss->onward, sizeof(pss->onward),
|
||||
"%s/post-verify-ok.html", vhd->email_confirm_url);
|
||||
|
@ -325,7 +326,8 @@ lwsgs_handler_change_password(struct per_vhost_data__gs *vhd, struct lws *wsi,
|
|||
a.event = LWSGSE_DELETED;
|
||||
a.username = u.username;
|
||||
a.email = "";
|
||||
lws_callback_vhost_protocols(wsi, LWS_CALLBACK_GS_EVENT, &a, 0);
|
||||
lws_callback_vhost_protocols_vhost(lws_get_vhost(wsi),
|
||||
LWS_CALLBACK_GS_EVENT, &a, 0);
|
||||
|
||||
lws_snprintf(s, sizeof(s) - 1,
|
||||
"delete from users where username='%s';"
|
||||
|
|
|
@ -213,7 +213,7 @@ callback_messageboard(struct lws *wsi, enum lws_callback_reasons reason,
|
|||
break;
|
||||
|
||||
case LWS_CALLBACK_PROTOCOL_DESTROY:
|
||||
if (vhd->pdb)
|
||||
if (vhd && vhd->pdb)
|
||||
sqlite3_close(vhd->pdb);
|
||||
goto passthru;
|
||||
|
||||
|
|
|
@ -33,6 +33,7 @@ struct per_session_data__esplws_ota {
|
|||
esp_ota_handle_t otahandle;
|
||||
const esp_partition_t *part;
|
||||
long file_length;
|
||||
long last_rep;
|
||||
nvs_handle nvh;
|
||||
TimerHandle_t reboot_timer;
|
||||
};
|
||||
|
@ -117,6 +118,7 @@ ota_file_upload_cb(void *data, const char *name, const char *filename,
|
|||
}
|
||||
|
||||
pss->file_length = 0;
|
||||
pss->last_rep = -1;
|
||||
break;
|
||||
|
||||
case LWS_UFS_FINAL_CONTENT:
|
||||
|
@ -126,9 +128,11 @@ ota_file_upload_cb(void *data, const char *name, const char *filename,
|
|||
return 1;
|
||||
}
|
||||
|
||||
lwsl_notice("writing 0x%lx... 0x%lx\n",
|
||||
pss->part->address + pss->file_length,
|
||||
pss->part->address + pss->file_length + len);
|
||||
if ((pss->file_length & ~0xffff) != (pss->last_rep & ~0xffff)) {
|
||||
lwsl_notice("writing 0x%lx...\n",
|
||||
pss->part->address + pss->file_length);
|
||||
pss->last_rep = pss->file_length;
|
||||
}
|
||||
if (esp_ota_write(pss->otahandle, buf, len) != ESP_OK) {
|
||||
lwsl_err("OTA: Failed to write\n");
|
||||
return 1;
|
||||
|
|
|
@ -56,6 +56,8 @@ struct per_session_data__esplws_scan {
|
|||
unsigned char changed_partway:1;
|
||||
};
|
||||
|
||||
#define max_aps 12
|
||||
|
||||
struct per_vhost_data__esplws_scan {
|
||||
wifi_ap_record_t ap_records[10];
|
||||
TimerHandle_t timer, reboot_timer;
|
||||
|
@ -63,6 +65,7 @@ struct per_vhost_data__esplws_scan {
|
|||
struct lws_context *context;
|
||||
struct lws_vhost *vhost;
|
||||
const struct lws_protocols *protocol;
|
||||
struct lws_wifi_scan *known_aps_list;
|
||||
|
||||
const esp_partition_t *part;
|
||||
esp_ota_handle_t otahandle;
|
||||
|
@ -75,6 +78,9 @@ struct per_vhost_data__esplws_scan {
|
|||
char json[2048];
|
||||
int json_len;
|
||||
|
||||
int acme_state;
|
||||
char acme_msg[256];
|
||||
|
||||
uint16_t count_ap_records;
|
||||
char count_live_pss;
|
||||
unsigned char scan_ongoing:1;
|
||||
|
@ -117,6 +123,9 @@ static const char * const param_names[] = {
|
|||
"pri",
|
||||
"serial",
|
||||
"opts",
|
||||
"group",
|
||||
"role",
|
||||
"updsettings",
|
||||
};
|
||||
|
||||
enum enum_param_names {
|
||||
|
@ -125,6 +134,9 @@ enum enum_param_names {
|
|||
EPN_PRI,
|
||||
EPN_SERIAL,
|
||||
EPN_OPTS,
|
||||
EPN_GROUP,
|
||||
EPN_ROLE,
|
||||
EPN_UPDSETTINGS,
|
||||
};
|
||||
|
||||
|
||||
|
@ -159,6 +171,9 @@ scan_start(struct per_vhost_data__esplws_scan *vhd)
|
|||
if (vhd->scan_ongoing)
|
||||
return;
|
||||
|
||||
if (lws_esp32.acme)
|
||||
return;
|
||||
|
||||
vhd->scan_ongoing = 1;
|
||||
lws_esp32.scan_consumer = scan_finished;
|
||||
lws_esp32.scan_consumer_arg = vhd;
|
||||
|
@ -167,10 +182,17 @@ scan_start(struct per_vhost_data__esplws_scan *vhd)
|
|||
lwsl_err("scan start failed %d\n", n);
|
||||
}
|
||||
|
||||
static char scan_defer;
|
||||
|
||||
static void timer_cb(TimerHandle_t t)
|
||||
{
|
||||
struct per_vhost_data__esplws_scan *vhd = pvTimerGetTimerID(t);
|
||||
|
||||
if (!lws_esp32.inet && (scan_defer & 1)) {
|
||||
/* if connected in AP mode, wait twice as long between scans */
|
||||
return;
|
||||
}
|
||||
|
||||
scan_start(vhd);
|
||||
}
|
||||
|
||||
|
@ -214,11 +236,101 @@ client_connection(struct per_vhost_data__esplws_scan *vhd, const char *file)
|
|||
return 0; /* ongoing */
|
||||
}
|
||||
|
||||
static int
|
||||
lws_wifi_scan_rssi(struct lws_wifi_scan *p)
|
||||
{
|
||||
if (!p->count)
|
||||
return -127;
|
||||
|
||||
return p->rssi / p->count;
|
||||
}
|
||||
|
||||
/*
|
||||
* Insert new lws_wifi_scan into linkedlist in rssi-sorted order, trimming the
|
||||
* list if needed to keep it at or below max_aps entries.
|
||||
*/
|
||||
|
||||
static int
|
||||
lws_wifi_scan_insert_trim(struct lws_wifi_scan **list, struct lws_wifi_scan *ns)
|
||||
{
|
||||
int count = 0, ins = 1, worst;
|
||||
struct lws_wifi_scan *newlist, **pworst, *pp1;
|
||||
|
||||
lws_start_foreach_llp(struct lws_wifi_scan **, pp, *list) {
|
||||
/* try to find existing match */
|
||||
if (!strcmp((*pp)->ssid, ns->ssid) &&
|
||||
!memcmp((*pp)->bssid, ns->bssid, 6)) {
|
||||
if ((*pp)->count > 127) {
|
||||
(*pp)->count /= 2;
|
||||
(*pp)->rssi /= 2;
|
||||
}
|
||||
(*pp)->rssi += ns->rssi;
|
||||
(*pp)->count++;
|
||||
ins = 0;
|
||||
break;
|
||||
}
|
||||
} lws_end_foreach_llp(pp, next);
|
||||
|
||||
if (ins) {
|
||||
lws_start_foreach_llp(struct lws_wifi_scan **, pp, *list) {
|
||||
/* trim any excess guys */
|
||||
if (count++ >= max_aps - 1) {
|
||||
pp1 = *pp;
|
||||
*pp = (*pp)->next;
|
||||
free(pp1);
|
||||
continue; /* stay where we are */
|
||||
}
|
||||
} lws_end_foreach_llp(pp, next);
|
||||
|
||||
/* we are inserting... so alloc a copy of him */
|
||||
pp1 = malloc(sizeof(*pp1));
|
||||
if (!pp1)
|
||||
return -1;
|
||||
|
||||
memcpy(pp1, ns, sizeof(*pp1));
|
||||
pp1->next = *list;
|
||||
*list = pp1;
|
||||
}
|
||||
|
||||
/* sort the list ... worst first, but added at the newlist head */
|
||||
|
||||
newlist = NULL;
|
||||
|
||||
/* while anybody left on the old list */
|
||||
while (*list) {
|
||||
worst = 0;
|
||||
pworst = NULL;
|
||||
|
||||
/* who is the worst guy still left on the old list? */
|
||||
lws_start_foreach_llp(struct lws_wifi_scan **, pp, *list) {
|
||||
if (lws_wifi_scan_rssi(*pp) <= worst) {
|
||||
worst = lws_wifi_scan_rssi(*pp);
|
||||
pworst = pp;
|
||||
}
|
||||
} lws_end_foreach_llp(pp, next);
|
||||
|
||||
if (pworst) {
|
||||
/* move the worst to the head of the new list */
|
||||
pp1 = *pworst;
|
||||
*pworst = (*pworst)->next;
|
||||
pp1->next = newlist;
|
||||
newlist = pp1;
|
||||
}
|
||||
}
|
||||
|
||||
*list = newlist;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
scan_finished(uint16_t count, wifi_ap_record_t *recs, void *v)
|
||||
{
|
||||
struct per_vhost_data__esplws_scan *vhd = v;
|
||||
struct per_session_data__esplws_scan *p = vhd->live_pss_list;
|
||||
struct lws_wifi_scan lws;
|
||||
wifi_ap_record_t *r;
|
||||
int m;
|
||||
|
||||
lwsl_notice("%s: count %d\n", __func__, count);
|
||||
|
||||
|
@ -232,13 +344,31 @@ scan_finished(uint16_t count, wifi_ap_record_t *recs, void *v)
|
|||
memcpy(vhd->ap_records, recs, vhd->count_ap_records * sizeof(*recs));
|
||||
|
||||
while (p) {
|
||||
if (p->scan_state != SCAN_STATE_INITIAL && p->scan_state != SCAN_STATE_NONE)
|
||||
if (p->scan_state != SCAN_STATE_INITIAL &&
|
||||
p->scan_state != SCAN_STATE_NONE)
|
||||
p->changed_partway = 1;
|
||||
else
|
||||
p->scan_state = SCAN_STATE_INITIAL;
|
||||
p = p->next;
|
||||
}
|
||||
|
||||
/* convert to generic, cumulative scan results */
|
||||
|
||||
for (m = 0; m < vhd->count_ap_records; m++) {
|
||||
|
||||
r = &vhd->ap_records[m];
|
||||
|
||||
lws.authmode = r->authmode;
|
||||
lws.channel = r->primary;
|
||||
lws.rssi = r->rssi;
|
||||
lws.count = 1;
|
||||
memcpy(&lws.bssid, r->bssid, 6);
|
||||
strncpy(lws.ssid, (const char *)r->ssid, sizeof(lws.ssid) - 1);
|
||||
lws.ssid[sizeof(lws.ssid) - 1] = '\0';
|
||||
|
||||
lws_wifi_scan_insert_trim(&vhd->known_aps_list, &lws);
|
||||
}
|
||||
|
||||
lws_callback_on_writable_all_protocol(vhd->context, vhd->protocol);
|
||||
|
||||
if (lws_esp32.inet && !vhd->cwsi && !vhd->checked_updates)
|
||||
|
@ -320,9 +450,8 @@ callback_esplws_scan(struct lws *wsi, enum lws_callback_reasons reason,
|
|||
unsigned char *start = pss->buffer + LWS_PRE - 1, *p = start,
|
||||
*end = pss->buffer + sizeof(pss->buffer) - 1;
|
||||
union lws_tls_cert_info_results ir;
|
||||
struct lws_wifi_scan *lwscan;
|
||||
char subject[64];
|
||||
const char *pp;
|
||||
wifi_ap_record_t *r;
|
||||
int n, m;
|
||||
nvs_handle nvh;
|
||||
size_t s;
|
||||
|
@ -341,7 +470,7 @@ callback_esplws_scan(struct lws *wsi, enum lws_callback_reasons reason,
|
|||
(TimerCallbackFunction_t)timer_cb);
|
||||
vhd->scan_ongoing = 0;
|
||||
strcpy(vhd->json, " { }");
|
||||
scan_start(vhd);
|
||||
// scan_start(vhd);
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_PROTOCOL_DESTROY:
|
||||
|
@ -354,17 +483,17 @@ callback_esplws_scan(struct lws *wsi, enum lws_callback_reasons reason,
|
|||
case LWS_CALLBACK_ESTABLISHED:
|
||||
lwsl_notice("%s: ESTABLISHED\n", __func__);
|
||||
if (!vhd->live_pss_list) {
|
||||
scan_start(vhd);
|
||||
// scan_start(vhd);
|
||||
xTimerStart(vhd->timer, 0);
|
||||
}
|
||||
vhd->count_live_pss++;
|
||||
pss->next = vhd->live_pss_list;
|
||||
vhd->live_pss_list = pss;
|
||||
/* if we have scan results, update them. Otherwise wait */
|
||||
if (vhd->count_ap_records) {
|
||||
// if (vhd->count_ap_records) {
|
||||
pss->scan_state = SCAN_STATE_INITIAL;
|
||||
lws_callback_on_writable(wsi);
|
||||
}
|
||||
// }
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_SERVER_WRITEABLE:
|
||||
|
@ -481,6 +610,10 @@ callback_esplws_scan(struct lws *wsi, enum lws_callback_reasons reason,
|
|||
" \"unixtime\":\"%llu\",\n"
|
||||
" \"certissuer\":\"%s\",\n"
|
||||
" \"certsubject\":\"%s\",\n"
|
||||
" \"le_dns\":\"%s\",\n"
|
||||
" \"le_email\":\"%s\",\n"
|
||||
" \"acme_state\":\"%d\",\n"
|
||||
" \"acme_msg\":\"%s\",\n"
|
||||
" \"button\":\"%d\",\n"
|
||||
" \"group\":\"%s\",\n"
|
||||
" \"role\":\"%s\",\n",
|
||||
|
@ -499,6 +632,10 @@ callback_esplws_scan(struct lws *wsi, enum lws_callback_reasons reason,
|
|||
vhd->cert_remaining_days,
|
||||
(unsigned long long)t.tv_sec,
|
||||
ir.ns.name, subject,
|
||||
lws_esp32.le_dns,
|
||||
lws_esp32.le_email,
|
||||
vhd->acme_state,
|
||||
vhd->acme_msg,
|
||||
((volatile struct lws_esp32 *)(&lws_esp32))->button_is_down,
|
||||
group, role);
|
||||
p += snprintf((char *)p, end - p,
|
||||
|
@ -561,6 +698,7 @@ callback_esplws_scan(struct lws *wsi, enum lws_callback_reasons reason,
|
|||
ssid, pp, use);
|
||||
}
|
||||
nvs_close(nvh);
|
||||
pss->ap_record = 0;
|
||||
|
||||
p += snprintf((char *)p, end - p,
|
||||
"], \"aps\":[\n");
|
||||
|
@ -570,27 +708,36 @@ callback_esplws_scan(struct lws *wsi, enum lws_callback_reasons reason,
|
|||
break;
|
||||
|
||||
case SCAN_STATE_LIST:
|
||||
lwscan = vhd->known_aps_list;
|
||||
|
||||
n = pss->ap_record;
|
||||
while (lwscan && n--)
|
||||
lwscan = lwscan->next;
|
||||
|
||||
for (m = 0; m < 6; m++) {
|
||||
n = LWS_WRITE_CONTINUATION | LWS_WRITE_NO_FIN;
|
||||
if (pss->ap_record >= vhd->count_ap_records)
|
||||
if (!lwscan)
|
||||
goto scan_state_final;
|
||||
|
||||
if (pss->subsequent)
|
||||
*p++ = ',';
|
||||
pss->subsequent = 1;
|
||||
pss->ap_record++;
|
||||
|
||||
r = &vhd->ap_records[(int)pss->ap_record++];
|
||||
p += snprintf((char *)p, end - p,
|
||||
"{\"ssid\":\"%s\",\n"
|
||||
"\"bssid\":\"%02X:%02X:%02X:%02X:%02X:%02X\",\n"
|
||||
"\"rssi\":\"%d\",\n"
|
||||
"\"chan\":\"%d\",\n"
|
||||
"\"auth\":\"%d\"}\n",
|
||||
r->ssid,
|
||||
r->bssid[0], r->bssid[1], r->bssid[2],
|
||||
r->bssid[3], r->bssid[4], r->bssid[5],
|
||||
r->rssi, r->primary, r->authmode);
|
||||
if (pss->ap_record >= vhd->count_ap_records)
|
||||
lwscan->ssid,
|
||||
lwscan->bssid[0], lwscan->bssid[1], lwscan->bssid[2],
|
||||
lwscan->bssid[3], lwscan->bssid[4], lwscan->bssid[5],
|
||||
lws_wifi_scan_rssi(lwscan),
|
||||
lwscan->channel, lwscan->authmode);
|
||||
|
||||
lwscan = lwscan->next;
|
||||
if (!lwscan)
|
||||
pss->scan_state = SCAN_STATE_FINAL;
|
||||
}
|
||||
break;
|
||||
|
@ -600,6 +747,7 @@ scan_state_final:
|
|||
n = LWS_WRITE_CONTINUATION;
|
||||
p += sprintf((char *)p, "]\n}\n");
|
||||
if (pss->changed_partway) {
|
||||
pss->changed_partway = 0;
|
||||
pss->subsequent = 0;
|
||||
pss->scan_state = SCAN_STATE_INITIAL;
|
||||
} else {
|
||||
|
@ -622,6 +770,17 @@ issue:
|
|||
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_VHOST_CERT_UPDATE:
|
||||
lwsl_notice("LWS_CALLBACK_VHOST_CERT_UPDATE: %d\n", (int)len);
|
||||
vhd->acme_state = (int)len;
|
||||
if (in) {
|
||||
strncpy(vhd->acme_msg, in, sizeof(vhd->acme_msg) - 1);
|
||||
vhd->acme_msg[sizeof(vhd->acme_msg) - 1] = '\0';
|
||||
lwsl_notice("acme_msg: %s\n", (char *)in);
|
||||
}
|
||||
lws_callback_on_writable_all_protocol_vhost(vhd->vhost, vhd->protocol);
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_RECEIVE:
|
||||
{
|
||||
const char *sect = "\"app\": {", *b;
|
||||
|
@ -644,6 +803,10 @@ issue:
|
|||
if (strstr((const char *)in, "\"reset\""))
|
||||
goto sched_reset;
|
||||
|
||||
if (!strncmp((const char *)in, "{\"job\":\"start-le\"", 17))
|
||||
goto start_le;
|
||||
|
||||
|
||||
if (nvs_open("lws-station", NVS_READWRITE, &nvh) != ESP_OK) {
|
||||
lwsl_err("Unable to open nvs\n");
|
||||
break;
|
||||
|
@ -662,16 +825,6 @@ issue:
|
|||
if (n == 8 && lws_esp32_get_reboot_type() != LWS_MAGIC_REBOOT_TYPE_FORCED_FACTORY_BUTTON)
|
||||
continue;
|
||||
|
||||
//lwsl_notice("%s: %s '%s'\n", __func__, store_json[n].nvs, p);
|
||||
if (n == 9) {
|
||||
strncpy(lws_esp32.group, p, sizeof(lws_esp32.group) - 1);
|
||||
lws_esp32.group[sizeof(lws_esp32.group) - 1] = '\0';
|
||||
}
|
||||
if (n == 10) {
|
||||
strncpy(lws_esp32.role, p, sizeof(lws_esp32.role) - 1);
|
||||
lws_esp32.role[sizeof(lws_esp32.role) - 1] = '\0';
|
||||
}
|
||||
|
||||
if (lws_nvs_set_str(nvh, store_json[n].nvs, p) != ESP_OK) {
|
||||
lwsl_err("Unable to store %s in nvm\n", store_json[n].nvs);
|
||||
goto bail_nvs;
|
||||
|
@ -767,6 +920,75 @@ auton:
|
|||
vhd->autonomous_update = 0;
|
||||
|
||||
break;
|
||||
|
||||
start_le:
|
||||
lws_esp32.acme = 1; /* hold off scanning */
|
||||
puts(in);
|
||||
/*
|
||||
* {"job":"start-le","cn":"home.warmcat.com",
|
||||
* "email":"andy@warmcat.com", "staging":"true"}
|
||||
*/
|
||||
|
||||
if (nvs_open("lws-station", NVS_READWRITE, &nvh) != ESP_OK) {
|
||||
lwsl_err("Unable to open nvs\n");
|
||||
break;
|
||||
}
|
||||
|
||||
n = 0;
|
||||
b = strstr(in, ",\"cn\":\"");
|
||||
if (b) {
|
||||
b += 7;
|
||||
while (*b && *b != '\"' && n < sizeof(lws_esp32.le_dns) - 1)
|
||||
lws_esp32.le_dns[n++] = *b++;
|
||||
}
|
||||
lws_esp32.le_dns[n] = '\0';
|
||||
|
||||
lws_nvs_set_str(nvh, "acme-cn", lws_esp32.le_dns);
|
||||
n = 0;
|
||||
b = strstr(in, ",\"email\":\"");
|
||||
if (b) {
|
||||
b += 10;
|
||||
while (*b && *b != '\"' && n < sizeof(lws_esp32.le_email) - 1)
|
||||
lws_esp32.le_email[n++] = *b++;
|
||||
}
|
||||
lws_esp32.le_email[n] = '\0';
|
||||
lws_nvs_set_str(nvh, "acme-email", lws_esp32.le_email);
|
||||
nvs_commit(nvh);
|
||||
|
||||
nvs_close(nvh);
|
||||
|
||||
n = 1;
|
||||
b = strstr(in, ",\"staging\":\"");
|
||||
if (b)
|
||||
lwsl_notice("staging: %s\n", b);
|
||||
if (b && b[12] == 'f')
|
||||
n = 0;
|
||||
|
||||
lwsl_notice("cn: %s, email: %s, staging: %d\n", lws_esp32.le_dns, lws_esp32.le_email, n);
|
||||
|
||||
{
|
||||
struct lws_acme_cert_aging_args caa;
|
||||
|
||||
memset(&caa, 0, sizeof(caa));
|
||||
caa.vh = vhd->vhost;
|
||||
|
||||
caa.element_overrides[LWS_TLS_REQ_ELEMENT_COMMON_NAME] = lws_esp32.le_dns;
|
||||
caa.element_overrides[LWS_TLS_REQ_ELEMENT_EMAIL] = lws_esp32.le_email;
|
||||
|
||||
if (n)
|
||||
caa.element_overrides[LWS_TLS_SET_DIR_URL] =
|
||||
"https://acme-staging.api.letsencrypt.org/directory"; /* staging */
|
||||
else
|
||||
caa.element_overrides[LWS_TLS_SET_DIR_URL] =
|
||||
"https://acme-v01.api.letsencrypt.org/directory"; /* real */
|
||||
|
||||
lws_callback_vhost_protocols_vhost(vhd->vhost,
|
||||
LWS_CALLBACK_VHOST_CERT_AGING,
|
||||
(void *)&caa, 0);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
case LWS_CALLBACK_CLOSED:
|
||||
|
@ -802,7 +1024,7 @@ auton:
|
|||
pss->filename[0] = '\0';
|
||||
pss->file_length = 0;
|
||||
}
|
||||
|
||||
//puts((const char *)in);
|
||||
/* let it parse the POST data */
|
||||
if (lws_spa_process(pss->spa, in, len))
|
||||
return -1;
|
||||
|
@ -813,6 +1035,14 @@ auton:
|
|||
/* call to inform no more payload data coming */
|
||||
lws_spa_finalize(pss->spa);
|
||||
|
||||
for (n = 0; n < ARRAY_SIZE(param_names); n++)
|
||||
if (lws_spa_get_string(pss->spa, n))
|
||||
lwsl_notice(" Param %s: %s\n", param_names[n],
|
||||
lws_spa_get_string(pss->spa, n));
|
||||
else
|
||||
lwsl_notice(" Param %s: (none)\n",
|
||||
param_names[n]);
|
||||
|
||||
if (nvs_open("lws-station", NVS_READWRITE, &nvh) != ESP_OK) {
|
||||
lwsl_err("Unable to open nvs\n");
|
||||
break;
|
||||
|
@ -838,15 +1068,29 @@ auton:
|
|||
nvs_commit(nvh);
|
||||
}
|
||||
}
|
||||
|
||||
if (lws_spa_get_string(pss->spa, EPN_GROUP)) {
|
||||
if (lws_nvs_set_str(nvh, "group", lws_spa_get_string(pss->spa, EPN_GROUP)) != ESP_OK) {
|
||||
lwsl_err("Unable to store group in nvm\n");
|
||||
goto bail_nvs;
|
||||
}
|
||||
|
||||
nvs_commit(nvh);
|
||||
}
|
||||
|
||||
if (lws_spa_get_string(pss->spa, EPN_ROLE)) {
|
||||
if (lws_nvs_set_str(nvh, "role", lws_spa_get_string(pss->spa, EPN_ROLE)) != ESP_OK) {
|
||||
lwsl_err("Unable to store group in nvm\n");
|
||||
goto bail_nvs;
|
||||
}
|
||||
|
||||
nvs_commit(nvh);
|
||||
}
|
||||
|
||||
nvs_close(nvh);
|
||||
|
||||
pp = lws_spa_get_string(pss->spa, EPN_SERIAL);
|
||||
if (!pp)
|
||||
pp = "unknown";
|
||||
pss->result_len = snprintf(pss->result + LWS_PRE, sizeof(pss->result) - LWS_PRE - 1,
|
||||
"<html>Rebooting after storing certs...<br>connect to AP '<b>config-%s-%s</b>' and continue here: "
|
||||
"<a href=\"https://192.168.4.1\">https://192.168.4.1</a></html>",
|
||||
lws_esp32.model, pp);
|
||||
"<html>OK</html>");
|
||||
|
||||
if (lws_add_http_header_status(wsi, HTTP_STATUS_OK, &p, end))
|
||||
goto bail;
|
||||
|
@ -860,11 +1104,7 @@ auton:
|
|||
goto bail;
|
||||
|
||||
n = lws_write(wsi, start, p - start, LWS_WRITE_HTTP_HEADERS);
|
||||
if (n < 0)
|
||||
goto bail;
|
||||
|
||||
lws_callback_on_writable(wsi);
|
||||
break;
|
||||
goto bail;
|
||||
|
||||
case LWS_CALLBACK_HTTP_WRITEABLE:
|
||||
lwsl_debug("LWS_CALLBACK_HTTP_WRITEABLE: sending %d\n",
|
||||
|
|
Loading…
Add table
Reference in a new issue