tls13_client.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. /*
  2. * Copyright 2014-2022 The GmSSL Project. All Rights Reserved.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the License); you may
  5. * not use this file except in compliance with the License.
  6. *
  7. * http://www.apache.org/licenses/LICENSE-2.0
  8. */
  9. #include <stdio.h>
  10. #include <errno.h>
  11. #include <string.h>
  12. #include <stdlib.h>
  13. #include <gmssl/tls.h>
  14. #include <gmssl/error.h>
  15. // TLSv1.2客户单和TLCP客户端可能没有什么区别
  16. static int client_ciphers[] = { TLS_cipher_sm4_gcm_sm3 };
  17. static const char *http_get =
  18. "GET / HTTP/1.1\r\n"
  19. "Hostname: aaa\r\n"
  20. "\r\n\r\n";
  21. static const char *options = "-host str [-port num] [-cacert file] [-cert file -key file -pass str]";
  22. int tls13_client_main(int argc, char *argv[])
  23. {
  24. int ret = -1;
  25. char *prog = argv[0];
  26. char *host = NULL;
  27. int port = 443;
  28. char *cacertfile = NULL;
  29. char *certfile = NULL;
  30. char *keyfile = NULL;
  31. char *pass = NULL;
  32. struct hostent *hp;
  33. struct sockaddr_in server;
  34. tls_socket_t sock;
  35. TLS_CTX ctx;
  36. TLS_CONNECT conn;
  37. char buf[1024] = {0};
  38. size_t len = sizeof(buf);
  39. char send_buf[1024] = {0};
  40. argc--;
  41. argv++;
  42. if (argc < 1) {
  43. fprintf(stderr, "usage: %s %s\n", prog, options);
  44. return 1;
  45. }
  46. while (argc >= 1) {
  47. if (!strcmp(*argv, "-help")) {
  48. printf("usage: %s %s\n", prog, options);
  49. return 0;
  50. } else if (!strcmp(*argv, "-host")) {
  51. if (--argc < 1) goto bad;
  52. host = *(++argv);
  53. } else if (!strcmp(*argv, "-port")) {
  54. if (--argc < 1) goto bad;
  55. port = atoi(*(++argv));
  56. } else if (!strcmp(*argv, "-cacert")) {
  57. if (--argc < 1) goto bad;
  58. cacertfile = *(++argv);
  59. } else if (!strcmp(*argv, "-cert")) {
  60. if (--argc < 1) goto bad;
  61. certfile = *(++argv);
  62. } else if (!strcmp(*argv, "-key")) {
  63. if (--argc < 1) goto bad;
  64. keyfile = *(++argv);
  65. } else if (!strcmp(*argv, "-pass")) {
  66. if (--argc < 1) goto bad;
  67. pass = *(++argv);
  68. } else {
  69. fprintf(stderr, "%s: invalid option '%s'\n", prog, *argv);
  70. return 1;
  71. bad:
  72. fprintf(stderr, "%s: option '%s' argument required\n", prog, *argv);
  73. return 0;
  74. }
  75. argc--;
  76. argv++;
  77. }
  78. if (!host) {
  79. fprintf(stderr, "%s: '-in' option required\n", prog);
  80. return -1;
  81. }
  82. if (tls_socket_lib_init() != 1) {
  83. error_print();
  84. return -1;
  85. }
  86. if (!(hp = gethostbyname(host))) {
  87. //herror("tls13_client: '-host' invalid");
  88. goto end;
  89. }
  90. memset(&ctx, 0, sizeof(ctx));
  91. memset(&conn, 0, sizeof(conn));
  92. server.sin_addr = *((struct in_addr *)hp->h_addr_list[0]);
  93. server.sin_family = AF_INET;
  94. server.sin_port = htons(port);
  95. if (tls_socket_create(&sock, AF_INET, SOCK_STREAM, 0) != 1) {
  96. fprintf(stderr, "%s: socket create error\n", prog);
  97. goto end;
  98. }
  99. if (tls_socket_connect(sock, &server) != 1) {
  100. fprintf(stderr, "%s: socket connect error\n", prog);
  101. goto end;
  102. }
  103. if (tls_ctx_init(&ctx, TLS_protocol_tls13, TLS_client_mode) != 1
  104. || tls_ctx_set_cipher_suites(&ctx, client_ciphers, sizeof(client_ciphers)/sizeof(client_ciphers[0])) != 1) {
  105. fprintf(stderr, "%s: context init error\n", prog);
  106. goto end;
  107. }
  108. if (cacertfile) {
  109. if (tls_ctx_set_ca_certificates(&ctx, cacertfile, TLS_DEFAULT_VERIFY_DEPTH) != 1) {
  110. fprintf(stderr, "%s: context init error\n", prog);
  111. goto end;
  112. }
  113. }
  114. if (certfile) {
  115. if (tls_ctx_set_certificate_and_key(&ctx, certfile, keyfile, pass) != 1) {
  116. fprintf(stderr, "%s: context init error\n", prog);
  117. goto end;
  118. }
  119. }
  120. if (tls_init(&conn, &ctx) != 1
  121. || tls_set_socket(&conn, sock) != 1
  122. || tls_do_handshake(&conn) != 1) {
  123. fprintf(stderr, "%s: error\n", prog);
  124. goto end;
  125. }
  126. for (;;) {
  127. fd_set fds;
  128. size_t sentlen;
  129. if (!fgets(send_buf, sizeof(send_buf), stdin)) {
  130. if (feof(stdin)) {
  131. tls_shutdown(&conn);
  132. goto end;
  133. } else {
  134. continue;
  135. }
  136. }
  137. if (tls13_send(&conn, (uint8_t *)send_buf, strlen(send_buf), &sentlen) != 1) {
  138. fprintf(stderr, "%s: send error\n", prog);
  139. goto end;
  140. }
  141. FD_ZERO(&fds);
  142. FD_SET(conn.sock, &fds);
  143. #ifdef WIN32
  144. #else
  145. FD_SET(fileno(stdin), &fds);
  146. #endif
  147. if (select((int)(conn.sock + 1), // In WinSock2, select() ignore the this arg
  148. &fds, NULL, NULL, NULL) < 0) {
  149. fprintf(stderr, "%s: select failed\n", prog);
  150. goto end;
  151. }
  152. if (FD_ISSET(conn.sock, &fds)) {
  153. for (;;) {
  154. memset(buf, 0, sizeof(buf));
  155. if (tls13_recv(&conn, (uint8_t *)buf, sizeof(buf), &len) != 1) {
  156. goto end;
  157. }
  158. fwrite(buf, 1, len, stdout);
  159. fflush(stdout);
  160. // 应该调整tls_recv 逻辑、API或者其他方式
  161. if (conn.datalen == 0) {
  162. break;
  163. }
  164. }
  165. }
  166. #ifdef WIN32
  167. #else
  168. if (FD_ISSET(fileno(stdin), &fds)) {
  169. memset(send_buf, 0, sizeof(send_buf));
  170. if (!fgets(send_buf, sizeof(send_buf), stdin)) {
  171. if (feof(stdin)) {
  172. tls_shutdown(&conn);
  173. goto end;
  174. } else {
  175. continue;
  176. }
  177. }
  178. if (tls13_send(&conn, (uint8_t *)send_buf, strlen(send_buf), &sentlen) != 1) {
  179. fprintf(stderr, "%s: send error\n", prog);
  180. goto end;
  181. }
  182. }
  183. #endif
  184. }
  185. end:
  186. tls_socket_close(sock);
  187. tls_ctx_cleanup(&ctx);
  188. tls_cleanup(&conn);
  189. return 0;
  190. }