mirror of
https://github.com/guanzhi/GmSSL.git
synced 2026-06-20 03:44:15 +08:00
Unify tlcp/tls12/tls13_client behavior
This commit is contained in:
@@ -768,7 +768,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.2.0-dev.1015")
|
set(CPACK_PACKAGE_VERSION "3.2.0-dev.1016")
|
||||||
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)
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ extern "C" {
|
|||||||
|
|
||||||
// Also update CPACK_PACKAGE_VERSION in CMakeLists.txt
|
// Also update CPACK_PACKAGE_VERSION in CMakeLists.txt
|
||||||
#define GMSSL_VERSION_NUM 30200
|
#define GMSSL_VERSION_NUM 30200
|
||||||
#define GMSSL_VERSION_STR "GmSSL 3.2.0-dev.1015"
|
#define GMSSL_VERSION_STR "GmSSL 3.2.0-dev.1016"
|
||||||
|
|
||||||
int gmssl_version_num(void);
|
int gmssl_version_num(void);
|
||||||
const char *gmssl_version_str(void);
|
const char *gmssl_version_str(void);
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ static const char *usage =
|
|||||||
"-host str [-port num] [-cacert pem]"
|
"-host str [-port num] [-cacert pem]"
|
||||||
" [-cert pem -key pem -pass str]"
|
" [-cert pem -key pem -pass str]"
|
||||||
" [-certout pem]"
|
" [-certout pem]"
|
||||||
" [-get path]"
|
" [-get path|-in file]"
|
||||||
" [-alpn str]"
|
" [-alpn str]"
|
||||||
" [-trusted_ca_keys]"
|
" [-trusted_ca_keys]"
|
||||||
" [-verbose]";
|
" [-verbose]";
|
||||||
@@ -43,6 +43,7 @@ static const char *help =
|
|||||||
" -pass password Password of encrypted private key\n"
|
" -pass password Password of encrypted private key\n"
|
||||||
" -client_cert_optional Allow client send empty Certificate\n"
|
" -client_cert_optional Allow client send empty Certificate\n"
|
||||||
" -get path Send a GET request with given path of URI\n"
|
" -get path Send a GET request with given path of URI\n"
|
||||||
|
" -in file | stdin Send input data and read response until close or timeout\n"
|
||||||
" -certout pem Save server certificates to a PEM file\n"
|
" -certout pem Save server certificates to a PEM file\n"
|
||||||
" -server_name str Send server_name (SNI) request\n"
|
" -server_name str Send server_name (SNI) request\n"
|
||||||
" -trusted_ca_keys Send trusted_ca_keys request\n"
|
" -trusted_ca_keys Send trusted_ca_keys request\n"
|
||||||
@@ -162,6 +163,65 @@ static int do_send_select(TLS_CONNECT *conn, const uint8_t *buf, size_t len)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int do_recv_until_timeout(TLS_CONNECT *conn, char *prog)
|
||||||
|
{
|
||||||
|
char buf[1024];
|
||||||
|
size_t len;
|
||||||
|
fd_set fds;
|
||||||
|
struct timeval timeout;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
FD_ZERO(&fds);
|
||||||
|
FD_SET(conn->sock, &fds);
|
||||||
|
timeout.tv_sec = TIMEOUT_SECONDS;
|
||||||
|
timeout.tv_usec = 0;
|
||||||
|
|
||||||
|
switch (select((int)(conn->sock + 1), &fds, NULL, NULL, &timeout)) {
|
||||||
|
case -1:
|
||||||
|
fprintf(stderr, "%s: select error\n", prog);
|
||||||
|
return -1;
|
||||||
|
case 0:
|
||||||
|
do_shutdown_select(conn);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
len = sizeof(buf);
|
||||||
|
switch (tls_recv(conn, (uint8_t *)buf, sizeof(buf), &len)) {
|
||||||
|
case 1:
|
||||||
|
fwrite(buf, 1, len, stdout);
|
||||||
|
fflush(stdout);
|
||||||
|
break;
|
||||||
|
case 0:
|
||||||
|
do_shutdown_select(conn);
|
||||||
|
return 1;
|
||||||
|
case TLS_ERROR_RECV_AGAIN:
|
||||||
|
case TLS_ERROR_SEND_AGAIN:
|
||||||
|
case -EAGAIN:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fprintf(stderr, "%s: tls_recv error\n", prog);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int do_send_file_select(TLS_CONNECT *conn, FILE *fp)
|
||||||
|
{
|
||||||
|
uint8_t buf[4096];
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
while ((len = fread(buf, 1, sizeof(buf), fp)) > 0) {
|
||||||
|
if (do_send_select(conn, buf, len) != 1) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ferror(fp)) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
int tlcp_client_main(int argc, char *argv[])
|
int tlcp_client_main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
@@ -186,6 +246,7 @@ int tlcp_client_main(int argc, char *argv[])
|
|||||||
size_t alpn_protocols_cnt = 0;
|
size_t alpn_protocols_cnt = 0;
|
||||||
int client_cert_optional = 0;
|
int client_cert_optional = 0;
|
||||||
char *get = NULL;
|
char *get = NULL;
|
||||||
|
char *infile = NULL;
|
||||||
char *certoutfile = NULL;
|
char *certoutfile = NULL;
|
||||||
int verbose = 0;
|
int verbose = 0;
|
||||||
struct hostent *hp;
|
struct hostent *hp;
|
||||||
@@ -294,6 +355,9 @@ int tlcp_client_main(int argc, char *argv[])
|
|||||||
} else if (!strcmp(*argv, "-get")) {
|
} else if (!strcmp(*argv, "-get")) {
|
||||||
if (--argc < 1) goto bad;
|
if (--argc < 1) goto bad;
|
||||||
get = *(++argv);
|
get = *(++argv);
|
||||||
|
} else if (!strcmp(*argv, "-in")) {
|
||||||
|
if (--argc < 1) goto bad;
|
||||||
|
infile = *(++argv);
|
||||||
} else if (!strcmp(*argv, "-certout")) {
|
} else if (!strcmp(*argv, "-certout")) {
|
||||||
if (--argc < 1) goto bad;
|
if (--argc < 1) goto bad;
|
||||||
certoutfile = *(++argv);
|
certoutfile = *(++argv);
|
||||||
@@ -321,6 +385,10 @@ bad:
|
|||||||
fprintf(stderr, "%s: option '-cipher_suite' missing\n", prog);
|
fprintf(stderr, "%s: option '-cipher_suite' missing\n", prog);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
if (get && infile) {
|
||||||
|
fprintf(stderr, "%s: '-get' and '-in' should not be used together\n", prog);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (tls_socket_lib_init() != 1) {
|
if (tls_socket_lib_init() != 1) {
|
||||||
error_print();
|
error_print();
|
||||||
@@ -454,10 +522,6 @@ bad:
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (get) {
|
if (get) {
|
||||||
struct timeval timeout;
|
|
||||||
timeout.tv_sec = TIMEOUT_SECONDS;
|
|
||||||
timeout.tv_usec = 0;
|
|
||||||
|
|
||||||
snprintf(buf, sizeof(buf), "GET %s HTTP/1.1\r\nHost: %s\r\n\r\n", get, host);
|
snprintf(buf, sizeof(buf), "GET %s HTTP/1.1\r\nHost: %s\r\n\r\n", get, host);
|
||||||
|
|
||||||
if (do_send_select(&conn, (uint8_t *)buf, strlen(buf)) != 1) {
|
if (do_send_select(&conn, (uint8_t *)buf, strlen(buf)) != 1) {
|
||||||
@@ -465,54 +529,32 @@ bad:
|
|||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
// use timeout to close the HTTP connection
|
if (do_recv_until_timeout(&conn, prog) != 1) {
|
||||||
if (setsockopt(conn.sock, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout, sizeof(timeout)) != 0) {
|
|
||||||
perror("setsockopt");
|
|
||||||
fprintf(stderr, "%s: set socket timeout error\n", prog);
|
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
ret = 0;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
for (;;) {
|
if (infile) {
|
||||||
int rv;
|
FILE *infp = stdin;
|
||||||
|
if (strcmp(infile, "-") && strcmp(infile, "stdin")) {
|
||||||
len = sizeof(buf);
|
if (!(infp = fopen(infile, "rb"))) {
|
||||||
rv = tls_recv(&conn, (uint8_t *)buf, sizeof(buf), &len);
|
fprintf(stderr, "%s: open '%s' failure\n", prog, infile);
|
||||||
|
|
||||||
if (rv == 1) {
|
|
||||||
fwrite(buf, 1, len, stdout);
|
|
||||||
fflush(stdout);
|
|
||||||
} else if (rv == 0) {
|
|
||||||
fprintf(stderr, "%s: TLCP connection is closed by remote host\n", prog);
|
|
||||||
do_shutdown_select(&conn);
|
|
||||||
ret = 0;
|
|
||||||
goto end;
|
|
||||||
} else if (rv == -EAGAIN
|
|
||||||
|| rv == TLS_ERROR_RECV_AGAIN
|
|
||||||
|| rv == TLS_ERROR_SEND_AGAIN) {
|
|
||||||
fd_set fds;
|
|
||||||
struct timeval timeout;
|
|
||||||
int sel;
|
|
||||||
|
|
||||||
timeout.tv_sec = TIMEOUT_SECONDS;
|
|
||||||
timeout.tv_usec = 0;
|
|
||||||
FD_ZERO(&fds);
|
|
||||||
FD_SET(conn.sock, &fds);
|
|
||||||
sel = select(conn.sock + 1, &fds, NULL, NULL, &timeout);
|
|
||||||
if (sel < 0) {
|
|
||||||
fprintf(stderr, "%s: select error\n", prog);
|
|
||||||
goto end;
|
|
||||||
} else if (sel == 0) {
|
|
||||||
do_shutdown_select(&conn);
|
|
||||||
ret = 0;
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
fprintf(stderr, "%s: tls_recv error\n", prog);
|
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (do_send_file_select(&conn, infp) != 1) {
|
||||||
read_stdin = 0;
|
if (infp != stdin) fclose(infp);
|
||||||
|
fprintf(stderr, "%s: send error\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (infp != stdin) fclose(infp);
|
||||||
|
if (do_recv_until_timeout(&conn, prog) != 1) {
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
ret = 0;
|
||||||
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
|||||||
@@ -18,12 +18,7 @@
|
|||||||
|
|
||||||
static int client_ciphers[] = { TLS_cipher_ecdhe_sm4_cbc_sm3 };
|
static int client_ciphers[] = { TLS_cipher_ecdhe_sm4_cbc_sm3 };
|
||||||
|
|
||||||
static const char *http_get =
|
static const char *options = "-host str [-port num] [-cacert pem] [-cert pem -key pem -pass str] [-get path|-in file] [-trusted_ca_keys] [-verbose]";
|
||||||
"GET / HTTP/1.1\r\n"
|
|
||||||
"Hostname: aaa\r\n"
|
|
||||||
"\r\n\r\n";
|
|
||||||
|
|
||||||
static const char *options = "-host str [-port num] [-cacert pem] [-cert pem -key pem -pass str] [-trusted_ca_keys] [-verbose]";
|
|
||||||
|
|
||||||
static const char *help =
|
static const char *help =
|
||||||
"Options\n"
|
"Options\n"
|
||||||
@@ -45,6 +40,8 @@ static const char *help =
|
|||||||
" -renegotiation_info_scsv\n"
|
" -renegotiation_info_scsv\n"
|
||||||
" Send TLS_EMPTY_RENEGOTIATION_INFO_SCSV\n"
|
" Send TLS_EMPTY_RENEGOTIATION_INFO_SCSV\n"
|
||||||
" -status_request Send status_request (OCSP Stapling) request\n"
|
" -status_request Send status_request (OCSP Stapling) request\n"
|
||||||
|
" -get path Send a HTTP GET request and read response until close or timeout\n"
|
||||||
|
" -in file | stdin Send input data and read response until close or timeout\n"
|
||||||
" -verbose Print TLS handshake messages\n"
|
" -verbose Print TLS handshake messages\n"
|
||||||
"\n"
|
"\n"
|
||||||
#include "tls12_help.h"
|
#include "tls12_help.h"
|
||||||
@@ -158,6 +155,65 @@ static int do_send_select(TLS_CONNECT *conn, const uint8_t *buf, size_t len)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int do_recv_until_timeout(TLS_CONNECT *conn, char *prog)
|
||||||
|
{
|
||||||
|
char buf[1024];
|
||||||
|
size_t len;
|
||||||
|
fd_set fds;
|
||||||
|
struct timeval timeout;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
FD_ZERO(&fds);
|
||||||
|
FD_SET(conn->sock, &fds);
|
||||||
|
timeout.tv_sec = 1;
|
||||||
|
timeout.tv_usec = 0;
|
||||||
|
|
||||||
|
switch (select((int)(conn->sock + 1), &fds, NULL, NULL, &timeout)) {
|
||||||
|
case -1:
|
||||||
|
fprintf(stderr, "%s: select failed\n", prog);
|
||||||
|
return -1;
|
||||||
|
case 0:
|
||||||
|
do_shutdown_select(conn);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
len = sizeof(buf);
|
||||||
|
switch (tls_recv(conn, (uint8_t *)buf, sizeof(buf), &len)) {
|
||||||
|
case 1:
|
||||||
|
fwrite(buf, 1, len, stdout);
|
||||||
|
fflush(stdout);
|
||||||
|
break;
|
||||||
|
case 0:
|
||||||
|
do_shutdown_select(conn);
|
||||||
|
return 1;
|
||||||
|
case TLS_ERROR_RECV_AGAIN:
|
||||||
|
case TLS_ERROR_SEND_AGAIN:
|
||||||
|
case -EAGAIN:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fprintf(stderr, "%s: tls_recv error\n", prog);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int do_send_file_select(TLS_CONNECT *conn, FILE *fp)
|
||||||
|
{
|
||||||
|
uint8_t buf[4096];
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
while ((len = fread(buf, 1, sizeof(buf), fp)) > 0) {
|
||||||
|
if (do_send_select(conn, buf, len) != 1) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ferror(fp)) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
int tls12_client_main(int argc, char *argv[])
|
int tls12_client_main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
@@ -180,6 +236,8 @@ int tls12_client_main(int argc, char *argv[])
|
|||||||
int trusted_ca_keys = 0;
|
int trusted_ca_keys = 0;
|
||||||
int renegotiation_info = 0;
|
int renegotiation_info = 0;
|
||||||
int empty_renegotiation_info_scsv = 0;
|
int empty_renegotiation_info_scsv = 0;
|
||||||
|
char *get = NULL;
|
||||||
|
char *infile = NULL;
|
||||||
int verbose = 0;
|
int verbose = 0;
|
||||||
TLS_CTX ctx;
|
TLS_CTX ctx;
|
||||||
TLS_CONNECT conn;
|
TLS_CONNECT conn;
|
||||||
@@ -280,6 +338,12 @@ int tls12_client_main(int argc, char *argv[])
|
|||||||
empty_renegotiation_info_scsv = 1;
|
empty_renegotiation_info_scsv = 1;
|
||||||
} else if (!strcmp(*argv, "-client_cert_optional")) {
|
} else if (!strcmp(*argv, "-client_cert_optional")) {
|
||||||
client_cert_optional = 1;
|
client_cert_optional = 1;
|
||||||
|
} else if (!strcmp(*argv, "-get")) {
|
||||||
|
if (--argc < 1) goto bad;
|
||||||
|
get = *(++argv);
|
||||||
|
} else if (!strcmp(*argv, "-in")) {
|
||||||
|
if (--argc < 1) goto bad;
|
||||||
|
infile = *(++argv);
|
||||||
} else if (!strcmp(*argv, "-verbose")) {
|
} else if (!strcmp(*argv, "-verbose")) {
|
||||||
verbose = 1;
|
verbose = 1;
|
||||||
} else {
|
} else {
|
||||||
@@ -294,7 +358,11 @@ bad:
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!host) {
|
if (!host) {
|
||||||
fprintf(stderr, "%s: '-in' option required\n", prog);
|
fprintf(stderr, "%s: '-host' option required\n", prog);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (get && infile) {
|
||||||
|
fprintf(stderr, "%s: '-get' and '-in' should not be used together\n", prog);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -424,6 +492,40 @@ bad:
|
|||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (get) {
|
||||||
|
snprintf(buf, sizeof(buf), "GET %s HTTP/1.1\r\nHost: %s\r\n\r\n", get, host);
|
||||||
|
if (do_send_select(&conn, (uint8_t *)buf, strlen(buf)) != 1) {
|
||||||
|
fprintf(stderr, "%s: send error\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (do_recv_until_timeout(&conn, prog) != 1) {
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
ret = 0;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (infile) {
|
||||||
|
FILE *infp = stdin;
|
||||||
|
if (strcmp(infile, "-") && strcmp(infile, "stdin")) {
|
||||||
|
if (!(infp = fopen(infile, "rb"))) {
|
||||||
|
fprintf(stderr, "%s: open '%s' failure\n", prog, infile);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (do_send_file_select(&conn, infp) != 1) {
|
||||||
|
if (infp != stdin) fclose(infp);
|
||||||
|
fprintf(stderr, "%s: send error\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (infp != stdin) fclose(infp);
|
||||||
|
if (do_recv_until_timeout(&conn, prog) != 1) {
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
ret = 0;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
fd_set fds;
|
fd_set fds;
|
||||||
if (!fgets(send_buf, sizeof(send_buf), stdin)) {
|
if (!fgets(send_buf, sizeof(send_buf), stdin)) {
|
||||||
|
|||||||
@@ -98,12 +98,99 @@ static int do_shutdown_select(TLS_CONNECT *conn)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *http_get =
|
static int do_send_select(TLS_CONNECT *conn, const uint8_t *buf, size_t len)
|
||||||
"GET / HTTP/1.1\r\n"
|
{
|
||||||
"Hostname: aaa\r\n"
|
int ret;
|
||||||
"\r\n\r\n";
|
size_t offset = 0;
|
||||||
|
fd_set rfds;
|
||||||
|
fd_set wfds;
|
||||||
|
|
||||||
static const char *options = "-host str [-port num] [-cacert pem] [-cert pem -key pem -pass str] [-verbose]";
|
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 do_recv_until_timeout(TLS_CONNECT *conn, char *prog)
|
||||||
|
{
|
||||||
|
char buf[1024];
|
||||||
|
size_t len;
|
||||||
|
fd_set fds;
|
||||||
|
struct timeval timeout;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
FD_ZERO(&fds);
|
||||||
|
FD_SET(conn->sock, &fds);
|
||||||
|
timeout.tv_sec = 1;
|
||||||
|
timeout.tv_usec = 0;
|
||||||
|
|
||||||
|
switch (select((int)(conn->sock + 1), &fds, NULL, NULL, &timeout)) {
|
||||||
|
case -1:
|
||||||
|
fprintf(stderr, "%s: select failed\n", prog);
|
||||||
|
return -1;
|
||||||
|
case 0:
|
||||||
|
do_shutdown_select(conn);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
len = sizeof(buf);
|
||||||
|
switch (tls_recv(conn, (uint8_t *)buf, sizeof(buf), &len)) {
|
||||||
|
case 1:
|
||||||
|
fwrite(buf, 1, len, stdout);
|
||||||
|
fflush(stdout);
|
||||||
|
break;
|
||||||
|
case 0:
|
||||||
|
do_shutdown_select(conn);
|
||||||
|
return 1;
|
||||||
|
case TLS_ERROR_RECV_AGAIN:
|
||||||
|
case TLS_ERROR_SEND_AGAIN:
|
||||||
|
case -EAGAIN:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fprintf(stderr, "%s: tls_recv error\n", prog);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int do_send_file_select(TLS_CONNECT *conn, FILE *fp)
|
||||||
|
{
|
||||||
|
uint8_t buf[4096];
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
while ((len = fread(buf, 1, sizeof(buf), fp)) > 0) {
|
||||||
|
if (do_send_select(conn, buf, len) != 1) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ferror(fp)) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *options = "-host str [-port num] [-cacert pem] [-cert pem -key pem -pass str] [-get path|-in file] [-verbose]";
|
||||||
|
|
||||||
static const char *help =
|
static const char *help =
|
||||||
"Options\n"
|
"Options\n"
|
||||||
@@ -136,6 +223,8 @@ static const char *help =
|
|||||||
" -post_handshake_auth Support post_handshake_auth\n"
|
" -post_handshake_auth Support post_handshake_auth\n"
|
||||||
" -client_cert_optional Allow client send empty Certificate\n"
|
" -client_cert_optional Allow client send empty Certificate\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"
|
||||||
|
" -get path Send a HTTP GET request and read response until close or timeout\n"
|
||||||
|
" -in file | stdin Send input data and read response until close or timeout\n"
|
||||||
" -verbose Print TLS handshake messages\n"
|
" -verbose Print TLS handshake messages\n"
|
||||||
"\n"
|
"\n"
|
||||||
#include "tls13_help.h"
|
#include "tls13_help.h"
|
||||||
@@ -234,6 +323,8 @@ int tls13_client_main(int argc, char *argv[])
|
|||||||
// ChangeCipherSpec
|
// ChangeCipherSpec
|
||||||
int tls13_change_cipher_spec = 0;
|
int tls13_change_cipher_spec = 0;
|
||||||
int verbose = 0;
|
int verbose = 0;
|
||||||
|
char *get = NULL;
|
||||||
|
char *infile = NULL;
|
||||||
|
|
||||||
int send_again = 0;
|
int send_again = 0;
|
||||||
|
|
||||||
@@ -399,6 +490,12 @@ int tls13_client_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, "-get")) {
|
||||||
|
if (--argc < 1) goto bad;
|
||||||
|
get = *(++argv);
|
||||||
|
} else if (!strcmp(*argv, "-in")) {
|
||||||
|
if (--argc < 1) goto bad;
|
||||||
|
infile = *(++argv);
|
||||||
} else if (!strcmp(*argv, "-verbose")) {
|
} else if (!strcmp(*argv, "-verbose")) {
|
||||||
verbose = 1;
|
verbose = 1;
|
||||||
} else {
|
} else {
|
||||||
@@ -421,6 +518,10 @@ bad:
|
|||||||
fprintf(stderr, "%s: option '-cipher_suite' required\n", prog);
|
fprintf(stderr, "%s: option '-cipher_suite' required\n", prog);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
if (get && infile) {
|
||||||
|
fprintf(stderr, "%s: '-get' and '-in' should not be used together\n", prog);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
// TLS_CTX
|
// TLS_CTX
|
||||||
|
|
||||||
@@ -725,6 +826,40 @@ bad:
|
|||||||
fprintf(stderr, "connected\n");
|
fprintf(stderr, "connected\n");
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
|
|
||||||
|
if (get) {
|
||||||
|
snprintf(buf, sizeof(buf), "GET %s HTTP/1.1\r\nHost: %s\r\n\r\n", get, host);
|
||||||
|
if (do_send_select(&conn, (uint8_t *)buf, strlen(buf)) != 1) {
|
||||||
|
fprintf(stderr, "%s: send error\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (do_recv_until_timeout(&conn, prog) != 1) {
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
ret = 0;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (infile) {
|
||||||
|
FILE *infp = stdin;
|
||||||
|
if (strcmp(infile, "-") && strcmp(infile, "stdin")) {
|
||||||
|
if (!(infp = fopen(infile, "rb"))) {
|
||||||
|
fprintf(stderr, "%s: open '%s' failure\n", prog, infile);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (do_send_file_select(&conn, infp) != 1) {
|
||||||
|
if (infp != stdin) fclose(infp);
|
||||||
|
fprintf(stderr, "%s: send error\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (infp != stdin) fclose(infp);
|
||||||
|
if (do_recv_until_timeout(&conn, prog) != 1) {
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
ret = 0;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
|
||||||
fd_set fds_send;
|
fd_set fds_send;
|
||||||
|
|||||||
Reference in New Issue
Block a user