Fix TLS Alert

Alert, ChangeCipherSpec record should be encrypted after handshake
This commit is contained in:
Zhi Guan
2024-02-06 20:57:27 +08:00
parent 24783e56ed
commit 69ffa88037
5 changed files with 196 additions and 180 deletions

View File

@@ -70,6 +70,7 @@ int tlcp_client_main(int argc, char *argv[])
size_t len = sizeof(buf);
char send_buf[1024] = {0};
size_t sentlen;
int read_stdin = 1;
argc--;
argv++;
@@ -130,24 +131,19 @@ bad:
return -1;
}
if (!(hp = gethostbyname(host))) {
fprintf(stderr, "%s: invalid hostname '%s'\n", prog, host);
goto end;
}
memset(&ctx, 0, sizeof(ctx));
memset(&conn, 0, sizeof(conn));
server.sin_addr = *((struct in_addr *)hp->h_addr_list[0]);
server.sin_family = AF_INET;
server.sin_port = htons(port);
if (tls_socket_create(&sock, AF_INET, SOCK_STREAM, 0) != 1) {
fprintf(stderr, "%s: open socket error\n", prog);
goto end;
}
if (!(hp = gethostbyname(host))) {
fprintf(stderr, "%s: invalid hostname '%s'\n", prog, host);
goto end;
}
server.sin_addr = *((struct in_addr *)hp->h_addr_list[0]);
server.sin_family = AF_INET;
server.sin_port = htons(port);
if (tls_socket_connect(sock, &server) != 1) {
fprintf(stderr, "%s: socket connect error\n", prog);
goto end;
@@ -158,19 +154,30 @@ bad:
fprintf(stderr, "%s: context init error\n", prog);
goto end;
}
if (cacertfile) {
if (tls_ctx_set_ca_certificates(&ctx, cacertfile, TLS_DEFAULT_VERIFY_DEPTH) != 1) {
fprintf(stderr, "%s: context init error\n", prog);
goto end;
}
}
if (certfile) {
if (!keyfile) {
fprintf(stderr, "%s: option '-key' should be assigned with '-cert'\n", prog);
goto end;
}
if (!pass) {
fprintf(stderr, "%s: option '-pass' should be assigned with '-pass'\n", prog);
goto end;
}
if (tls_ctx_set_certificate_and_key(&ctx, certfile, keyfile, pass) != 1) {
fprintf(stderr, "%s: context init error\n", prog);
goto end;
}
}
if (quiet || get) {
if (quiet) {
ctx.quiet = 1;
}
@@ -196,6 +203,9 @@ bad:
fclose(outcertsfp);
}
// tls_shutdown(&conn);
// return 0;
if (get) {
struct timeval timeout;
timeout.tv_sec = TIMEOUT_SECONDS;
@@ -208,6 +218,7 @@ bad:
goto end;
}
// use timeout to close the HTTP connection
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);
@@ -215,100 +226,84 @@ bad:
}
for (;;) {
int ret;
if ((ret = tls_recv(&conn, (uint8_t *)buf, sizeof(buf), &len)) != 1) {
if (ret == 0) {
fprintf(stderr, "%s: TLCP connection is closed by remote host\n", prog);
} else if (ret != -EAGAIN) {
fprintf(stderr, "%s: recv error\n", prog);
}
break;
int rv;
rv = tls_recv(&conn, (uint8_t *)buf, sizeof(buf), &len);
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);
goto end;
} else if (rv == -EAGAIN) {
// when timeout, tls_recv return -EAGAIN (-11)
tls_shutdown(&conn);
ret = 0;
goto end;
} else {
fprintf(stderr, "%s: tls_recv error\n", prog);
goto end;
}
fwrite(buf, 1, len, stdout);
fflush(stdout);
}
tls_shutdown(&conn);
goto end;
}
for (;;) {
fd_set fds;
if (!fgets(send_buf, sizeof(send_buf), stdin)) {
if (feof(stdin)) {
tls_shutdown(&conn);
goto end;
} else {
continue;
}
}
if (tls_send(&conn, (uint8_t *)send_buf, strlen(send_buf), &sentlen) != 1) {
fprintf(stderr, "%s: send error\n", prog);
goto end;
}
FD_ZERO(&fds);
FD_SET(conn.sock, &fds);
#ifdef WIN32
#else
FD_SET(fileno(stdin), &fds); //FD_SET(STDIN_FILENO, &fds); // NOT allowed in winsock2 !!!
#endif
if (read_stdin)
FD_SET(STDIN_FILENO, &fds);
if (select((int)(conn.sock + 1), // WinSock2 select() ignore this arg
&fds, NULL, NULL, NULL) < 0) {
fprintf(stderr, "%s: select failed\n", prog);
#ifdef WIN32
fprintf(stderr, "WSAGetLastError = %u\n", WSAGetLastError());
#endif
if (select(conn.sock + 1, &fds, NULL, NULL, NULL) < 0) {
fprintf(stderr, "%s: select error\n", prog);
goto end;
}
if (read_stdin && FD_ISSET(STDIN_FILENO, &fds)) {
if (fgets(buf, sizeof(buf), stdin)) {
if (tls_send(&conn, (uint8_t *)buf, strlen(buf), &len) != 1) {
fprintf(stderr, "%s: send error\n", prog);
goto end;
}
} else {
if (!feof(stdin)) {
fprintf(stderr, "%s: length of input line exceeds buffer size\n", prog);
goto end;
}
read_stdin = 0;
}
}
if (FD_ISSET(conn.sock, &fds)) {
for (;;) {
memset(buf, 0, sizeof(buf));
if (tls_recv(&conn, (uint8_t *)buf, sizeof(buf), &len) != 1) {
goto end;
}
int rv;
rv = tls_recv(&conn, (uint8_t *)buf, sizeof(buf), &len);
if (rv == 1) {
fwrite(buf, 1, len, stdout);
fflush(stdout);
// 应该调整tls_recv 逻辑、API或者其他方式
if (conn.datalen == 0) {
break;
}
}
}
#ifdef WIN32
#else
if (FD_ISSET(fileno(stdin), &fds)) {
fprintf(stderr, "recv from stdin\n");
memset(send_buf, 0, sizeof(send_buf));
if (!fgets(send_buf, sizeof(send_buf), stdin)) {
if (feof(stdin)) {
tls_shutdown(&conn);
goto end;
} else {
continue;
}
}
if (tls_send(&conn, (uint8_t *)send_buf, strlen(send_buf), &sentlen) != 1) {
fprintf(stderr, "%s: send error\n", prog);
} else if (rv == 0) {
fprintf(stderr, "Connection closed by remote host\n");
goto end;
} else if (rv == -EAGAIN) {
// should not happen
error_print();
goto end;
} else {
error_print();
fprintf(stderr, "%s: tls_recv error\n", prog);
goto end;
}
}
#endif
fprintf(stderr, "end of this round\n");
}
end:
// FIXME: clean ctx and connection ASAP, as Ctrl-C is not handled
if (sock != -1) tls_socket_close(sock);
tls_ctx_cleanup(&ctx);
tls_cleanup(&conn);
return 0;
return ret;
}