tests: added sanity check for rfc7633 behavior
[gd/gnutls] / tests / rfc7633-ok.c
1 /*
2  * Copyright (C) 2016-2019 Tim Kosse
3  * Copyright (C) 2019 Nikos Mavrogiannopoulos
4  *
5  * Author: Tim Kosse, Nikos Mavrogiannopoulos
6  *
7  * This file is part of GnuTLS.
8  *
9  * GnuTLS is free software; you can redistribute it and/or modify it
10  * under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 3 of the License, or
12  * (at your option) any later version.
13  *
14  * GnuTLS is distributed in the hope that it will be useful, but
15  * WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public License
20  * along with this program.  If not, see <https://www.gnu.org/licenses/>
21  *
22  */
23
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <assert.h>
31
32 #if defined(_WIN32)
33
34 int main()
35 {
36         exit(77);
37 }
38
39 #else
40
41 #include <string.h>
42 #include <sys/types.h>
43 #include <netinet/in.h>
44 #include <sys/socket.h>
45 #include <sys/wait.h>
46 #include <arpa/inet.h>
47 #include <unistd.h>
48 #include <time.h>
49 #include <gnutls/gnutls.h>
50 #include <gnutls/dtls.h>
51 #include <signal.h>
52
53 #include "utils.h"
54 #include "cert-common.h"
55
56 /* This program tests that handshakes succeed if the server includes the
57  * requested certificate status with the server certificate having
58  * TLS feature 5 (status request).
59  *
60  * See RFC 7633
61  */
62
63 static time_t mytime(time_t * t)
64 {
65         time_t then = 1559941819;
66         if (t)
67                 *t = then;
68
69         return then;
70 }
71
72 static void server_log_func(int level, const char *str)
73 {
74         fprintf(stderr, "server|<%d>| %s", level, str);
75 }
76
77 static void client_log_func(int level, const char *str)
78 {
79         fprintf(stderr, "client|<%d>| %s", level, str);
80 }
81
82 const unsigned char ocsp_resp[] = {
83   0x30, 0x82, 0x02, 0x3f, 0x0a, 0x01, 0x00, 0xa0, 0x82, 0x02, 0x38, 0x30,
84   0x82, 0x02, 0x34, 0x06, 0x09, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30,
85   0x01, 0x01, 0x04, 0x82, 0x02, 0x25, 0x30, 0x82, 0x02, 0x21, 0x30, 0x81,
86   0x8a, 0xa1, 0x11, 0x30, 0x0f, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x03, 0x55,
87   0x04, 0x03, 0x13, 0x04, 0x43, 0x41, 0x2d, 0x33, 0x18, 0x0f, 0x32, 0x30,
88   0x31, 0x39, 0x30, 0x36, 0x30, 0x37, 0x32, 0x31, 0x31, 0x35, 0x32, 0x32,
89   0x5a, 0x30, 0x64, 0x30, 0x62, 0x30, 0x4d, 0x30, 0x09, 0x06, 0x05, 0x2b,
90   0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14, 0xb7, 0xca, 0x0f, 0xab,
91   0xdc, 0x6f, 0xb8, 0xb0, 0x96, 0x7a, 0x15, 0xac, 0x98, 0x0a, 0x0f, 0x19,
92   0xfe, 0xa4, 0x12, 0xde, 0x04, 0x14, 0x1e, 0x85, 0xed, 0x7f, 0x9e, 0x71,
93   0xfa, 0x08, 0x9d, 0x37, 0x48, 0x43, 0xa0, 0x12, 0xef, 0xe5, 0xaa, 0xe1,
94   0xe3, 0x8a, 0x02, 0x14, 0x60, 0x14, 0x5f, 0x01, 0xcb, 0xe0, 0x05, 0x45,
95   0x38, 0x8c, 0x26, 0xfc, 0x5b, 0xcf, 0x6c, 0x41, 0xc3, 0xcb, 0xaa, 0xcc,
96   0x80, 0x00, 0x18, 0x0f, 0x32, 0x30, 0x31, 0x39, 0x30, 0x36, 0x30, 0x37,
97   0x32, 0x31, 0x31, 0x35, 0x32, 0x32, 0x5a, 0x30, 0x0d, 0x06, 0x09, 0x2a,
98   0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82,
99   0x01, 0x81, 0x00, 0x44, 0xc4, 0x59, 0xab, 0x7b, 0x6e, 0x35, 0x4e, 0x18,
100   0x83, 0x02, 0xbd, 0x94, 0x26, 0x50, 0x01, 0xe2, 0xb1, 0x50, 0xdd, 0xca,
101   0x61, 0x30, 0xb0, 0x93, 0x18, 0x56, 0xfe, 0x8d, 0x4f, 0xcc, 0x33, 0xc8,
102   0x01, 0x1e, 0xac, 0xa1, 0x8e, 0xb0, 0x76, 0x0f, 0x41, 0x38, 0x7d, 0x06,
103   0x9b, 0xfe, 0x09, 0x50, 0x6d, 0x86, 0x07, 0x2a, 0x48, 0x6e, 0x6a, 0xb1,
104   0x13, 0xf4, 0xc0, 0x0f, 0x7c, 0x7d, 0x89, 0xb9, 0x69, 0xe7, 0x04, 0x2e,
105   0xa4, 0x3d, 0xf6, 0xbd, 0x51, 0xbf, 0x52, 0x7d, 0xfb, 0x38, 0x7a, 0xbf,
106   0xe6, 0xd7, 0x32, 0x57, 0x36, 0x87, 0xec, 0x91, 0x07, 0x0c, 0xac, 0xb9,
107   0x79, 0xe7, 0x79, 0x4e, 0x49, 0x72, 0x1d, 0x16, 0xb6, 0x94, 0xbf, 0xc4,
108   0x9f, 0x4e, 0x8b, 0x51, 0x54, 0x73, 0xb4, 0x4d, 0xe7, 0x01, 0x91, 0xcd,
109   0x7c, 0xb2, 0x91, 0x4a, 0xc3, 0x4d, 0xc4, 0x4f, 0xa3, 0x42, 0xf1, 0x89,
110   0xc7, 0xab, 0x36, 0x11, 0xf0, 0x7c, 0xc6, 0x8f, 0x03, 0x53, 0x85, 0x0c,
111   0xfb, 0x30, 0x6b, 0xdd, 0x9e, 0x72, 0xd7, 0x77, 0xe5, 0xea, 0xd3, 0x39,
112   0xb5, 0xb8, 0xdd, 0x61, 0xb9, 0xe7, 0x24, 0x9c, 0x85, 0x42, 0xd7, 0x2b,
113   0x2e, 0x99, 0xdf, 0xe5, 0x8b, 0x79, 0xe3, 0x6e, 0x56, 0x6e, 0xd6, 0xed,
114   0x5f, 0x9b, 0x5f, 0x40, 0x89, 0x17, 0x1a, 0x76, 0xbb, 0x3c, 0x9f, 0x33,
115   0x71, 0xc1, 0xc5, 0x2f, 0xf4, 0x69, 0xe5, 0x5f, 0x83, 0xd4, 0x3a, 0x3d,
116   0xd7, 0x44, 0xaa, 0xc0, 0x9d, 0xd9, 0xd9, 0x99, 0xec, 0x80, 0x4c, 0x46,
117   0x5f, 0x91, 0xf4, 0x09, 0x06, 0xef, 0x37, 0x7c, 0x32, 0x64, 0x67, 0x85,
118   0x99, 0xde, 0x9c, 0xce, 0x3e, 0x58, 0x1a, 0x6c, 0x59, 0xc9, 0x60, 0x26,
119   0x02, 0xeb, 0x95, 0x52, 0x3e, 0x4f, 0xdd, 0x5f, 0x6c, 0x2d, 0x37, 0xc2,
120   0x3b, 0x72, 0x70, 0xab, 0x1d, 0xf5, 0x2a, 0xbe, 0x8c, 0x70, 0x8e, 0xf0,
121   0x25, 0x18, 0x68, 0xe5, 0xe9, 0xd1, 0xcf, 0xd8, 0x1f, 0x6c, 0x8e, 0xcf,
122   0x18, 0x46, 0x51, 0xb4, 0x69, 0xbb, 0x6f, 0x4f, 0x1e, 0x2a, 0x61, 0x3f,
123   0x64, 0x8b, 0x07, 0x7f, 0xc5, 0x80, 0xb9, 0x06, 0xd6, 0xb1, 0x8d, 0x47,
124   0x4a, 0x61, 0xd2, 0x3e, 0xb4, 0xa6, 0xab, 0x12, 0xc6, 0x5c, 0x90, 0x9e,
125   0x2e, 0x16, 0x2e, 0xd4, 0xfc, 0x4b, 0x08, 0x41, 0x94, 0xaf, 0x1d, 0x6e,
126   0x6c, 0x11, 0x5c, 0x88, 0x3d, 0xd9, 0x30, 0x9d, 0x69, 0xf7, 0x45, 0xbe,
127   0x5d, 0x1e, 0xd5, 0xe2, 0xf6, 0x38, 0xfa, 0xe1, 0xbf, 0xae, 0x9f, 0x2f,
128   0xc6, 0x7b, 0x7b, 0x98, 0x89, 0x05, 0x8d, 0x4c, 0x01, 0xad, 0x61, 0x14,
129   0x00, 0xca, 0xa3, 0xed, 0xd0, 0x2c, 0xfe, 0x1b, 0x7e, 0x1d, 0x70, 0x5b,
130   0x2e, 0xc2, 0x54, 0xcf, 0x4c, 0x0a, 0xb3, 0x21, 0x58, 0xed, 0x51, 0xe7,
131   0xeb, 0x8d, 0xb7 };
132
133 static int received = 0;
134
135 static int handshake_callback(gnutls_session_t session, unsigned int htype,
136                               unsigned post, unsigned int incoming,
137                               const gnutls_datum_t * msg)
138 {
139         received = 1;
140         return 0;
141 }
142
143 #define MAX_BUF 1024
144
145 static void client(int fd, const char *prio)
146 {
147         int ret;
148         unsigned int status;
149         gnutls_certificate_credentials_t x509_cred;
150         gnutls_session_t session;
151
152         gnutls_global_set_time_function(mytime);
153         global_init();
154
155         if (debug) {
156                 gnutls_global_set_log_function(client_log_func);
157                 gnutls_global_set_log_level(7);
158         }
159
160         assert(gnutls_certificate_allocate_credentials(&x509_cred) >= 0);
161         assert(gnutls_certificate_set_x509_trust_mem(x509_cred, &ca3_cert, GNUTLS_X509_FMT_PEM)>=0);
162
163         assert(gnutls_init(&session, GNUTLS_CLIENT) >= 0);
164
165         assert(gnutls_priority_set_direct(session, prio, NULL) >= 0);
166
167         gnutls_handshake_set_hook_function(session,
168                                            GNUTLS_HANDSHAKE_CERTIFICATE_STATUS,
169                                            GNUTLS_HOOK_POST,
170                                            handshake_callback);
171
172         gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, x509_cred);
173
174         gnutls_transport_set_int(session, fd);
175
176         do {
177                 ret = gnutls_handshake(session);
178         }
179         while (ret < 0 && gnutls_error_is_fatal(ret) == 0);
180         if (ret < 0) {
181                 fail("client: Handshake failed: %s\n", gnutls_strerror(ret));
182         } else {
183                 if (debug)
184                         success("client: Handshake was completed\n");
185         }
186
187         if (debug)
188                 success("client: TLS version is: %s\n",
189                         gnutls_protocol_get_name
190                         (gnutls_protocol_get_version(session)));
191
192         if (received == 0
193             && gnutls_protocol_get_version(session) == GNUTLS_TLS1_2) {
194                 fail("client: did not receive certificate status when we should.\n");
195         }
196
197         ret = gnutls_certificate_verify_peers2(session, &status);
198         if (ret != GNUTLS_E_SUCCESS) {
199                 fail("client: Peer certificate validation failed: %s\n",
200                      gnutls_strerror(ret));
201         } else {
202                 if (status) {
203                         gnutls_datum_t tmp;
204                         assert(gnutls_certificate_verification_status_print(status, GNUTLS_CRT_X509, &tmp, 0)>=0);
205                         fail("client: Validation status is not success (%x: %s)\n",
206                              status, (char*)tmp.data);
207                 }
208         }
209
210         gnutls_bye(session, GNUTLS_SHUT_WR);
211
212         close(fd);
213
214         gnutls_deinit(session);
215
216         gnutls_certificate_free_credentials(x509_cred);
217
218         gnutls_global_deinit();
219 }
220
221 static int status_func(gnutls_session_t session, void *ptr, gnutls_datum_t *resp)
222 {
223         resp->data = gnutls_malloc(sizeof(ocsp_resp));
224         if (resp->data == NULL)
225                 return -1;
226
227         memcpy(resp->data, ocsp_resp, sizeof(ocsp_resp));
228         resp->size = sizeof(ocsp_resp);
229         return 0;
230 }
231
232 static void server(int fd, const char *prio)
233 {
234         int ret;
235         char buffer[MAX_BUF + 1];
236         gnutls_session_t session;
237         gnutls_certificate_credentials_t x509_cred;
238
239         /* this must be called once in the program
240          */
241         global_init();
242         memset(buffer, 0, sizeof(buffer));
243
244         if (debug) {
245                 gnutls_global_set_log_function(server_log_func);
246                 gnutls_global_set_log_level(4711);
247         }
248
249         assert(gnutls_certificate_allocate_credentials(&x509_cred)>=0);
250         assert(gnutls_certificate_set_x509_key_mem(x509_cred, &server_ca3_tlsfeat_cert,
251                                             &server_ca3_key, GNUTLS_X509_FMT_PEM)>=0);
252
253         assert(gnutls_init(&session, GNUTLS_SERVER) >= 0);
254
255         assert(gnutls_priority_set_direct(session, prio, NULL) >= 0);
256
257         gnutls_certificate_set_ocsp_status_request_function(x509_cred, status_func, NULL);
258
259         gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, x509_cred);
260
261         gnutls_transport_set_int(session, fd);
262
263         do {
264                 ret = gnutls_handshake(session);
265         } while (ret < 0 && gnutls_error_is_fatal(ret) == 0);
266
267         if (ret < 0) {
268                 fail("server: Handshake failed: %s\n", gnutls_strerror(ret));
269         }
270
271         if (debug) {
272                 success("server: Handshake was completed\n");
273         }
274
275         if (debug)
276                 success("server: TLS version is: %s\n",
277                         gnutls_protocol_get_name
278                         (gnutls_protocol_get_version(session)));
279
280         /* do not wait for the peer to close the connection.
281          */
282         gnutls_bye(session, GNUTLS_SHUT_WR);
283
284         close(fd);
285         gnutls_deinit(session);
286
287         gnutls_certificate_free_credentials(x509_cred);
288
289         gnutls_global_deinit();
290
291         if (debug)
292                 success("server: finished\n");
293 }
294
295 static void ch_handler(int sig)
296 {
297         return;
298 }
299
300 static void start(const char *name, const char *prio)
301 {
302         pid_t child;
303         int fd[2];
304         int ret, status = 0;
305
306         signal(SIGCHLD, ch_handler);
307         signal(SIGPIPE, SIG_IGN);
308
309         received = 0;
310         success("running: %s\n", name);
311
312         ret = socketpair(AF_UNIX, SOCK_STREAM, 0, fd);
313         if (ret < 0) {
314                 perror("socketpair");
315                 exit(1);
316         }
317
318         child = fork();
319         if (child < 0) {
320                 perror("fork");
321                 fail("fork");
322                 exit(1);
323         }
324
325         if (child) {
326                 /* parent */
327                 close(fd[1]);
328                 client(fd[0], prio);
329                 waitpid(child, &status, 0);
330                 check_wait_status(status);
331         } else {
332                 close(fd[0]);
333                 server(fd[1], prio);
334                 exit(0);
335         }
336
337         return;
338 }
339
340 void doit(void)
341 {
342         start("tls1.2", "NORMAL:-VERS-TLS-ALL:+VERS-TLS1.2");
343         start("tls1.3", "NORMAL:-VERS-TLS-ALL:+VERS-TLS1.3");
344         start("default", "NORMAL");
345 }
346
347 #endif                          /* _WIN32 */