1 /*
2 * Copyright (C) 2020 Red Hat, 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 Lesser General Public License
19 * along with this program. If not, see <https://www.gnu.org/licenses/>
20 */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <assert.h>
29 #include <gnutls/gnutls.h>
30 #include <gnutls/x509.h>
31
32 #ifdef ENABLE_OCSP
33
34 #include "cert-common.h"
35 #include "ocsp-common.h"
36 #include "utils.h"
37
38 /* Tests whether setting an OCSP response to a client
39 * is working as expected */
40
mytime(time_t * t)41 static time_t mytime(time_t * t)
42 {
43 time_t then = OCSP_RESP_DATE;
44 if (t)
45 *t = then;
46
47 return then;
48 }
49
check_cli(gnutls_session_t session,void * priv)50 static void check_cli(gnutls_session_t session, void *priv)
51 {
52 assert((gnutls_session_get_flags(session) & GNUTLS_SFLAGS_SERV_REQUESTED_OCSP) != 0);
53 }
54
check_serv(gnutls_session_t session,void * priv)55 static void check_serv(gnutls_session_t session, void *priv)
56 {
57 int ret;
58 unsigned int status;
59 gnutls_datum_t resp;
60 gnutls_datum_t *exp_resp = priv;
61
62 assert((gnutls_session_get_flags(session) & GNUTLS_SFLAGS_SERV_REQUESTED_OCSP) != 0);
63
64 ret = gnutls_ocsp_status_request_get(session, &resp);
65 if (ret < 0) {
66 if (priv == NULL)
67 return;
68 fail("no response was received\n");
69 }
70
71 if (priv == NULL) {
72 fail("not expected response, but received one\n");
73 }
74
75 if (resp.size != exp_resp->size || memcmp(resp.data, exp_resp->data, resp.size) != 0) {
76 fail("did not receive the expected response\n");
77 }
78
79 /* Check intermediate response */
80 if (gnutls_protocol_get_version(session) == GNUTLS_TLS1_3) {
81 ret = gnutls_ocsp_status_request_get2(session, 1, &resp);
82 if (ret < 0) {
83 fail("no intermediate response was received\n");
84 }
85
86 if (resp.size != ocsp_subca3_unknown.size || memcmp(resp.data, ocsp_subca3_unknown.data, resp.size) != 0) {
87 fail("did not receive the expected intermediate response\n");
88 }
89 }
90
91 ret = gnutls_certificate_verify_peers2(session, &status);
92 if (ret != 0)
93 fail("error in verification (%s)\n", gnutls_strerror(ret));
94
95 ret = gnutls_ocsp_status_request_is_checked(session, GNUTLS_OCSP_SR_IS_AVAIL);
96 if (ret == 0) {
97 fail("did not receive the expected value (%d)\n", ret);
98 }
99
100 ret = gnutls_ocsp_status_request_is_checked(session, 0);
101 if (ret == 0) {
102 fail("did not receive the expected value (%d)\n", ret);
103 }
104 }
105
tls_log_func(int level,const char * str)106 static void tls_log_func(int level, const char *str)
107 {
108 fprintf(stderr, "|<%d>| %s", level, str);
109 }
110
doit(void)111 void doit(void)
112 {
113 int ret;
114 gnutls_certificate_credentials_t xcred;
115 gnutls_certificate_credentials_t clicred;
116 const char *certfile1;
117 const char *ocspfile1;
118 char certname1[TMPNAME_SIZE], ocspname1[TMPNAME_SIZE];
119 FILE *fp;
120 unsigned index1;
121 time_t t;
122
123 global_init();
124 gnutls_global_set_time_function(mytime);
125
126 gnutls_global_set_log_function(tls_log_func);
127 if (debug)
128 gnutls_global_set_log_level(4711);
129
130 assert(gnutls_certificate_allocate_credentials(&xcred) >= 0);
131 assert(gnutls_certificate_allocate_credentials(&clicred) >= 0);
132
133 gnutls_certificate_set_flags(xcred, GNUTLS_CERTIFICATE_API_V2);
134
135 certfile1 = get_tmpname(certname1);
136
137 /* set cert with localhost name */
138 fp = fopen(certfile1, "wb");
139 if (fp == NULL)
140 fail("error in fopen\n");
141 assert(fwrite(server_localhost_ca3_cert_chain_pem, 1, strlen(server_localhost_ca3_cert_chain_pem), fp)>0);
142 assert(fwrite(server_ca3_key_pem, 1, strlen((char*)server_ca3_key_pem), fp)>0);
143 fclose(fp);
144
145 ret = gnutls_certificate_set_x509_key_file2(xcred, certfile1, certfile1,
146 GNUTLS_X509_FMT_PEM, NULL, 0);
147 if (ret < 0)
148 fail("set_x509_key_file failed: %s\n", gnutls_strerror(ret));
149
150 ret = gnutls_certificate_set_x509_key_file2(clicred, certfile1, certfile1,
151 GNUTLS_X509_FMT_PEM, NULL, 0);
152 if (ret < 0)
153 fail("set_x509_key_file failed: %s\n", gnutls_strerror(ret));
154 index1 = ret;
155
156 /* set OCSP response1, include an unrelated OCSP response */
157 ocspfile1 = get_tmpname(ocspname1);
158 fp = fopen(ocspfile1, "wb");
159 if (fp == NULL)
160 fail("error in fopen\n");
161 assert(fwrite(ocsp_subca3_unknown_pem.data, 1, ocsp_subca3_unknown_pem.size, fp)>0);
162 assert(fwrite(ocsp_ca3_localhost_unknown_pem.data, 1, ocsp_ca3_localhost_unknown_pem.size, fp)>0);
163 assert(fwrite(ocsp_ca3_localhost6_unknown_pem.data, 1, ocsp_ca3_localhost6_unknown_pem.size, fp)>0);
164 fclose(fp);
165
166 ret = gnutls_certificate_set_ocsp_status_request_file2(clicred, ocspfile1, index1,
167 GNUTLS_X509_FMT_PEM);
168 if (ret != GNUTLS_E_OCSP_MISMATCH_WITH_CERTS)
169 fail("ocsp file set failed: %s\n", gnutls_strerror(ret));
170
171 /* set OCSP response1, include correct responses */
172 remove(ocspfile1);
173 fp = fopen(ocspfile1, "wb");
174 if (fp == NULL)
175 fail("error in fopen\n");
176 assert(fwrite(ocsp_subca3_unknown_pem.data, 1, ocsp_subca3_unknown_pem.size, fp)>0);
177 assert(fwrite(ocsp_ca3_localhost_unknown_pem.data, 1, ocsp_ca3_localhost_unknown_pem.size, fp)>0);
178 fclose(fp);
179
180 ret = gnutls_certificate_set_ocsp_status_request_file2(clicred, ocspfile1, index1,
181 GNUTLS_X509_FMT_PEM);
182 if (ret < 0)
183 fail("ocsp file set failed: %s\n", gnutls_strerror(ret));
184
185 ret = gnutls_certificate_set_x509_trust_mem(clicred, &ca3_cert, GNUTLS_X509_FMT_PEM);
186 if (ret < 0) {
187 fail("error in setting trust cert: %s\n", gnutls_strerror(ret));
188 }
189
190 t = gnutls_certificate_get_ocsp_expiration(clicred, 0, 0, 0);
191 if (t != 1509625639)
192 fail("error in OCSP validity time: %ld\n", (long int)t);
193
194 t = gnutls_certificate_get_ocsp_expiration(clicred, 0, 1, 0);
195 if (t != 1509625639)
196 fail("error in OCSP validity time: %ld\n", (long int)t);
197
198 t = gnutls_certificate_get_ocsp_expiration(clicred, 0, -1, 0);
199 if (t != 1509625639)
200 fail("error in OCSP validity time: %ld\n", (long int)t);
201
202 #define PRIO "NORMAL:-ECDHE-ECDSA:-VERS-TLS-ALL:+VERS-TLS1.3"
203 _test_cli_serv(xcred, clicred, PRIO, PRIO, "localhost", &ocsp_ca3_localhost_unknown, check_cli,
204 check_serv, 0, 1, 0, 0);
205
206 gnutls_certificate_free_credentials(xcred);
207 gnutls_certificate_free_credentials(clicred);
208 gnutls_global_deinit();
209 remove(ocspfile1);
210 remove(certfile1);
211 }
212
213 #else
doit(void)214 void doit(void)
215 {
216 exit(77);
217 }
218 #endif
219