xref: /openbsd-src/regress/lib/libcrypto/ocsp/ocsp_test.c (revision d75fd186365b74ea6d1283cd78511289ef0e9739)
1 /*	$OpenBSD: ocsp_test.c,v 1.7 2023/07/07 19:54:36 bcook Exp $	*/
2 /*
3  * Copyright (c) 2016 Bob Beck <beck@openbsd.org>
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 #include <stdio.h>
19 #include <netdb.h>
20 #include <stdlib.h>
21 #include <unistd.h>
22 #include <err.h>
23 #include <sys/socket.h>
24 
25 #include <openssl/ssl.h>
26 #include <openssl/ocsp.h>
27 
28 static int
tcp_connect(char * host,char * port)29 tcp_connect(char *host, char *port)
30 {
31 	int error, sd = -1;
32 	struct addrinfo hints, *res, *r;
33 
34 	memset(&hints, 0, sizeof(struct addrinfo));
35 	hints.ai_family = AF_INET;
36 	hints.ai_socktype = SOCK_STREAM;
37 
38 	if (BIO_sock_init() != 1) {
39 		perror("BIO_sock_init()");
40 		exit(-1);
41 	}
42 
43 	error = getaddrinfo(host, port, &hints, &res);
44 	if (error != 0) {
45 		perror("getaddrinfo()");
46 		exit(-1);
47 	}
48 
49 	for (r = res; r != NULL; r = r->ai_next) {
50 		sd = socket(r->ai_family, r->ai_socktype, r->ai_protocol);
51 		if (sd == -1)
52 			continue;
53 
54 		if (connect(sd, r->ai_addr, r->ai_addrlen) == 0)
55 			break;
56 
57 		close(sd);
58 	}
59 
60 	freeaddrinfo(res);
61 
62 	return sd;
63 }
64 
65 int
main(int argc,char * argv[])66 main(int argc, char *argv[])
67 {
68 	int sd, ocsp_status;
69 	const unsigned char *p;
70 	long len;
71 	OCSP_RESPONSE *rsp = NULL;
72 	OCSP_BASICRESP *br = NULL;
73 	X509_STORE     *st = NULL;
74 	STACK_OF(X509) *ch = NULL;
75 	char *host, *port;
76 #ifdef _PATH_SSL_CA_FILE
77 	char *cafile = _PATH_SSL_CA_FILE;
78 #else
79 	char *cafile = "/etc/ssl/cert.pem";
80 #endif
81 
82 	SSL *ssl;
83 	SSL_CTX *ctx;
84 
85 	SSL_library_init();
86 	SSL_load_error_strings();
87 
88 	ctx = SSL_CTX_new(SSLv23_client_method());
89 
90 	if (!SSL_CTX_load_verify_locations(ctx, cafile, NULL)) {
91 		printf("failed to load %s\n", cafile);
92 		exit(-1);
93 	}
94 
95 	if (argc != 3)
96 		errx(-1, "need a host and port to connect to");
97 	else {
98 		host = argv[1];
99 		port = argv[2];
100 	}
101 
102 	sd = tcp_connect(host, port);
103 
104 	ssl = SSL_new(ctx);
105 
106 	SSL_set_fd(ssl, (int) sd);
107 	SSL_set_tlsext_status_type(ssl, TLSEXT_STATUSTYPE_ocsp);
108 
109 	if (SSL_connect(ssl) <= 0) {
110 		printf("SSL connect error\n");
111 		exit(-1);
112 	}
113 
114 	if (SSL_get_verify_result(ssl) != X509_V_OK) {
115 		printf("Certificate doesn't verify from host %s port %s\n", host, port);
116 		exit(-1);
117 	}
118 
119 	/* ==== VERIFY OCSP RESPONSE ==== */
120 
121 
122 	len = SSL_get_tlsext_status_ocsp_resp(ssl, &p);
123 
124 	if (!p) {
125 		printf("No OCSP response received for %s port %s\n", host, port);
126 		exit(-1);
127 	}
128 
129 	rsp = d2i_OCSP_RESPONSE(NULL, &p, len);
130 	if (!rsp) {
131 		puts("Invalid OCSP response");
132 		exit(-1);
133 	}
134 
135 	ocsp_status = OCSP_response_status(rsp);
136 	if (ocsp_status != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
137 		printf("Invalid OCSP response status: %s (%d)",
138 		       OCSP_response_status_str(ocsp_status), ocsp_status);
139 		exit(-1);
140 	}
141 
142 	br = OCSP_response_get1_basic(rsp);
143 	if (!br) {
144 		puts("Invalid OCSP response");
145 		exit(-1);
146 	}
147 
148 	ch = SSL_get_peer_cert_chain(ssl);
149 	st = SSL_CTX_get_cert_store(ctx);
150 
151 	if (OCSP_basic_verify(br, ch, st, 0) <= 0) {
152 		puts("OCSP response verification failed");
153 		exit(-1);
154 	}
155 
156 	printf("OCSP validated from %s %s\n", host, port);
157 
158 	return 0;
159 }
160