mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
Add a 'esp_https_server' component allowing to use http_server with OpenSSL
This commit is contained in:
parent
a10fc02dd9
commit
4dd0fa61e9
7
components/esp_https_server/CMakeLists.txt
Normal file
7
components/esp_https_server/CMakeLists.txt
Normal file
@ -0,0 +1,7 @@
|
||||
set(COMPONENT_ADD_INCLUDEDIRS include)
|
||||
set(COMPONENT_SRCS "src/https_server.c")
|
||||
|
||||
set(COMPONENT_REQUIRES esp_http_server openssl)
|
||||
set(COMPONENT_PRIV_REQUIRES lwip)
|
||||
|
||||
register_component()
|
44
components/esp_https_server/README.md
Normal file
44
components/esp_https_server/README.md
Normal file
@ -0,0 +1,44 @@
|
||||
# HTTPS server
|
||||
|
||||
This component is built on top of `esp_http_server`. The HTTPS server takes advantage of hooks and
|
||||
function overrides in the regular HTTP server to provide encryption using OpenSSL.
|
||||
|
||||
All documentation for `esp_http_server` applies also to a server you create this way.
|
||||
|
||||
## Used APIs
|
||||
|
||||
The following API of `esp_http_server` should not be used with `esp_https_server`, as they are
|
||||
used internally to handle secure sessions and to maintain internal state:
|
||||
|
||||
- "send", "receive" and "pending" function overrides - secure socket handling
|
||||
- `httpd_set_sess_send_override()`
|
||||
- `httpd_set_sess_recv_override()`
|
||||
- `httpd_set_sess_pending_override()`
|
||||
- `httpd_set_send_override()`
|
||||
- `httpd_set_recv_override()`
|
||||
- `httpd_set_pending_override()`
|
||||
- "transport context" - both global and session
|
||||
- `httpd_sess_get_transport_ctx()` - returns SSL used for the session
|
||||
- `httpd_sess_set_transport_ctx()`
|
||||
- `httpd_get_global_transport_ctx()` - returns the shared SSL context
|
||||
- `httpd_config_t.global_transport_ctx`
|
||||
- `httpd_config_t.global_transport_ctx_free_fn`
|
||||
- `httpd_config_t.open_fn` - used to set up secure sockets
|
||||
|
||||
Everything else can be used without limitations.
|
||||
|
||||
## Usage
|
||||
|
||||
Please see the example `protocols/https_server` to learn how to set up a secure server.
|
||||
|
||||
Basically all you need is to generate a certificate, embed it in the firmware, and provide
|
||||
its pointers and lengths to the start function via the init struct.
|
||||
|
||||
The server can be started with or without SSL by changing a flag in the init struct.
|
||||
This could be used e.g. for testing or in trusted environments where you prefer speed over security.
|
||||
|
||||
## Performance
|
||||
|
||||
The initial session setup can take about two seconds, or more with slower clock speeds or more
|
||||
verbose logging. Subsequent requests through the open secure socket are much faster (down to under
|
||||
100 ms).
|
2
components/esp_https_server/component.mk
Normal file
2
components/esp_https_server/component.mk
Normal file
@ -0,0 +1,2 @@
|
||||
COMPONENT_SRCDIRS := src
|
||||
COMPONENT_ADD_INCLUDEDIRS := include
|
112
components/esp_https_server/include/esp_https_server.h
Normal file
112
components/esp_https_server/include/esp_https_server.h
Normal file
@ -0,0 +1,112 @@
|
||||
// Copyright 2018 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef _ESP_HTTPS_SERVER_H_
|
||||
#define _ESP_HTTPS_SERVER_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "esp_err.h"
|
||||
#include "esp_http_server.h"
|
||||
|
||||
/**
|
||||
* HTTPS server config struct
|
||||
*
|
||||
* Please use HTTPD_SSL_CONFIG_DEFAULT() to initialize it.
|
||||
*/
|
||||
struct httpd_ssl_config {
|
||||
/**
|
||||
* Underlying HTTPD server config
|
||||
*
|
||||
* Parameters like task stack size and priority can be adjusted here.
|
||||
*/
|
||||
httpd_config_t httpd;
|
||||
|
||||
/** CA certificate */
|
||||
const uint8_t *cacert_pem;
|
||||
|
||||
/** CA certificate byte length */
|
||||
size_t cacert_len;
|
||||
|
||||
/** Private key */
|
||||
const uint8_t *prvtkey_pem;
|
||||
|
||||
/** Private key byte length */
|
||||
size_t prvtkey_len;
|
||||
|
||||
/** Enable SSL (default true) */
|
||||
bool secure_enable;
|
||||
|
||||
/** Port used when SSL is enabled (default 443) */
|
||||
uint16_t port_secure;
|
||||
|
||||
/** Port used when SSL is disabled (default 80) */
|
||||
uint16_t port_insecure;
|
||||
};
|
||||
|
||||
typedef struct httpd_ssl_config httpd_ssl_config_t;
|
||||
|
||||
/**
|
||||
* Default config struct init
|
||||
*
|
||||
* (http_server default config had to be copied for customization)
|
||||
*
|
||||
* Notes:
|
||||
* - port is set when starting the server, according to 'secure_enable'
|
||||
* - one socket uses ~ 40kB RAM with SSL, we reduce the default socket count to 4
|
||||
* - SSL sockets are usually long-lived, closing LRU prevents pool exhaustion DOS
|
||||
* - Stack size may need adjustments depending on the user application
|
||||
*/
|
||||
#define HTTPD_SSL_CONFIG_DEFAULT() { \
|
||||
.httpd = { \
|
||||
.task_priority = tskIDLE_PRIORITY+5, \
|
||||
.stack_size = 10240, \
|
||||
.server_port = 0, \
|
||||
.ctrl_port = 32768, \
|
||||
.max_open_sockets = 4, \
|
||||
.max_uri_handlers = 8, \
|
||||
.max_resp_headers = 8, \
|
||||
.backlog_conn = 5, \
|
||||
.lru_purge_enable = true, \
|
||||
.recv_wait_timeout = 5, \
|
||||
.send_wait_timeout = 5, \
|
||||
.global_user_ctx = NULL, \
|
||||
.global_user_ctx_free_fn = NULL, \
|
||||
.global_transport_ctx = NULL, \
|
||||
.global_transport_ctx_free_fn = NULL, \
|
||||
.open_fn = NULL, \
|
||||
.close_fn = NULL, \
|
||||
}, \
|
||||
.secure_enable = true, \
|
||||
.port_secure = 443, \
|
||||
.port_insecure = 80, \
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a SSL capable HTTP server (secure mode may be disabled in config)
|
||||
*
|
||||
* @param[in,out] config - server config, must not be const. Does not have to stay valid after
|
||||
* calling this function.
|
||||
* @param[out] handle - storage for the server handle, must be a valid pointer
|
||||
* @return success
|
||||
*/
|
||||
esp_err_t httpd_ssl_start(httpd_handle_t *handle, httpd_ssl_config_t *config);
|
||||
|
||||
/**
|
||||
* Stop the server. Blocks until the server is shut down.
|
||||
*
|
||||
* @param[in] handle
|
||||
*/
|
||||
void httpd_ssl_stop(httpd_handle_t handle);
|
||||
|
||||
#endif // _ESP_HTTPS_SERVER_H_
|
220
components/esp_https_server/src/https_server.c
Normal file
220
components/esp_https_server/src/https_server.c
Normal file
@ -0,0 +1,220 @@
|
||||
// Copyright 2018 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <string.h>
|
||||
#include "esp_https_server.h"
|
||||
#include "openssl/ssl.h"
|
||||
#include "esp_log.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
const static char *TAG = "esp_https_server";
|
||||
|
||||
/**
|
||||
* SSL socket close handler
|
||||
*
|
||||
* @param[in] ctx - session transport context (SSL context we stored there)
|
||||
*/
|
||||
static void httpd_ssl_close(void *ctx)
|
||||
{
|
||||
assert(ctx != NULL);
|
||||
SSL_shutdown(ctx);
|
||||
SSL_free(ctx);
|
||||
ESP_LOGD(TAG, "Secure socket closed");
|
||||
}
|
||||
|
||||
/**
|
||||
* SSL socket pending-check function
|
||||
*
|
||||
* @param server
|
||||
* @param sockfd
|
||||
* @return number of pending bytes, negative on error
|
||||
*/
|
||||
static int httpd_ssl_pending(httpd_handle_t server, int sockfd)
|
||||
{
|
||||
SSL *ssl = httpd_sess_get_transport_ctx(server, sockfd);
|
||||
assert(ssl != NULL);
|
||||
return SSL_pending(ssl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Receive from a SSL socket
|
||||
*
|
||||
* @param server
|
||||
* @param sockfd
|
||||
* @param buf
|
||||
* @param buf_len
|
||||
* @param flags
|
||||
* @return bytes read, negative on error
|
||||
*/
|
||||
static int httpd_ssl_recv(httpd_handle_t server, int sockfd, char *buf, size_t buf_len, int flags)
|
||||
{
|
||||
SSL *ssl = httpd_sess_get_transport_ctx(server, sockfd);
|
||||
assert(ssl != NULL);
|
||||
return SSL_read(ssl, buf, buf_len);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send to a SSL socket
|
||||
*
|
||||
* @param server
|
||||
* @param sockfd
|
||||
* @param buf
|
||||
* @param buf_len
|
||||
* @param flags
|
||||
* @return bytes sent, negative on error
|
||||
*/
|
||||
static int httpd_ssl_send(httpd_handle_t server, int sockfd, const char *buf, size_t buf_len, int flags)
|
||||
{
|
||||
SSL *ssl = httpd_sess_get_transport_ctx(server, sockfd);
|
||||
assert(ssl != NULL);
|
||||
return SSL_write(ssl, buf, buf_len);
|
||||
}
|
||||
|
||||
/**
|
||||
* Open a SSL socket for the server.
|
||||
* The fd is already open and ready to read / write raw data.
|
||||
*
|
||||
* @param server
|
||||
* @param sockfd - raw socket fd
|
||||
* @return success
|
||||
*/
|
||||
static esp_err_t httpd_ssl_open(httpd_handle_t server, int sockfd)
|
||||
{
|
||||
assert(server != NULL);
|
||||
|
||||
// Retrieve the SSL context from the global context field (set in config)
|
||||
SSL_CTX *global_ctx = httpd_get_global_transport_ctx(server);
|
||||
assert(global_ctx != NULL);
|
||||
|
||||
SSL *ssl = SSL_new(global_ctx);
|
||||
if (NULL == ssl) {
|
||||
ESP_LOGE(TAG, "SSL_new ret NULL (out of memory)");
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
if (1 != SSL_set_fd(ssl, sockfd)) {
|
||||
ESP_LOGE(TAG, "fail to set SSL fd");
|
||||
goto teardown;
|
||||
}
|
||||
|
||||
ESP_LOGD(TAG, "SSL accept");
|
||||
if (1 != SSL_accept(ssl)) {
|
||||
ESP_LOGW(TAG, "fail to SSL_accept - handshake error");
|
||||
goto teardown;
|
||||
}
|
||||
|
||||
// Store the SSL session into the context field of the HTTPD session object
|
||||
httpd_sess_set_transport_ctx(server, sockfd, ssl, httpd_ssl_close);
|
||||
|
||||
// Set rx/tx/pending override functions
|
||||
httpd_set_sess_send_override(server, sockfd, httpd_ssl_send);
|
||||
httpd_set_sess_recv_override(server, sockfd, httpd_ssl_recv);
|
||||
httpd_set_sess_pending_override(server, sockfd, httpd_ssl_pending);
|
||||
|
||||
// all access should now go through SSL
|
||||
|
||||
ESP_LOGD(TAG, "Secure socket open");
|
||||
|
||||
return ESP_OK;
|
||||
|
||||
teardown:
|
||||
SSL_free(ssl);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tear down the HTTPD global transport context
|
||||
*
|
||||
* @param ctx
|
||||
*/
|
||||
static void free_secure_context(void *ctx)
|
||||
{
|
||||
assert(ctx != NULL);
|
||||
|
||||
ESP_LOGI(TAG, "Server shuts down, releasing SSL context");
|
||||
SSL_CTX_free(ctx);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and perform basic init of a SSL_CTX, or return NULL on failure
|
||||
*
|
||||
* @return ctx or null
|
||||
*/
|
||||
static SSL_CTX *create_secure_context(const struct httpd_ssl_config *config)
|
||||
{
|
||||
SSL_CTX *ctx = NULL;
|
||||
|
||||
ESP_LOGD(TAG, "SSL server context create");
|
||||
ctx = SSL_CTX_new(TLS_server_method());
|
||||
if (NULL != ctx) {
|
||||
//region SSL ctx alloc'd
|
||||
ESP_LOGD(TAG, "SSL ctx set own cert");
|
||||
if (SSL_CTX_use_certificate_ASN1(ctx, config->cacert_len, config->cacert_pem)
|
||||
&& SSL_CTX_use_PrivateKey_ASN1(0, ctx, config->prvtkey_pem, (long) config->prvtkey_len)) {
|
||||
return ctx;
|
||||
}
|
||||
else {
|
||||
ESP_LOGE(TAG, "Failed to set certificate");
|
||||
SSL_CTX_free(ctx);
|
||||
ctx = NULL;
|
||||
}
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Failed to create SSL context");
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/** Start the server */
|
||||
esp_err_t httpd_ssl_start(httpd_handle_t *pHandle, struct httpd_ssl_config *config)
|
||||
{
|
||||
assert(config != NULL);
|
||||
assert(pHandle != NULL);
|
||||
|
||||
ESP_LOGI(TAG, "Starting server");
|
||||
|
||||
if (config->secure_enable) {
|
||||
SSL_CTX *ctx = create_secure_context(config);
|
||||
if (!ctx) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
ESP_LOGD(TAG, "SSL context ready");
|
||||
|
||||
// set SSL specific config
|
||||
config->httpd.global_transport_ctx = ctx;
|
||||
config->httpd.global_transport_ctx_free_fn = free_secure_context;
|
||||
config->httpd.open_fn = httpd_ssl_open; // the open function configures the created SSL sessions
|
||||
|
||||
config->httpd.server_port = config->port_secure;
|
||||
} else {
|
||||
ESP_LOGD(TAG, "SSL disabled, using plain HTTP");
|
||||
config->httpd.server_port = config->port_insecure;
|
||||
}
|
||||
|
||||
httpd_handle_t handle = NULL;
|
||||
|
||||
esp_err_t ret = httpd_start(&handle, &config->httpd);
|
||||
if (ret != ESP_OK) return ret;
|
||||
|
||||
*pHandle = handle;
|
||||
|
||||
ESP_LOGI(TAG, "Server listening on port %d", config->httpd.server_port);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/** Stop the server */
|
||||
void httpd_ssl_stop(httpd_handle_t handle)
|
||||
{
|
||||
httpd_stop(handle);
|
||||
}
|
6
examples/protocols/https_server/CMakeLists.txt
Normal file
6
examples/protocols/https_server/CMakeLists.txt
Normal file
@ -0,0 +1,6 @@
|
||||
# The following lines of boilerplate have to be in your project's CMakeLists
|
||||
# in this exact order for cmake to work correctly
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
project(https_server)
|
9
examples/protocols/https_server/Makefile
Normal file
9
examples/protocols/https_server/Makefile
Normal file
@ -0,0 +1,9 @@
|
||||
#
|
||||
# This is a project Makefile. It is assumed the directory this Makefile resides in is a
|
||||
# project subdirectory.
|
||||
#
|
||||
|
||||
PROJECT_NAME := https_server
|
||||
|
||||
include $(IDF_PATH)/make/project.mk
|
||||
|
15
examples/protocols/https_server/README.md
Normal file
15
examples/protocols/https_server/README.md
Normal file
@ -0,0 +1,15 @@
|
||||
# HTTP server with SSL support using OpenSSL
|
||||
|
||||
This example creates a SSL server that returns a simple HTML page when you visit its root URL.
|
||||
|
||||
See the `esp_https_server` component documentation for details.
|
||||
|
||||
## Certificates
|
||||
|
||||
You will need to approve a security exception in your browser. This is because of a self signed
|
||||
certificate; this will be always the case, unless you preload the CA root into your browser/system
|
||||
as trusted.
|
||||
|
||||
You can generate a new certificate using the OpenSSL command line tool as shown in the script
|
||||
`main/certs/gencert.sh`. It is **strongly recommended** to not reuse the example certificate in
|
||||
your application; it is included only for demonstration.
|
8
examples/protocols/https_server/main/CMakeLists.txt
Normal file
8
examples/protocols/https_server/main/CMakeLists.txt
Normal file
@ -0,0 +1,8 @@
|
||||
set(COMPONENT_SRCS "main.c")
|
||||
set(COMPONENT_ADD_INCLUDEDIRS ".")
|
||||
|
||||
set(COMPONENT_EMBED_TXTFILES
|
||||
"certs/cacert.pem"
|
||||
"certs/prvtkey.pem")
|
||||
|
||||
register_component()
|
16
examples/protocols/https_server/main/Kconfig.projbuild
Normal file
16
examples/protocols/https_server/main/Kconfig.projbuild
Normal file
@ -0,0 +1,16 @@
|
||||
menu "Example Configuration"
|
||||
|
||||
config WIFI_SSID
|
||||
string "WiFi SSID"
|
||||
default "myssid"
|
||||
help
|
||||
SSID (network name) for the example to connect to.
|
||||
|
||||
config WIFI_PASSWORD
|
||||
string "WiFi Password"
|
||||
default "mypassword"
|
||||
help
|
||||
WiFi password (WPA or WPA2) for the example to use.
|
||||
Can be left blank if the network has no security set.
|
||||
|
||||
endmenu
|
19
examples/protocols/https_server/main/certs/cacert.pem
Normal file
19
examples/protocols/https_server/main/certs/cacert.pem
Normal file
@ -0,0 +1,19 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDKzCCAhOgAwIBAgIUBxM3WJf2bP12kAfqhmhhjZWv0ukwDQYJKoZIhvcNAQEL
|
||||
BQAwJTEjMCEGA1UEAwwaRVNQMzIgSFRUUFMgc2VydmVyIGV4YW1wbGUwHhcNMTgx
|
||||
MDE3MTEzMjU3WhcNMjgxMDE0MTEzMjU3WjAlMSMwIQYDVQQDDBpFU1AzMiBIVFRQ
|
||||
UyBzZXJ2ZXIgZXhhbXBsZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
|
||||
ALBint6nP77RCQcmKgwPtTsGK0uClxg+LwKJ3WXuye3oqnnjqJCwMEneXzGdG09T
|
||||
sA0SyNPwrEgebLCH80an3gWU4pHDdqGHfJQa2jBL290e/5L5MB+6PTs2NKcojK/k
|
||||
qcZkn58MWXhDW1NpAnJtjVniK2Ksvr/YIYSbyD+JiEs0MGxEx+kOl9d7hRHJaIzd
|
||||
GF/vO2pl295v1qXekAlkgNMtYIVAjUy9CMpqaQBCQRL+BmPSJRkXBsYk8GPnieS4
|
||||
sUsp53DsNvCCtWDT6fd9D1v+BB6nDk/FCPKhtjYOwOAZlX4wWNSZpRNr5dfrxKsb
|
||||
jAn4PCuR2akdF4G8WLUeDWECAwEAAaNTMFEwHQYDVR0OBBYEFMnmdJKOEepXrHI/
|
||||
ivM6mVqJgAX8MB8GA1UdIwQYMBaAFMnmdJKOEepXrHI/ivM6mVqJgAX8MA8GA1Ud
|
||||
EwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBADiXIGEkSsN0SLSfCF1VNWO3
|
||||
emBurfOcDq4EGEaxRKAU0814VEmU87btIDx80+z5Dbf+GGHCPrY7odIkxGNn0DJY
|
||||
W1WcF+DOcbiWoUN6DTkAML0SMnp8aGj9ffx3x+qoggT+vGdWVVA4pgwqZT7Ybntx
|
||||
bkzcNFW0sqmCv4IN1t4w6L0A87ZwsNwVpre/j6uyBw7s8YoJHDLRFT6g7qgn0tcN
|
||||
ZufhNISvgWCVJQy/SZjNBHSpnIdCUSJAeTY2mkM4sGxY0Widk8LnjydxZUSxC3Nl
|
||||
hb6pnMh3jRq4h0+5CZielA4/a+TdrNPv/qok67ot/XJdY3qHCCd8O2b14OVq9jo=
|
||||
-----END CERTIFICATE-----
|
8
examples/protocols/https_server/main/certs/gencert.sh
Normal file
8
examples/protocols/https_server/main/certs/gencert.sh
Normal file
@ -0,0 +1,8 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Example command to generate a new certificate in the correct format.
|
||||
# Expiry time and metadata fields can be adjusted in the invocation.
|
||||
|
||||
# Please see the openssl man pages (man openssl-req) for more details
|
||||
|
||||
openssl req -newkey rsa:2048 -nodes -keyout prvtkey.pem -x509 -days 3650 -out cacert.pem -subj "/CN=ESP32 HTTPS server example"
|
28
examples/protocols/https_server/main/certs/prvtkey.pem
Normal file
28
examples/protocols/https_server/main/certs/prvtkey.pem
Normal file
@ -0,0 +1,28 @@
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCwYp7epz++0QkH
|
||||
JioMD7U7BitLgpcYPi8Cid1l7snt6Kp546iQsDBJ3l8xnRtPU7ANEsjT8KxIHmyw
|
||||
h/NGp94FlOKRw3ahh3yUGtowS9vdHv+S+TAfuj07NjSnKIyv5KnGZJ+fDFl4Q1tT
|
||||
aQJybY1Z4itirL6/2CGEm8g/iYhLNDBsRMfpDpfXe4URyWiM3Rhf7ztqZdveb9al
|
||||
3pAJZIDTLWCFQI1MvQjKamkAQkES/gZj0iUZFwbGJPBj54nkuLFLKedw7DbwgrVg
|
||||
0+n3fQ9b/gQepw5PxQjyobY2DsDgGZV+MFjUmaUTa+XX68SrG4wJ+DwrkdmpHReB
|
||||
vFi1Hg1hAgMBAAECggEAaTCnZkl/7qBjLexIryC/CBBJyaJ70W1kQ7NMYfniWwui
|
||||
f0aRxJgOdD81rjTvkINsPp+xPRQO6oOadjzdjImYEuQTqrJTEUnntbu924eh+2D9
|
||||
Mf2CAanj0mglRnscS9mmljZ0KzoGMX6Z/EhnuS40WiJTlWlH6MlQU/FDnwC6U34y
|
||||
JKy6/jGryfsx+kGU/NRvKSru6JYJWt5v7sOrymHWD62IT59h3blOiP8GMtYKeQlX
|
||||
49om9Mo1VTIFASY3lrxmexbY+6FG8YO+tfIe0tTAiGrkb9Pz6tYbaj9FjEWOv4Vc
|
||||
+3VMBUVdGJjgqvE8fx+/+mHo4Rg69BUPfPSrpEg7sQKBgQDlL85G04VZgrNZgOx6
|
||||
pTlCCl/NkfNb1OYa0BELqWINoWaWQHnm6lX8YjrUjwRpBF5s7mFhguFjUjp/NW6D
|
||||
0EEg5BmO0ePJ3dLKSeOA7gMo7y7kAcD/YGToqAaGljkBI+IAWK5Su5yldrECTQKG
|
||||
YnMKyQ1MWUfCYEwHtPvFvE5aPwKBgQDFBWXekpxHIvt/B41Cl/TftAzE7/f58JjV
|
||||
MFo/JCh9TDcH6N5TMTRS1/iQrv5M6kJSSrHnq8pqDXOwfHLwxetpk9tr937VRzoL
|
||||
CuG1Ar7c1AO6ujNnAEmUVC2DppL/ck5mRPWK/kgLwZSaNcZf8sydRgphsW1ogJin
|
||||
7g0nGbFwXwKBgQCPoZY07Pr1TeP4g8OwWTu5F6dSvdU2CAbtZthH5q98u1n/cAj1
|
||||
noak1Srpa3foGMTUn9CHu+5kwHPIpUPNeAZZBpq91uxa5pnkDMp3UrLIRJ2uZyr8
|
||||
4PxcknEEh8DR5hsM/IbDcrCJQglM19ZtQeW3LKkY4BsIxjDf45ymH407IQKBgE/g
|
||||
Ul6cPfOxQRlNLH4VMVgInSyyxWx1mODFy7DRrgCuh5kTVh+QUVBM8x9lcwAn8V9/
|
||||
nQT55wR8E603pznqY/jX0xvAqZE6YVPcw4kpZcwNwL1RhEl8GliikBlRzUL3SsW3
|
||||
q30AfqEViHPE3XpE66PPo6Hb1ymJCVr77iUuC3wtAoGBAIBrOGunv1qZMfqmwAY2
|
||||
lxlzRgxgSiaev0lTNxDzZkmU/u3dgdTwJ5DDANqPwJc6b8SGYTp9rQ0mbgVHnhIB
|
||||
jcJQBQkTfq6Z0H6OoTVi7dPs3ibQJFrtkoyvYAbyk36quBmNRjVh6rc8468bhXYr
|
||||
v/t+MeGJP/0Zw8v/X2CFll96
|
||||
-----END PRIVATE KEY-----
|
7
examples/protocols/https_server/main/component.mk
Normal file
7
examples/protocols/https_server/main/component.mk
Normal file
@ -0,0 +1,7 @@
|
||||
#
|
||||
# "main" pseudo-component makefile.
|
||||
#
|
||||
# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)
|
||||
|
||||
COMPONENT_EMBED_TXTFILES := certs/cacert.pem
|
||||
COMPONENT_EMBED_TXTFILES += certs/prvtkey.pem
|
150
examples/protocols/https_server/main/main.c
Normal file
150
examples/protocols/https_server/main/main.c
Normal file
@ -0,0 +1,150 @@
|
||||
/* Simple HTTP + SSL Server Example
|
||||
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
|
||||
#include <esp_wifi.h>
|
||||
#include <esp_event_loop.h>
|
||||
#include <esp_log.h>
|
||||
#include <esp_system.h>
|
||||
#include <nvs_flash.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
#include <esp_https_server.h>
|
||||
|
||||
/* A simple example that demonstrates how to create GET and POST
|
||||
* handlers for the web server.
|
||||
* The examples use simple WiFi configuration that you can set via
|
||||
* 'make menuconfig'.
|
||||
* If you'd rather not, just change the below entries to strings
|
||||
* with the config you want -
|
||||
* ie. #define EXAMPLE_WIFI_SSID "mywifissid"
|
||||
*/
|
||||
#define EXAMPLE_WIFI_SSID CONFIG_WIFI_SSID
|
||||
#define EXAMPLE_WIFI_PASS CONFIG_WIFI_PASSWORD
|
||||
|
||||
static const char *TAG="APP";
|
||||
|
||||
|
||||
/* An HTTP GET handler */
|
||||
esp_err_t root_get_handler(httpd_req_t *req)
|
||||
{
|
||||
httpd_resp_set_type(req, "text/html");
|
||||
httpd_resp_send(req, "<h1>Hello Secure World!</h1>", -1); // -1 = use strlen()
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
const httpd_uri_t root = {
|
||||
.uri = "/",
|
||||
.method = HTTP_GET,
|
||||
.handler = root_get_handler
|
||||
};
|
||||
|
||||
|
||||
httpd_handle_t start_webserver(void)
|
||||
{
|
||||
httpd_handle_t server = NULL;
|
||||
|
||||
// Start the httpd server
|
||||
ESP_LOGI(TAG, "Starting server");
|
||||
|
||||
httpd_ssl_config_t conf = HTTPD_SSL_CONFIG_DEFAULT();
|
||||
|
||||
extern const unsigned char cacert_pem_start[] asm("_binary_cacert_pem_start");
|
||||
extern const unsigned char cacert_pem_end[] asm("_binary_cacert_pem_end");
|
||||
conf.cacert_pem = cacert_pem_start;
|
||||
conf.cacert_len = cacert_pem_end - cacert_pem_start;
|
||||
|
||||
extern const unsigned char prvtkey_pem_start[] asm("_binary_prvtkey_pem_start");
|
||||
extern const unsigned char prvtkey_pem_end[] asm("_binary_prvtkey_pem_end");
|
||||
conf.prvtkey_pem = prvtkey_pem_start;
|
||||
conf.prvtkey_len = prvtkey_pem_end - prvtkey_pem_start;
|
||||
|
||||
esp_err_t ret = httpd_ssl_start(&server, &conf);
|
||||
if (ESP_OK != ret) {
|
||||
ESP_LOGI(TAG, "Error starting server!");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Set URI handlers
|
||||
ESP_LOGI(TAG, "Registering URI handlers");
|
||||
httpd_register_uri_handler(server, &root);
|
||||
return server;
|
||||
}
|
||||
|
||||
void stop_webserver(httpd_handle_t server)
|
||||
{
|
||||
// Stop the httpd server
|
||||
httpd_ssl_stop(server);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// ------------------------- application boilerplate ------------------------
|
||||
|
||||
static esp_err_t event_handler(void *ctx, system_event_t *event)
|
||||
{
|
||||
httpd_handle_t *server = (httpd_handle_t *) ctx;
|
||||
|
||||
switch(event->event_id) {
|
||||
case SYSTEM_EVENT_STA_START:
|
||||
ESP_LOGI(TAG, "SYSTEM_EVENT_STA_START");
|
||||
ESP_ERROR_CHECK(esp_wifi_connect());
|
||||
break;
|
||||
case SYSTEM_EVENT_STA_GOT_IP:
|
||||
ESP_LOGI(TAG, "SYSTEM_EVENT_STA_GOT_IP");
|
||||
ESP_LOGI(TAG, "Got IP: '%s'",
|
||||
ip4addr_ntoa(&event->event_info.got_ip.ip_info.ip));
|
||||
|
||||
/* Start the web server */
|
||||
if (*server == NULL) {
|
||||
*server = start_webserver();
|
||||
}
|
||||
break;
|
||||
case SYSTEM_EVENT_STA_DISCONNECTED:
|
||||
ESP_LOGI(TAG, "SYSTEM_EVENT_STA_DISCONNECTED");
|
||||
ESP_ERROR_CHECK(esp_wifi_connect());
|
||||
|
||||
/* Stop the web server */
|
||||
if (*server) {
|
||||
stop_webserver(*server);
|
||||
*server = NULL;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static void initialise_wifi(void *arg)
|
||||
{
|
||||
tcpip_adapter_init();
|
||||
ESP_ERROR_CHECK(esp_event_loop_init(event_handler, arg));
|
||||
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
|
||||
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
|
||||
ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM));
|
||||
wifi_config_t wifi_config = {
|
||||
.sta = {
|
||||
.ssid = EXAMPLE_WIFI_SSID,
|
||||
.password = EXAMPLE_WIFI_PASS,
|
||||
},
|
||||
};
|
||||
ESP_LOGI(TAG, "Setting WiFi configuration SSID %s...", wifi_config.sta.ssid);
|
||||
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
|
||||
ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config));
|
||||
ESP_ERROR_CHECK(esp_wifi_start());
|
||||
}
|
||||
|
||||
void app_main()
|
||||
{
|
||||
static httpd_handle_t server = NULL;
|
||||
ESP_ERROR_CHECK(nvs_flash_init());
|
||||
initialise_wifi(&server);
|
||||
}
|
Loading…
Reference in New Issue
Block a user