bakalarka/components/https_server/https_server.c
2020-04-06 16:37:01 +02:00

323 lines
9.1 KiB
C

/* 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.h>
#include <esp_log.h>
#include <esp_system.h>
#include <nvs_flash.h>
#include <sys/param.h>
#include "esp_netif.h"
#include "esp_eth.h"
#include "esp_console.h"
#include "string.h"
#include "url_decoder.h"
#include "file.h"
#include "ca.h"
#include <esp_https_server.h>
/* A simple example that demonstrates how to create GET and POST
* handlers and start an HTTPS server.
*/
/*
struct pass_args
{
int argc;
char **argv;
};
//struct pass_args global_arg_task;
*/
static const char *TAG = "server";
TaskHandle_t xHandleServer = NULL;
/* HTTP GET handler
formular pre vlozenie csr requestu
*/
static esp_err_t root_get_handler(httpd_req_t *req)
{
httpd_resp_set_type(req, "text/html");
httpd_resp_send(req, "<form action=\"/echo\" method=\"post\">\n"
" <label for=\"csr\">CSR:</label><br>\n"
" <input type=\"text\" id=\"csr\" name=\"csr\" value=\"\"><br>\n"
" <input type=\"submit\" value=\"Submit\">\n"
"</form>", -1); // -1 = pouziva strlen()
return ESP_OK;
}
/* HTTP POST handler
spustenie po stlaceni Submit z root handleru
generuje subor .crt
*/
static esp_err_t echo_post_handler(httpd_req_t *req)
{
/*Nacitanie vstupu*/
char buf[2000];
int ret, remaining = req->content_len;
memset(buf,'\0',sizeof(buf));
while (remaining > 0) {
/* Read the data for the request */
if ((ret = httpd_req_recv(req, buf,
MIN(remaining, sizeof(buf)))) <= 0) {
if (ret == HTTPD_SOCK_ERR_TIMEOUT) {
/* Retry receiving if timeout occurred */
continue;
}
return ESP_FAIL;
}
/* Vypis dat do konzoly */
ESP_LOGI(TAG, "=========== RECEIVED DATA ==========");
ESP_LOGI(TAG, "%.*s", ret, buf);
ESP_LOGI(TAG, "====================================");
/*odstranenie premennej z textu*/
const char *url = &buf[4];
char out[strlen(url) + 1];
printf("length: %d\n", decode(url, 0));
/*Dekodovanie url textu do normalnej podoby*/
printf("%s\n",decode(url, out) < 0 ? "bad string" : out);
char buffered_out[strlen(url) + 1];
char formatted_out[strlen(url) + 1];read_file("/spiffs/user.crt");
memset(buffered_out, '\0', strlen(url));
memset(formatted_out, '\0', strlen(url));
char* csr_begin = "-----BEGIN CERTIFICATE REQUEST-----";
char* csr_end = "-----END CERTIFICATE REQUEST-----";
strncpy(buffered_out, &out[strlen(csr_begin)], strlen(out) - strlen(csr_begin) - strlen(csr_end));
/*formatovanie textu novým riadkom kvoli standardu*/
char* token;
token = strtok(buffered_out, " ");
strcat(formatted_out,csr_begin);
strcat(formatted_out,"\r\n");
while (token != NULL)
{
strcat(formatted_out,token);
strcat(formatted_out,"\r\n");
token = strtok(NULL, " ");
}
strcat(formatted_out,csr_end);
printf("%s",formatted_out);
//Hodnoty predavane ulohe cert_write pre generovanie certifikatov pod CA
const int argc = 5;
const char* argv[] = {"write_cert","request_file=/spiffs/certsignreq.csr","issuer_key=/spiffs/keyfile.key","issuer_crt=/spiffs/ca.crt","output_file=/spiffs/user.crt"};
//global_arg_task.argc = argc;
//global_arg_task.argv = argv;
/*
int ii;
global_arg_task.argv = malloc(argc * sizeof *global_arg_task.argv);
for(ii = 0; ii < argc; ii++) {
global_arg_task.argv[ii] = malloc(strlen(argv[ii])+1);
strcpy(global_arg_task.argv[ii], argv[ii]);
}
*/ /*Ulozenie CSR requestu*/
create_file("/spiffs/certsignreq.csr",formatted_out);
/*Volanie funkcie pre vytvorenie ulohy podpisu certifikatu*/
task_create_ca(argc,argv);
memset(buf,'\0',sizeof(buf)-1);
memset(buffered_out, '\0', strlen(url));
memset(formatted_out, '\0', strlen(url));
vTaskDelay(400);
/*nahradenie LF znaku za CRLF v certifikate kvoli HTTP serveru */
FILE* f = fopen("/spiffs/user.crt", "r");
if(f!=NULL){
while(fgets(buffered_out, sizeof(buffered_out)-1, f)){
strcat(buf,buffered_out);
}
}
fclose(f);
/*Rozdelenie certifikatu do tokenov*/
token = NULL;
token = strtok(buf, "\n");
while (token != NULL)
{
strcat(formatted_out,token);
strcat(formatted_out,"\r\n");
token = strtok(NULL, "\n");
}
/*Nastavenie typu suboru*/
httpd_resp_set_type(req, "application/x-x509-user-cert");
/*Odoslanie dat*/
httpd_resp_send_chunk(req, formatted_out, strlen(formatted_out));
remaining -= ret;
}
/*Ukoncenie prenosu dat*/
httpd_resp_send_chunk(req, NULL, 0);
return ESP_OK;
}
/*Registrovanie URI*/
static const httpd_uri_t echo = {
.uri = "/echo",
.method = HTTP_POST,
.handler = echo_post_handler,
.user_ctx = NULL
};
/*Registrovanie URI*/
static const httpd_uri_t root = {
.uri = "/",
.method = HTTP_GET,
.handler = root_get_handler
};
static httpd_handle_t start_webserver(void)
{
httpd_handle_t server = NULL;
// Start the httpd server
ESP_LOGI(TAG, "Starting server");
//Inicializacia konfiguracie pre http server
httpd_ssl_config_t conf = HTTPD_SSL_CONFIG_DEFAULT();
conf.httpd.stack_size = 12000;
//pridanie certifikatu do konfiguracie
unsigned char *cacert_pem_start = calloc(1200,sizeof(unsigned char));//[1025];
//memset(cacert_pem_start,'\0',1025);
//char line_buffer[66];
FILE* fd = fopen("/spiffs/server.crt", "r");
fseek(fd, 0, SEEK_END);
long int size = ftell(fd);
fseek(fd, 0, SEEK_SET);
int bytes_read = fread(cacert_pem_start, sizeof(unsigned char), size, fd);
/*
if(fd!=NULL){
while(fgets(line_buffer, sizeof(line_buffer)-1, fd)){
strcat(cacert_pem_start,line_buffer);
}
}
*/
fclose(fd);
conf.cacert_pem = (const unsigned char*)cacert_pem_start;
printf("%s", conf.cacert_pem);
conf.cacert_len = size+1;
//pridanie sukromneho kluca do konfiguracie
unsigned char *prvtkey_pem_start =calloc(1800,sizeof(unsigned char));
//memset(prvtkey_pem_start,'\0',2050);
// memset(line_buffer,'\0',66);
fd = fopen("/spiffs/server_key.key", "rb");
/*
if(fd!=NULL){
while(fgets(line_buffer, sizeof(line_buffer)-1, fd)){
strcat((char*)prvtkey_pem_start,line_buffer);
}
}
*/
fseek(fd, 0, SEEK_END);
size = ftell(fd);
fseek(fd, 0, SEEK_SET);
bytes_read = fread(prvtkey_pem_start, sizeof(unsigned char), size, fd);
fclose(fd);
conf.prvtkey_pem = prvtkey_pem_start;
conf.prvtkey_len = size+1;
//vytvorenie HTTP + SSL servera
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);
httpd_register_uri_handler(server, &echo);
return server;
}
static void stop_webserver(httpd_handle_t server)
{
// Stop the httpd server
httpd_ssl_stop(server);
}
static void disconnect_handler(void* arg, esp_event_base_t event_base,
int32_t event_id, void* event_data)
{
httpd_handle_t* server = (httpd_handle_t*) arg;
if (*server) {
stop_webserver(*server);
*server = NULL;
}
}
static void connect_handler(void* arg, esp_event_base_t event_base,
int32_t event_id, void* event_data)
{
httpd_handle_t* server = (httpd_handle_t*) arg;
if (*server == NULL) {
*server = start_webserver();
}
}
static void connect(void)
{
static httpd_handle_t server = NULL;
// ESP_ERROR_CHECK(nvs_flash_init());
// ESP_ERROR_CHECK(esp_netif_init());
// ESP_ERROR_CHECK(esp_event_loop_create_default());
/* Register event handlers to start server when Wi-Fi or Ethernet is connected,
* and stop server when disconnection happens.
*/
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &connect_handler, &server));
ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_DISCONNECTED, &disconnect_handler, &server));
}
static void server_off(){
vTaskDelete(xHandleServer);
}
/*Registrovanie prikazov pre konzolu*/
void register_server(void)
{
const esp_console_cmd_t webserver_on = {
.command = "server_on",
.help = "HTTPS server",
.hint = NULL,
.func = &connect,
.argtable = NULL
};
const esp_console_cmd_t webserver_off = {
.command = "server_off",
.help = "HTTPS server",
.hint = NULL,
.func = &server_off,
.argtable = NULL
};
ESP_ERROR_CHECK(esp_console_cmd_register(&webserver_on));
ESP_ERROR_CHECK(esp_console_cmd_register(&webserver_off));
}