1 /*
2 * Copyright (C) 2017 Red Hat, Inc.
3 *
4 * Author: Thierry Quemerais, Nikos Mavrogiannopoulos
5 *
6 * This file is part of GnuTLS.
7 *
8 * GnuTLS is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * GnuTLS is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program. If not, see <https://www.gnu.org/licenses/>
20 */
21
22 /* This program tests whether a cookie sent by the server is repeated
23 * by the gnutls client. */
24
25 #ifdef HAVE_CONFIG_H
26 #include <config.h>
27 #endif
28
29 #include <stdio.h>
30 #include <stdlib.h>
31
32 #if defined(_WIN32)
33
34 /* socketpair isn't supported on Win32. */
main(int argc,char ** argv)35 int main(int argc, char **argv)
36 {
37 exit(77);
38 }
39
40 #else
41
42 #include <string.h>
43 #include <sys/types.h>
44 #include <sys/socket.h>
45 #if !defined(_WIN32)
46 #include <sys/wait.h>
47 #include <signal.h>
48 #endif
49 #include <unistd.h>
50 #include <gnutls/gnutls.h>
51 #include <assert.h>
52
53 #include "utils.h"
54 #include "cert-common.h"
55
56 const char *side = "";
57
tls_log_func(int level,const char * str)58 static void tls_log_func(int level, const char *str)
59 {
60 fprintf(stderr, "%s|<%d>| %s", side, level, str);
61 }
62
63 static int TLSEXT_TYPE_server_sent = 0;
64 static int TLSEXT_TYPE_server_received = 0;
65
66 static const unsigned char ext_data[] =
67 {
68 0x00,
69 0x03,
70 0xFE,
71 0xED,
72 0xFF
73 };
74
ext_recv_server_cookie(gnutls_session_t session,const unsigned char * buf,size_t buflen)75 static int ext_recv_server_cookie(gnutls_session_t session, const unsigned char *buf, size_t buflen)
76 {
77 if (buflen != sizeof(ext_data))
78 fail("ext_recv_server_params: Invalid input buffer length\n");
79
80 if (memcmp(buf, ext_data, sizeof(ext_data)) != 0)
81 fail("ext_recv_server_params: Invalid input buffer data\n");
82
83 TLSEXT_TYPE_server_received = 1;
84
85 return 0; //Success
86 }
87
ext_send_server_cookie(gnutls_session_t session,gnutls_buffer_t extdata)88 static int ext_send_server_cookie(gnutls_session_t session, gnutls_buffer_t extdata)
89 {
90 if (gnutls_ext_get_current_msg(session) == GNUTLS_EXT_FLAG_HRR) {
91 TLSEXT_TYPE_server_sent = 1;
92
93 gnutls_buffer_append_data(extdata, ext_data, sizeof(ext_data));
94 return sizeof(ext_data);
95 }
96 return 0;
97 }
98
client(int sd)99 static void client(int sd)
100 {
101 int ret;
102 gnutls_session_t session;
103 gnutls_certificate_credentials_t clientx509cred;
104
105 global_init();
106 gnutls_global_set_log_function(tls_log_func);
107 if (debug)
108 gnutls_global_set_log_level(4711);
109
110 side = "client";
111
112 gnutls_certificate_allocate_credentials(&clientx509cred);
113
114 /* Initialize TLS session
115 */
116 gnutls_init(&session, GNUTLS_CLIENT);
117
118 /* Use default priorities */
119 assert(gnutls_priority_set_direct(session, "NORMAL:-VERS-ALL:+VERS-TLS1.3",
120 NULL)>=0);
121
122 /* put the anonymous credentials to the current session
123 */
124 gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE,
125 clientx509cred);
126
127 gnutls_transport_set_int(session, sd);
128 gnutls_handshake_set_timeout(session, 20 * 1000);
129
130 /* Perform the TLS handshake
131 */
132 ret = gnutls_handshake(session);
133
134 if (ret < 0) {
135 fail("client: Handshake failed: %s\n", gnutls_strerror(ret));
136 goto end;
137 } else {
138 if (debug)
139 success("client: Handshake was completed\n");
140 }
141
142 gnutls_bye(session, GNUTLS_SHUT_WR);
143
144 end:
145 close(sd);
146
147 gnutls_deinit(session);
148
149 gnutls_certificate_free_credentials(clientx509cred);
150
151 gnutls_global_deinit();
152 }
153
server(int sd)154 static void server(int sd)
155 {
156 gnutls_certificate_credentials_t serverx509cred;
157 int ret;
158 gnutls_session_t session;
159
160 /* this must be called once in the program
161 */
162 global_init();
163 gnutls_global_set_log_function(tls_log_func);
164 if (debug)
165 gnutls_global_set_log_level(4711);
166
167 side = "server";
168
169 gnutls_certificate_allocate_credentials(&serverx509cred);
170 gnutls_certificate_set_x509_key_mem(serverx509cred,
171 &server_cert, &server_key,
172 GNUTLS_X509_FMT_PEM);
173
174 gnutls_init(&session, GNUTLS_SERVER);
175
176
177 /* force a hello retry request by disabling all the groups that are
178 * enabled by default. */
179 assert(gnutls_priority_set_direct(session,
180 "NORMAL:-VERS-ALL:+VERS-TLS1.3:"
181 "-GROUP-SECP256R1:-GROUP-X25519:-GROUP-FFDHE2048",
182 NULL)>=0);
183
184 gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE,
185 serverx509cred);
186
187 ret = gnutls_session_ext_register(session, "cookie_server", 44, GNUTLS_EXT_TLS, ext_recv_server_cookie, ext_send_server_cookie,
188 NULL, NULL, NULL,
189 GNUTLS_EXT_FLAG_CLIENT_HELLO|GNUTLS_EXT_FLAG_HRR|GNUTLS_EXT_FLAG_OVERRIDE_INTERNAL|GNUTLS_EXT_FLAG_IGNORE_CLIENT_REQUEST);
190 if (ret != 0)
191 fail("server: cannot register: %s", gnutls_strerror(ret));
192
193 gnutls_transport_set_int(session, sd);
194 gnutls_handshake_set_timeout(session, 20 * 1000);
195
196 ret = gnutls_handshake(session);
197 if (ret < 0) {
198 fail("server: Handshake has failed: %s\n\n",
199 gnutls_strerror(ret));
200 goto end;
201 }
202 if (debug)
203 success("server: Handshake was completed\n");
204
205 if (TLSEXT_TYPE_server_sent != 1)
206 fail("server: extension not properly sent\n");
207
208 if (TLSEXT_TYPE_server_received != 1)
209 fail("server: extension not properly received\n");
210
211 /* do not wait for the peer to close the connection.
212 */
213 gnutls_bye(session, GNUTLS_SHUT_WR);
214
215 end:
216 close(sd);
217 gnutls_deinit(session);
218
219 gnutls_certificate_free_credentials(serverx509cred);
220
221 gnutls_global_deinit();
222
223 if (debug)
224 success("server: finished\n");
225 }
226
doit(void)227 void doit(void)
228 {
229 pid_t child;
230 int sockets[2];
231 int err;
232
233 signal(SIGPIPE, SIG_IGN);
234
235 err = socketpair(AF_UNIX, SOCK_STREAM, 0, sockets);
236 if (err == -1) {
237 perror("socketpair");
238 fail("socketpair failed\n");
239 return;
240 }
241
242 TLSEXT_TYPE_server_sent = 0;
243 TLSEXT_TYPE_server_received = 0;
244
245 child = fork();
246 if (child < 0) {
247 perror("fork");
248 fail("fork");
249 return;
250 }
251
252 if (child) {
253 int status = 0;
254 /* parent */
255 close(sockets[1]);
256 server(sockets[0]);
257 wait(&status);
258 } else {
259 close(sockets[0]);
260 client(sockets[1]);
261 exit(0);
262 }
263 }
264
265 #endif /* _WIN32 */
266