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
10
11 #include <stdio.h>
12 #include <errno.h>
13 #include <string.h>
14 #include <stdlib.h>
15 #include <unistd.h>
16 #include <sys/types.h>
17 #include <arpa/inet.h>
18 #include <sys/socket.h>
19 #include <netinet/in.h>
20 #include <gmssl/mem.h>
21 #include <gmssl/sm2.h>
22 #include <gmssl/tls.h>
23 #include <gmssl/error.h>
24
25
26 static const char *options = "[-port num] -cert file -key file [-pass str] -ex_key file [-ex_pass str] [-cacert file]";
27
tlcp_server_main(int argc,char ** argv)28 int tlcp_server_main(int argc , char **argv)
29 {
30 int ret = 1;
31 char *prog = argv[0];
32 int port = 443;
33 char *certfile = NULL;
34 char *signkeyfile = NULL;
35 char *signpass = NULL;
36 char *enckeyfile = NULL;
37 char *encpass = NULL;
38 char *cacertfile = NULL;
39
40 int server_ciphers[] = { TLS_cipher_ecc_sm4_cbc_sm3, };
41 uint8_t verify_buf[4096];
42
43 TLS_CTX ctx;
44 TLS_CONNECT conn;
45 char buf[1600] = {0};
46 size_t len = sizeof(buf);
47
48 int sock;
49 struct sockaddr_in server_addr;
50 struct sockaddr_in client_addr;
51 socklen_t client_addrlen;
52 int conn_sock;
53
54
55 argc--;
56 argv++;
57
58 if (argc < 1) {
59 fprintf(stderr, "usage: %s %s\n", prog, options);
60 return 1;
61 }
62
63 while (argc > 0) {
64 if (!strcmp(*argv, "-help")) {
65 printf("usage: %s %s\n", prog, options);
66 return 0;
67 } else if (!strcmp(*argv, "-port")) {
68 if (--argc < 1) goto bad;
69 port = atoi(*(++argv));
70 } else if (!strcmp(*argv, "-cert")) {
71 if (--argc < 1) goto bad;
72 certfile = *(++argv);
73 } else if (!strcmp(*argv, "-key")) {
74 if (--argc < 1) goto bad;
75 signkeyfile = *(++argv);
76 } else if (!strcmp(*argv, "-pass")) {
77 if (--argc < 1) goto bad;
78 signpass = *(++argv);
79 } else if (!strcmp(*argv, "-ex_key")) {
80 if (--argc < 1) goto bad;
81 enckeyfile = *(++argv);
82 } else if (!strcmp(*argv, "-ex_pass")) {
83 if (--argc < 1) goto bad;
84 encpass = *(++argv);
85 } else if (!strcmp(*argv, "-cacert")) {
86 if (--argc < 1) goto bad;
87 cacertfile = *(++argv);
88 } else {
89 fprintf(stderr, "%s: invalid option '%s'\n", prog, *argv);
90 return 1;
91 bad:
92 fprintf(stderr, "%s: option '%s' argument required\n", prog, *argv);
93 return 1;
94 }
95 argc--;
96 argv++;
97 }
98 if (!certfile) {
99 fprintf(stderr, "%s: '-cert' option required\n", prog);
100 return 1;
101 }
102 if (!signkeyfile) {
103 fprintf(stderr, "%s: '-key' option required\n", prog);
104 return 1;
105 }
106 if (!signpass) {
107 fprintf(stderr, "%s: '-pass' option required\n", prog);
108 return 1;
109 }
110 if (!enckeyfile) {
111 fprintf(stderr, "%s: '-ex_key' option required\n", prog);
112 return 1;
113 }
114 if (!encpass) {
115 fprintf(stderr, "%s: '-ex_pass' option required\n", prog);
116 return 1;
117 }
118
119 memset(&ctx, 0, sizeof(ctx));
120 memset(&conn, 0, sizeof(conn));
121
122 if (tls_ctx_init(&ctx, TLS_protocol_tlcp, TLS_server_mode) != 1
123 || tls_ctx_set_cipher_suites(&ctx, server_ciphers, sizeof(server_ciphers)/sizeof(int)) != 1
124 || tls_ctx_set_tlcp_server_certificate_and_keys(&ctx, certfile, signkeyfile, signpass, enckeyfile, encpass) != 1) {
125 error_print();
126 return -1;
127 }
128 if (cacertfile) {
129 if (tls_ctx_set_ca_certificates(&ctx, cacertfile, TLS_DEFAULT_VERIFY_DEPTH) != 1) {
130 error_print();
131 return -1;
132 }
133 }
134
135 // Socket
136 if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
137 error_print();
138 return 1;
139 }
140 server_addr.sin_family = AF_INET;
141 server_addr.sin_addr.s_addr = INADDR_ANY;
142 server_addr.sin_port = htons(port);
143 if (bind(sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
144 error_print();
145 perror("tlcp_accept: bind: ");
146 goto end;
147 }
148 puts("start listen ...\n");
149 listen(sock, 1);
150
151
152
153 restart:
154
155 client_addrlen = sizeof(client_addr);
156 if ((conn_sock = accept(sock, (struct sockaddr *)&client_addr, &client_addrlen)) < 0) {
157 error_print();
158 goto end;
159 }
160 puts("socket connected\n");
161
162 if (tls_init(&conn, &ctx) != 1
163 || tls_set_socket(&conn, conn_sock) != 1) {
164 error_print();
165 return -1;
166 }
167
168 if (tls_do_handshake(&conn) != 1) {
169 error_print(); // 为什么这个会触发呢?
170 return -1;
171 }
172
173 for (;;) {
174
175 int rv;
176 size_t sentlen;
177
178 do {
179 len = sizeof(buf);
180 if ((rv = tls_recv(&conn, (uint8_t *)buf, sizeof(buf), &len)) != 1) {
181 if (rv < 0) fprintf(stderr, "%s: recv failure\n", prog);
182 else fprintf(stderr, "%s: Disconnected by remote\n", prog);
183
184 //close(conn.sock);
185 tls_cleanup(&conn);
186 goto restart;
187 }
188 } while (!len);
189
190 if (tls_send(&conn, (uint8_t *)buf, len, &sentlen) != 1) {
191 fprintf(stderr, "%s: send failure, close connection\n", prog);
192 close(conn.sock);
193 goto end;
194 }
195 }
196
197
198 end:
199 return ret;
200 }
201