Fix CVE-2017-6891 in minitasn1 code
[platform/upstream/gnutls.git] / tests / mini-loss-time.c
1 /*
2  * Copyright (C) 2012 Free Software Foundation, Inc.
3  *
4  * Author: 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 General Public License
19  * along with GnuTLS; if not, write to the Free Software Foundation,
20  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
21  */
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30
31 #if defined(_WIN32)
32
33 int main()
34 {
35         exit(77);
36 }
37
38 #else
39
40 #include <sys/types.h>
41 #include <netinet/in.h>
42 #include <sys/socket.h>
43 #include <sys/wait.h>
44 #include <arpa/inet.h>
45 #include <unistd.h>
46 #include <gnutls/gnutls.h>
47 #include <gnutls/dtls.h>
48 #include <signal.h>
49
50 #include "utils.h"
51
52 /* This program tests whether a DTLS handshake would timeout
53  * in the expected time.
54  */
55
56 static void print_type(const unsigned char *buf, int size)
57 {
58         if (buf[0] == 22 && size >= 13) {
59                 if (buf[13] == 1)
60                         fprintf(stderr, "Client Hello\n");
61                 else if (buf[13] == 2)
62                         fprintf(stderr, "Server Hello\n");
63                 else if (buf[13] == 12)
64                         fprintf(stderr, "Server Key exchange\n");
65                 else if (buf[13] == 14)
66                         fprintf(stderr, "Server Hello Done\n");
67                 else if (buf[13] == 11)
68                         fprintf(stderr, "Certificate\n");
69                 else if (buf[13] == 16)
70                         fprintf(stderr, "Client Key Exchange\n");
71                 else if (buf[4] == 1)
72                         fprintf(stderr, "Finished\n");
73                 else if (buf[13] == 11)
74                         fprintf(stderr, "Server Hello Done\n");
75                 else
76                         fprintf(stderr, "Unknown handshake\n");
77         } else if (buf[0] == 20) {
78                 fprintf(stderr, "Change Cipher Spec\n");
79         } else
80                 fprintf(stderr, "Unknown\n");
81 }
82
83 static void server_log_func(int level, const char *str)
84 {
85         fprintf(stderr, "server|<%d>| %s", level, str);
86 }
87
88 static void client_log_func(int level, const char *str)
89 {
90         fprintf(stderr, "client|<%d>| %s", level, str);
91 }
92
93 /* A very basic TLS client, with anonymous authentication.
94  */
95
96 static int counter;
97 static int packet_to_lose;
98
99 static ssize_t
100 push(gnutls_transport_ptr_t tr, const void *data, size_t len)
101 {
102         int fd = (long int) tr;
103
104         counter++;
105
106         if (packet_to_lose != -1 && packet_to_lose == counter) {
107                 if (debug) {
108                         fprintf(stderr, "Discarding packet %d: ", counter);
109                         print_type(data, len);
110                 }
111
112                 packet_to_lose = 1;
113                 counter = 0;
114                 return len;
115         }
116         return send(fd, data, len, 0);
117 }
118
119 static void client(int fd, unsigned timeout)
120 {
121         int ret;
122         gnutls_anon_client_credentials_t anoncred;
123         gnutls_session_t session;
124         /* Need to enable anonymous KX specifically. */
125
126         global_init();
127
128         if (debug) {
129                 gnutls_global_set_log_function(client_log_func);
130                 gnutls_global_set_log_level(4711);
131         }
132
133         gnutls_anon_allocate_client_credentials(&anoncred);
134
135         /* Initialize TLS session
136          */
137         gnutls_init(&session, GNUTLS_CLIENT | GNUTLS_DATAGRAM);
138         gnutls_dtls_set_mtu(session, 1500);
139         gnutls_dtls_set_timeouts(session, 1 * 1000, timeout * 1000);
140
141         /* Use default priorities */
142         gnutls_priority_set_direct(session,
143                                    "NONE:+VERS-DTLS1.0:+CIPHER-ALL:+MAC-ALL:+SIGN-ALL:+COMP-ALL:+ANON-ECDH:+CURVE-ALL",
144                                    NULL);
145
146         /* put the anonymous credentials to the current session
147          */
148         gnutls_credentials_set(session, GNUTLS_CRD_ANON, anoncred);
149
150         counter = 0;
151
152         gnutls_transport_set_int(session, fd);
153
154         /* Perform the TLS handshake
155          */
156         do {
157                 ret = gnutls_handshake(session);
158         }
159         while (ret < 0 && (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED));
160
161         gnutls_deinit(session);
162         gnutls_anon_free_client_credentials(anoncred);
163         gnutls_global_deinit();
164
165         if (ret < 0) {
166                 if (ret == GNUTLS_E_TIMEDOUT) {
167                         if (debug)
168                                 success("client: received timeout\n");
169                         return;
170                 }
171                 fail("client: Handshake failed with unexpected reason: %s\n", gnutls_strerror(ret));
172         } else {
173                 fail("client: Handshake was completed (unexpected)\n");
174         }
175 }
176
177
178 /* These are global */
179 pid_t child;
180
181 static void server(int fd, int packet, unsigned timeout)
182 {
183         gnutls_anon_server_credentials_t anoncred;
184         gnutls_session_t session;
185         int ret;
186         /* this must be called once in the program
187          */
188         global_init();
189
190         if (debug) {
191                 gnutls_global_set_log_function(server_log_func);
192                 gnutls_global_set_log_level(4711);
193         }
194
195         gnutls_anon_allocate_server_credentials(&anoncred);
196
197         gnutls_init(&session, GNUTLS_SERVER | GNUTLS_DATAGRAM);
198         gnutls_dtls_set_mtu(session, 1500);
199         gnutls_dtls_set_timeouts(session, 1 * 1000, timeout * 1000);
200
201         /* avoid calling all the priority functions, since the defaults
202          * are adequate.
203          */
204         gnutls_priority_set_direct(session,
205                                    "NONE:+VERS-DTLS1.0:+CIPHER-ALL:+MAC-ALL:+SIGN-ALL:+COMP-ALL:+ANON-ECDH:+CURVE-ALL",
206                                    NULL);
207
208         gnutls_credentials_set(session, GNUTLS_CRD_ANON, anoncred);
209
210         counter = 0;
211         packet_to_lose = packet;
212
213         gnutls_transport_set_int(session, fd);
214         gnutls_transport_set_push_function(session, push);
215
216         do {
217                 ret = gnutls_handshake(session);
218         }
219         while (ret < 0 && (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED));
220
221         gnutls_deinit(session);
222         gnutls_anon_free_server_credentials(anoncred);
223         gnutls_global_deinit();
224
225         if (ret < 0) {
226                 if (ret == GNUTLS_E_TIMEDOUT) {
227                         if (debug)
228                                 success("server received timeout\n");
229                         return;
230                 }
231                 fail("server: Handshake failed with unexpected reason: %s\n", gnutls_strerror(ret));
232         } else {
233                 fail("server: Handshake was completed (unexpected)\n");
234         }
235
236         if (ret < 0) {
237                 return;
238         }
239 }
240
241 static void start(int server_packet, int wait_server)
242 {
243         int fd[2];
244         int ret;
245
246         if (debug)
247                 fprintf(stderr, "\nWill discard server packet %d\n",
248                         server_packet);
249
250         /* we need dgram in this test */
251         ret = socketpair(AF_UNIX, SOCK_DGRAM, 0, fd);
252         if (ret < 0) {
253                 perror("socketpair");
254                 exit(1);
255         }
256
257         child = fork();
258         if (child < 0) {
259                 perror("fork");
260                 fail("fork");
261                 exit(1);
262         }
263
264         if (child) {
265                 /* parent */
266                 close(fd[0]);
267                 if (wait_server)
268                         server(fd[1], server_packet, 30);
269                 else
270                         client(fd[1], 30);
271                 close(fd[1]);
272                 kill(child, SIGTERM);
273         } else {
274                 close(fd[1]);
275                 if (wait_server)
276                         client(fd[0], 32);
277                 else
278                         server(fd[0], server_packet, 32);
279                 close(fd[0]);
280                 exit(0);
281         }
282 }
283
284 static void ch_handler(int sig)
285 {
286         int status = 0;
287         wait(&status);
288         if (WEXITSTATUS(status) != 0)
289                 fail("Child died with status %d\n", WEXITSTATUS(status));
290         return;
291 }
292
293 void doit(void)
294 {
295         time_t tstart, tstop;
296         int tries = 5; /* we try multiple times because in very busy systems the suite may fail to finish on time */
297
298         signal(SIGCHLD, ch_handler);
299         signal(SIGPIPE, SIG_IGN);
300
301 #if 0
302         for (;tries>=0;tries--) {
303                 tstart = time(0);
304                 start(2, 0);
305
306                 tstop = time(0);
307
308                 tstop = tstop - tstart;
309
310                 if (!(tstop < 40 && tstop > 25)) {
311                         if (tries == 0)
312                                 fail("Client wait time difference: %u\n", (unsigned) tstop);
313                         else if (debug)
314                                 success("Client wait time difference: %u\n", (unsigned) tstop);
315                 } else break;
316         }
317 #endif
318
319         for (;tries>=0;tries--) {
320                 tstart = time(0);
321                 start(2, 1);
322
323                 tstop = time(0);
324
325                 tstop = tstop - tstart;
326
327                 if (!(tstop < 40 && tstop > 25)) {
328                         if (tries == 0)
329                                 fail("Server wait time difference: %u\n", (unsigned) tstop);
330                         else if (debug)
331                                 success("Server wait time difference: %u\n", (unsigned) tstop);
332                 } else break;
333         }
334 }
335
336 #endif                          /* _WIN32 */