mirror of
https://github.com/guanzhi/GmSSL.git
synced 2026-08-06 11:53:39 +08:00
Add -www HTTP echo mode to TLCP and TLS server commands
This commit is contained in:
@@ -1026,7 +1026,7 @@ endif()
|
|||||||
#
|
#
|
||||||
set(CPACK_PACKAGE_NAME "GmSSL")
|
set(CPACK_PACKAGE_NAME "GmSSL")
|
||||||
set(CPACK_PACKAGE_VENDOR "GmSSL develop team")
|
set(CPACK_PACKAGE_VENDOR "GmSSL develop team")
|
||||||
set(CPACK_PACKAGE_VERSION "3.3.0-dev.1175")
|
set(CPACK_PACKAGE_VERSION "3.3.0-dev.1176")
|
||||||
set(CPACK_PACKAGE_DESCRIPTION_FILE ${PROJECT_SOURCE_DIR}/README.md)
|
set(CPACK_PACKAGE_DESCRIPTION_FILE ${PROJECT_SOURCE_DIR}/README.md)
|
||||||
set(CPACK_NSIS_MODIFY_PATH ON)
|
set(CPACK_NSIS_MODIFY_PATH ON)
|
||||||
include(CPack)
|
include(CPack)
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ extern "C" {
|
|||||||
|
|
||||||
|
|
||||||
#define GMSSL_VERSION_NUM 30300
|
#define GMSSL_VERSION_NUM 30300
|
||||||
#define GMSSL_VERSION_STR "GmSSL 3.3.0-dev.1175"
|
#define GMSSL_VERSION_STR "GmSSL 3.3.0-dev.1176"
|
||||||
|
|
||||||
int gmssl_version_num(void);
|
int gmssl_version_num(void);
|
||||||
const char *gmssl_version_str(void);
|
const char *gmssl_version_str(void);
|
||||||
|
|||||||
@@ -31,9 +31,10 @@
|
|||||||
#include <gmssl/tls.h>
|
#include <gmssl/tls.h>
|
||||||
#include <gmssl/error.h>
|
#include <gmssl/error.h>
|
||||||
#include "passwd.h"
|
#include "passwd.h"
|
||||||
|
#include "tls_server_http.h"
|
||||||
|
|
||||||
|
|
||||||
static const char *options = "[-port num] -cert pem -key pem [-pass str] [-cipher_suite str] [-alpn str] [-cert_request] [-cacert pem] [-verbose]";
|
static const char *options = "[-port num] -cert pem -key pem [-pass str] [-cipher_suite str] [-alpn str] [-cert_request] [-cacert pem] [-www] [-verbose]";
|
||||||
|
|
||||||
|
|
||||||
static const char *help =
|
static const char *help =
|
||||||
@@ -47,6 +48,7 @@ static const char *help =
|
|||||||
" -alpn str Application protocol name, may appear multiple times, higher priority first\n"
|
" -alpn str Application protocol name, may appear multiple times, higher priority first\n"
|
||||||
" -cert_request Client certificate request\n"
|
" -cert_request Client certificate request\n"
|
||||||
" -cacert pem CA certificate for client certificate verification\n"
|
" -cacert pem CA certificate for client certificate verification\n"
|
||||||
|
" -www Return HTTP 200 OK and echo client request data as text\n"
|
||||||
" -verbose Print TLS handshake messages\n"
|
" -verbose Print TLS handshake messages\n"
|
||||||
"\n"
|
"\n"
|
||||||
#include "tlcp_help.h"
|
#include "tlcp_help.h"
|
||||||
@@ -159,12 +161,16 @@ int tlcp_server_main(int argc , char **argv)
|
|||||||
size_t alpn_protocols_cnt = 0;
|
size_t alpn_protocols_cnt = 0;
|
||||||
int cert_request = 0;
|
int cert_request = 0;
|
||||||
char *cacertfile = NULL;
|
char *cacertfile = NULL;
|
||||||
|
int www = 0;
|
||||||
int verbose = 0;
|
int verbose = 0;
|
||||||
|
|
||||||
TLS_CTX ctx;
|
TLS_CTX ctx;
|
||||||
TLS_CONNECT conn;
|
TLS_CONNECT conn;
|
||||||
char buf[1600] = {0};
|
char buf[1600] = {0};
|
||||||
size_t len = sizeof(buf);
|
size_t len = sizeof(buf);
|
||||||
|
uint8_t *www_request = NULL;
|
||||||
|
size_t www_request_len = 0;
|
||||||
|
size_t www_request_cap = 0;
|
||||||
tls_socket_t sock;
|
tls_socket_t sock;
|
||||||
tls_socket_t conn_sock;
|
tls_socket_t conn_sock;
|
||||||
struct sockaddr_in server_addr;
|
struct sockaddr_in server_addr;
|
||||||
@@ -237,6 +243,8 @@ int tlcp_server_main(int argc , char **argv)
|
|||||||
} else if (!strcmp(*argv, "-cacert")) {
|
} else if (!strcmp(*argv, "-cacert")) {
|
||||||
if (--argc < 1) goto bad;
|
if (--argc < 1) goto bad;
|
||||||
cacertfile = *(++argv);
|
cacertfile = *(++argv);
|
||||||
|
} else if (!strcmp(*argv, "-www")) {
|
||||||
|
www = 1;
|
||||||
} else if (!strcmp(*argv, "-verbose")) {
|
} else if (!strcmp(*argv, "-verbose")) {
|
||||||
verbose = TLS_verbose;
|
verbose = TLS_verbose;
|
||||||
} else {
|
} else {
|
||||||
@@ -345,6 +353,7 @@ bad:
|
|||||||
|
|
||||||
|
|
||||||
restart:
|
restart:
|
||||||
|
www_request_len = 0;
|
||||||
|
|
||||||
client_addrlen = sizeof(client_addr);
|
client_addrlen = sizeof(client_addr);
|
||||||
|
|
||||||
@@ -410,6 +419,31 @@ restart:
|
|||||||
}
|
}
|
||||||
} while (!len);
|
} while (!len);
|
||||||
|
|
||||||
|
if (www) {
|
||||||
|
fwrite(buf, 1, len, stdout);
|
||||||
|
fflush(stdout);
|
||||||
|
if (tls_server_www_append(&www_request, &www_request_len, &www_request_cap,
|
||||||
|
(uint8_t *)buf, len) != 1) {
|
||||||
|
fprintf(stderr, "%s: append HTTP request failure\n", prog);
|
||||||
|
tls_socket_close(conn.sock);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (tls_server_www_request_complete(www_request, www_request_len)) {
|
||||||
|
if (tls_server_www_send_response(&conn, www_request, www_request_len) != 1) {
|
||||||
|
fprintf(stderr, "%s: send HTTP response failure\n", prog);
|
||||||
|
tls_socket_close(conn.sock);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (do_shutdown_select(&conn) != 1) {
|
||||||
|
fprintf(stderr, "%s: shutdown failure\n", prog);
|
||||||
|
}
|
||||||
|
tls_socket_close(conn.sock);
|
||||||
|
tls_cleanup(&conn);
|
||||||
|
goto restart;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (do_send_select(&conn, (uint8_t *)buf, len) != 1) {
|
if (do_send_select(&conn, (uint8_t *)buf, len) != 1) {
|
||||||
fprintf(stderr, "%s: send failure, close connection\n", prog);
|
fprintf(stderr, "%s: send failure, close connection\n", prog);
|
||||||
tls_socket_close(conn.sock);
|
tls_socket_close(conn.sock);
|
||||||
@@ -419,6 +453,7 @@ restart:
|
|||||||
|
|
||||||
|
|
||||||
end:
|
end:
|
||||||
|
free(www_request);
|
||||||
gmssl_secure_clear(passbufs, sizeof(passbufs));
|
gmssl_secure_clear(passbufs, sizeof(passbufs));
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,9 +16,10 @@
|
|||||||
#include <gmssl/tls.h>
|
#include <gmssl/tls.h>
|
||||||
#include <gmssl/error.h>
|
#include <gmssl/error.h>
|
||||||
#include "passwd.h"
|
#include "passwd.h"
|
||||||
|
#include "tls_server_http.h"
|
||||||
|
|
||||||
|
|
||||||
static const char *options = "[-port num] -cert pem -key pem [-pass str] [-cacert pem] [-verbose]";
|
static const char *options = "[-port num] -cert pem -key pem [-pass str] [-cacert pem] [-www] [-verbose]";
|
||||||
|
|
||||||
static const char *help =
|
static const char *help =
|
||||||
"Options\n"
|
"Options\n"
|
||||||
@@ -35,6 +36,7 @@ static const char *help =
|
|||||||
" -verify_depth num Certificate verification depth\n"
|
" -verify_depth num Certificate verification depth\n"
|
||||||
" -client_cert_optional Allow client send empty Certificate\n"
|
" -client_cert_optional Allow client send empty Certificate\n"
|
||||||
" -renegotiation_info Enable RFC 5746 renegotiation_info response\n"
|
" -renegotiation_info Enable RFC 5746 renegotiation_info response\n"
|
||||||
|
" -www Return HTTP 200 OK and echo client request data as text\n"
|
||||||
" -verbose Print TLS handshake messages\n"
|
" -verbose Print TLS handshake messages\n"
|
||||||
"\n"
|
"\n"
|
||||||
#include "tls12_help.h"
|
#include "tls12_help.h"
|
||||||
@@ -153,11 +155,15 @@ int tls12_server_main(int argc , char **argv)
|
|||||||
int verify_depth = TLS_DEFAULT_VERIFY_DEPTH;
|
int verify_depth = TLS_DEFAULT_VERIFY_DEPTH;
|
||||||
int client_cert_optional = 0;
|
int client_cert_optional = 0;
|
||||||
int renegotiation_info = 0;
|
int renegotiation_info = 0;
|
||||||
|
int www = 0;
|
||||||
int verbose = 0;
|
int verbose = 0;
|
||||||
TLS_CTX ctx;
|
TLS_CTX ctx;
|
||||||
TLS_CONNECT conn;
|
TLS_CONNECT conn;
|
||||||
char buf[1600] = {0};
|
char buf[1600] = {0};
|
||||||
size_t len = sizeof(buf);
|
size_t len = sizeof(buf);
|
||||||
|
uint8_t *www_request = NULL;
|
||||||
|
size_t www_request_len = 0;
|
||||||
|
size_t www_request_cap = 0;
|
||||||
tls_socket_t sock;
|
tls_socket_t sock;
|
||||||
tls_socket_t conn_sock;
|
tls_socket_t conn_sock;
|
||||||
struct sockaddr_in server_addr;
|
struct sockaddr_in server_addr;
|
||||||
@@ -263,6 +269,8 @@ int tls12_server_main(int argc , char **argv)
|
|||||||
client_cert_optional = 1;
|
client_cert_optional = 1;
|
||||||
} else if (!strcmp(*argv, "-renegotiation_info")) {
|
} else if (!strcmp(*argv, "-renegotiation_info")) {
|
||||||
renegotiation_info = 1;
|
renegotiation_info = 1;
|
||||||
|
} else if (!strcmp(*argv, "-www")) {
|
||||||
|
www = 1;
|
||||||
} else if (!strcmp(*argv, "-verbose")) {
|
} else if (!strcmp(*argv, "-verbose")) {
|
||||||
verbose = TLS_verbose;
|
verbose = TLS_verbose;
|
||||||
} else {
|
} else {
|
||||||
@@ -391,6 +399,7 @@ bad:
|
|||||||
tls_socket_listen(sock, 1);
|
tls_socket_listen(sock, 1);
|
||||||
|
|
||||||
restart:
|
restart:
|
||||||
|
www_request_len = 0;
|
||||||
|
|
||||||
//client_addrlen = sizeof(client_addr);
|
//client_addrlen = sizeof(client_addr);
|
||||||
|
|
||||||
@@ -455,6 +464,31 @@ restart:
|
|||||||
}
|
}
|
||||||
} while (!len);
|
} while (!len);
|
||||||
|
|
||||||
|
if (www) {
|
||||||
|
fwrite(buf, 1, len, stdout);
|
||||||
|
fflush(stdout);
|
||||||
|
if (tls_server_www_append(&www_request, &www_request_len, &www_request_cap,
|
||||||
|
(uint8_t *)buf, len) != 1) {
|
||||||
|
fprintf(stderr, "%s: append HTTP request failure\n", prog);
|
||||||
|
tls_socket_close(conn.sock);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (tls_server_www_request_complete(www_request, www_request_len)) {
|
||||||
|
if (tls_server_www_send_response(&conn, www_request, www_request_len) != 1) {
|
||||||
|
fprintf(stderr, "%s: send HTTP response failure\n", prog);
|
||||||
|
tls_socket_close(conn.sock);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (do_shutdown_select(&conn) != 1) {
|
||||||
|
fprintf(stderr, "%s: shutdown failure\n", prog);
|
||||||
|
}
|
||||||
|
tls_socket_close(conn.sock);
|
||||||
|
tls_cleanup(&conn);
|
||||||
|
goto restart;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (do_send_select(&conn, (uint8_t *)buf, len) != 1) {
|
if (do_send_select(&conn, (uint8_t *)buf, len) != 1) {
|
||||||
fprintf(stderr, "%s: send failure, close connection\n", prog);
|
fprintf(stderr, "%s: send failure, close connection\n", prog);
|
||||||
tls_socket_close(conn.sock);
|
tls_socket_close(conn.sock);
|
||||||
@@ -464,6 +498,7 @@ restart:
|
|||||||
|
|
||||||
|
|
||||||
end:
|
end:
|
||||||
|
free(www_request);
|
||||||
gmssl_secure_clear(passbufs, sizeof(passbufs));
|
gmssl_secure_clear(passbufs, sizeof(passbufs));
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,10 +17,11 @@
|
|||||||
#include <gmssl/tls.h>
|
#include <gmssl/tls.h>
|
||||||
#include <gmssl/error.h>
|
#include <gmssl/error.h>
|
||||||
#include "passwd.h"
|
#include "passwd.h"
|
||||||
|
#include "tls_server_http.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static const char *options = "[-port num] -cert pem -key pem [-pass str] [-cacert pem] [-verbose]";
|
static const char *options = "[-port num] -cert pem -key pem [-pass str] [-cacert pem] [-www] [-verbose]";
|
||||||
|
|
||||||
static const char *help =
|
static const char *help =
|
||||||
"Options\n"
|
"Options\n"
|
||||||
@@ -47,6 +48,7 @@ static const char *help =
|
|||||||
" -ticket_key hex Session ticket encrypt/decrypt key in HEX format\n"
|
" -ticket_key hex Session ticket encrypt/decrypt key in HEX format\n"
|
||||||
" -key_update_seq_num num Send KeyUpdate handshake after sending/receiving <num> records\n"
|
" -key_update_seq_num num Send KeyUpdate handshake after sending/receiving <num> records\n"
|
||||||
" -tls13_change_cipher_spec Support ChangeCipherSpec in TLS 1.3 to be compatible with middlebox\n"
|
" -tls13_change_cipher_spec Support ChangeCipherSpec in TLS 1.3 to be compatible with middlebox\n"
|
||||||
|
" -www Return HTTP 200 OK and echo client request data as text\n"
|
||||||
" -verbose Print TLS handshake messages\n"
|
" -verbose Print TLS handshake messages\n"
|
||||||
"\n"
|
"\n"
|
||||||
#include "tls13_help.h"
|
#include "tls13_help.h"
|
||||||
@@ -133,6 +135,9 @@ int tls13_server_main(int argc , char **argv)
|
|||||||
|
|
||||||
char buf[1600] = {0};
|
char buf[1600] = {0};
|
||||||
size_t len = sizeof(buf);
|
size_t len = sizeof(buf);
|
||||||
|
uint8_t *www_request = NULL;
|
||||||
|
size_t www_request_len = 0;
|
||||||
|
size_t www_request_cap = 0;
|
||||||
|
|
||||||
int cipher_suites[TLS_MAX_CIPHER_SUITES];
|
int cipher_suites[TLS_MAX_CIPHER_SUITES];
|
||||||
size_t cipher_suites_cnt = 0;
|
size_t cipher_suites_cnt = 0;
|
||||||
@@ -175,6 +180,7 @@ int tls13_server_main(int argc , char **argv)
|
|||||||
|
|
||||||
// ChangeCipherSpec
|
// ChangeCipherSpec
|
||||||
int tls13_change_cipher_spec = 0;
|
int tls13_change_cipher_spec = 0;
|
||||||
|
int www = 0;
|
||||||
int verbose = 0;
|
int verbose = 0;
|
||||||
|
|
||||||
|
|
||||||
@@ -330,6 +336,8 @@ int tls13_server_main(int argc , char **argv)
|
|||||||
client_cert_optional = 1;
|
client_cert_optional = 1;
|
||||||
} else if (!strcmp(*argv, "-tls13_change_cipher_spec")) {
|
} else if (!strcmp(*argv, "-tls13_change_cipher_spec")) {
|
||||||
tls13_change_cipher_spec = 1;
|
tls13_change_cipher_spec = 1;
|
||||||
|
} else if (!strcmp(*argv, "-www")) {
|
||||||
|
www = 1;
|
||||||
} else if (!strcmp(*argv, "-verbose")) {
|
} else if (!strcmp(*argv, "-verbose")) {
|
||||||
verbose = TLS_verbose;
|
verbose = TLS_verbose;
|
||||||
} else {
|
} else {
|
||||||
@@ -599,6 +607,22 @@ bad:
|
|||||||
|
|
||||||
if (conn.early_data && conn.early_data_len) {
|
if (conn.early_data && conn.early_data_len) {
|
||||||
format_string(stderr, 0, 0, "EarlyData", conn.early_data_buf, conn.early_data_len);
|
format_string(stderr, 0, 0, "EarlyData", conn.early_data_buf, conn.early_data_len);
|
||||||
|
if (www) {
|
||||||
|
if (tls_server_www_append(&www_request, &www_request_len, &www_request_cap,
|
||||||
|
conn.early_data_buf, conn.early_data_len) != 1) {
|
||||||
|
fprintf(stderr, "%s: append HTTP request failure\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (tls_server_www_request_complete(www_request, www_request_len)) {
|
||||||
|
if (tls_server_www_send_response(&conn, www_request, www_request_len) != 1) {
|
||||||
|
fprintf(stderr, "%s: send HTTP response failure\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
do_shutdown_select(&conn);
|
||||||
|
ret = 0;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t send_len = 0;
|
size_t send_len = 0;
|
||||||
@@ -663,6 +687,24 @@ bad:
|
|||||||
fwrite(buf, 1, len, stdout);
|
fwrite(buf, 1, len, stdout);
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
|
|
||||||
|
if (www) {
|
||||||
|
if (tls_server_www_append(&www_request, &www_request_len, &www_request_cap,
|
||||||
|
(uint8_t *)buf, len) != 1) {
|
||||||
|
fprintf(stderr, "%s: append HTTP request failure\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (tls_server_www_request_complete(www_request, www_request_len)) {
|
||||||
|
if (tls_server_www_send_response(&conn, www_request, www_request_len) != 1) {
|
||||||
|
fprintf(stderr, "%s: send HTTP response failure\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
do_shutdown_select(&conn);
|
||||||
|
ret = 0;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
send_len = len;
|
send_len = len;
|
||||||
send_offset = 0;
|
send_offset = 0;
|
||||||
/*
|
/*
|
||||||
@@ -680,6 +722,7 @@ bad:
|
|||||||
|
|
||||||
|
|
||||||
end:
|
end:
|
||||||
|
free(www_request);
|
||||||
gmssl_secure_clear(passbufs, sizeof(passbufs));
|
gmssl_secure_clear(passbufs, sizeof(passbufs));
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|||||||
253
tools/tls_server_http.h
Normal file
253
tools/tls_server_http.h
Normal file
@@ -0,0 +1,253 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2014-2026 The GmSSL Project. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||||
|
* not use this file except in compliance with the License.
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef GMSSL_TOOLS_TLS_SERVER_HTTP_H
|
||||||
|
#define GMSSL_TOOLS_TLS_SERVER_HTTP_H
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <gmssl/tls.h>
|
||||||
|
#include <gmssl/error.h>
|
||||||
|
|
||||||
|
static int tls_server_www_append(uint8_t **buf, size_t *len, size_t *cap,
|
||||||
|
const uint8_t *data, size_t datalen)
|
||||||
|
{
|
||||||
|
uint8_t *p;
|
||||||
|
size_t newlen;
|
||||||
|
size_t newcap;
|
||||||
|
|
||||||
|
if (datalen > (size_t)-1 - *len) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
newlen = *len + datalen;
|
||||||
|
if (newlen <= *cap) {
|
||||||
|
memcpy(*buf + *len, data, datalen);
|
||||||
|
*len = newlen;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
newcap = *cap ? *cap : 4096;
|
||||||
|
while (newcap < newlen) {
|
||||||
|
if (newcap > ((size_t)-1)/2) {
|
||||||
|
newcap = newlen;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
newcap *= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(p = realloc(*buf, newcap))) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
*buf = p;
|
||||||
|
*cap = newcap;
|
||||||
|
memcpy(*buf + *len, data, datalen);
|
||||||
|
*len = newlen;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tls_server_www_ascii_lower(int c)
|
||||||
|
{
|
||||||
|
if (c >= 'A' && c <= 'Z') {
|
||||||
|
return c - 'A' + 'a';
|
||||||
|
}
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tls_server_www_memcase_equal(const uint8_t *a, const char *b, size_t len)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
|
if (tls_server_www_ascii_lower(a[i]) != tls_server_www_ascii_lower((unsigned char)b[i])) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tls_server_www_starts_with(const uint8_t *buf, size_t len, const char *prefix)
|
||||||
|
{
|
||||||
|
size_t prefix_len = strlen(prefix);
|
||||||
|
|
||||||
|
if (len < prefix_len) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return memcmp(buf, prefix, prefix_len) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tls_server_www_looks_like_http(const uint8_t *buf, size_t len)
|
||||||
|
{
|
||||||
|
if (tls_server_www_starts_with(buf, len, "GET ")
|
||||||
|
|| tls_server_www_starts_with(buf, len, "POST ")
|
||||||
|
|| tls_server_www_starts_with(buf, len, "HEAD ")
|
||||||
|
|| tls_server_www_starts_with(buf, len, "PUT ")
|
||||||
|
|| tls_server_www_starts_with(buf, len, "DELETE ")
|
||||||
|
|| tls_server_www_starts_with(buf, len, "PATCH ")
|
||||||
|
|| tls_server_www_starts_with(buf, len, "OPTIONS ")
|
||||||
|
|| tls_server_www_starts_with(buf, len, "TRACE ")
|
||||||
|
|| tls_server_www_starts_with(buf, len, "CONNECT ")) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tls_server_www_find_header_end(const uint8_t *buf, size_t len, size_t *header_len)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i = 0; i + 3 < len; i++) {
|
||||||
|
if (buf[i] == '\r' && buf[i + 1] == '\n' && buf[i + 2] == '\r' && buf[i + 3] == '\n') {
|
||||||
|
*header_len = i + 4;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tls_server_www_parse_content_length(const uint8_t *buf, size_t header_len,
|
||||||
|
size_t *content_length, int *has_content_length)
|
||||||
|
{
|
||||||
|
const char name[] = "content-length:";
|
||||||
|
size_t name_len = sizeof(name) - 1;
|
||||||
|
size_t pos = 0;
|
||||||
|
|
||||||
|
*content_length = 0;
|
||||||
|
*has_content_length = 0;
|
||||||
|
|
||||||
|
while (pos < header_len) {
|
||||||
|
size_t line_end = pos;
|
||||||
|
size_t val_pos;
|
||||||
|
size_t value = 0;
|
||||||
|
|
||||||
|
while (line_end + 1 < header_len
|
||||||
|
&& !(buf[line_end] == '\r' && buf[line_end + 1] == '\n')) {
|
||||||
|
line_end++;
|
||||||
|
}
|
||||||
|
if (line_end > pos + name_len
|
||||||
|
&& tls_server_www_memcase_equal(buf + pos, name, name_len)) {
|
||||||
|
val_pos = pos + name_len;
|
||||||
|
while (val_pos < line_end && (buf[val_pos] == ' ' || buf[val_pos] == '\t')) {
|
||||||
|
val_pos++;
|
||||||
|
}
|
||||||
|
if (val_pos == line_end) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
while (val_pos < line_end) {
|
||||||
|
unsigned int digit;
|
||||||
|
|
||||||
|
if (buf[val_pos] < '0' || buf[val_pos] > '9') {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
digit = buf[val_pos] - '0';
|
||||||
|
if (value > ((size_t)-1 - digit)/10) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
value = value * 10 + digit;
|
||||||
|
val_pos++;
|
||||||
|
}
|
||||||
|
*content_length = value;
|
||||||
|
*has_content_length = 1;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (line_end + 1 >= header_len) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
pos = line_end + 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tls_server_www_request_complete(const uint8_t *buf, size_t len)
|
||||||
|
{
|
||||||
|
size_t header_len;
|
||||||
|
size_t content_length;
|
||||||
|
int has_content_length;
|
||||||
|
|
||||||
|
if (!tls_server_www_find_header_end(buf, len, &header_len)) {
|
||||||
|
if (len && !tls_server_www_looks_like_http(buf, len)) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (tls_server_www_parse_content_length(buf, header_len, &content_length,
|
||||||
|
&has_content_length) != 1) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (!has_content_length) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (content_length > (size_t)-1 - header_len) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return len >= header_len + content_length;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tls_server_www_send_all(TLS_CONNECT *conn, const uint8_t *buf, size_t len)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
size_t offset = 0;
|
||||||
|
fd_set rfds;
|
||||||
|
fd_set wfds;
|
||||||
|
|
||||||
|
while (offset < len) {
|
||||||
|
size_t sentlen = 0;
|
||||||
|
|
||||||
|
ret = tls_send(conn, buf + offset, len - offset, &sentlen);
|
||||||
|
if (ret == 1) {
|
||||||
|
offset += sentlen;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
FD_ZERO(&rfds);
|
||||||
|
FD_ZERO(&wfds);
|
||||||
|
if (ret == TLS_ERROR_RECV_AGAIN) {
|
||||||
|
FD_SET(conn->sock, &rfds);
|
||||||
|
} else if (ret == TLS_ERROR_SEND_AGAIN) {
|
||||||
|
FD_SET(conn->sock, &wfds);
|
||||||
|
} else {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (select((int)(conn->sock + 1), &rfds, &wfds, NULL, NULL) < 0) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tls_server_www_send_response(TLS_CONNECT *conn, const uint8_t *body, size_t bodylen)
|
||||||
|
{
|
||||||
|
char header[256];
|
||||||
|
int header_len;
|
||||||
|
|
||||||
|
header_len = snprintf(header, sizeof(header),
|
||||||
|
"HTTP/1.0 200 OK\r\n"
|
||||||
|
"Content-Type: text/plain\r\n"
|
||||||
|
"Content-Length: %zu\r\n"
|
||||||
|
"Connection: close\r\n"
|
||||||
|
"\r\n", bodylen);
|
||||||
|
if (header_len < 0 || (size_t)header_len >= sizeof(header)) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (tls_server_www_send_all(conn, (uint8_t *)header, (size_t)header_len) != 1) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (bodylen && tls_server_www_send_all(conn, body, bodylen) != 1) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
Reference in New Issue
Block a user