1#! /usr/bin/env perl 2# Copyright 2023-2024 The OpenSSL Project Authors. All Rights Reserved. 3# 4# Licensed under the Apache License 2.0 (the "License"). You may not use 5# this file except in compliance with the License. You can obtain a copy 6# in the file LICENSE in the source distribution or at 7# https://www.openssl.org/source/license.html 8 9use strict; 10use warnings; 11 12use IPC::Open3; 13use OpenSSL::Test qw/:DEFAULT srctop_file bldtop_file/; 14use OpenSSL::Test::Utils; 15use Symbol 'gensym'; 16 17my $test_name = "test_ocsp_cert_chain"; 18setup($test_name); 19 20plan skip_all => "$test_name requires OCSP support" 21 if disabled("ocsp"); 22plan skip_all => "$test_name requires EC cryptography" 23 if disabled("ec"); 24plan skip_all => "$test_name requires sock enabled" 25 if disabled("sock"); 26plan skip_all => "$test_name requires TLS enabled" 27 if alldisabled(available_protocols("tls")); 28plan skip_all => "$test_name is not available Windows or VMS" 29 if $^O =~ /^(VMS|MSWin32|msys)$/; 30 31plan tests => 3; 32 33my $shlib_wrap = bldtop_file("util", "shlib_wrap.sh"); 34my $apps_openssl = bldtop_file("apps", "openssl"); 35 36my $index_txt = srctop_file("test", "ocsp-tests", "index.txt"); 37my $ocsp_pem = srctop_file("test", "ocsp-tests", "ocsp.pem"); 38my $intermediate_cert_pem = srctop_file("test", "ocsp-tests", "intermediate-cert.pem"); 39 40my $server_pem = srctop_file("test", "ocsp-tests", "server.pem"); 41 42sub run_test { 43 44 # this test starts two servers that listen on respective ports. 45 # that can be problematic since the ports may not be available 46 # (e.g. when multiple instances of the test are run on the same 47 # machine). 48 49 # to avoid this, we specify port 0 when staring each server, which 50 # causes the OS to provide a random unused port. 51 52 # using a random port with s_server is straightforward. doing so 53 # with the ocsp responder required some investigation because the 54 # url for the ocsp responder is usually included in the server's 55 # cert (normally, in the authority-information-access extension, 56 # and it would be complicated to change that when the test 57 # executes). however, s_server has an option "-status_url" that 58 # can be used to specify a fallback url when no url is specified 59 # in the cert. that is what we do here. 60 61 # openssl ocsp -port 0 -index index.txt -rsigner ocsp.pem -CA intermediate-cert.pem 62 my @ocsp_cmd = ("ocsp", "-port", "0", "-index", $index_txt, "-rsigner", $ocsp_pem, "-CA", $intermediate_cert_pem); 63 my $ocsp_pid = open3(my $ocsp_i, my $ocsp_o, my $ocsp_e = gensym, $shlib_wrap, $apps_openssl, @ocsp_cmd); 64 65 ## ipv4 66 # ACCEPT 0.0.0.0:19254 PID=620007 67 ## ipv6 68 # ACCEPT [::]:19254 PID=620007 69 my $port = "0"; 70 while (<$ocsp_o>) { 71 print($_); 72 chomp; 73 if (/^ACCEPT 0.0.0.0:(\d+)/) { 74 $port = $1; 75 last; 76 } elsif (/^ACCEPT \[::\]:(\d+)/) { 77 $port = $1; 78 last; 79 } else { 80 last; 81 } 82 } 83 ok($port ne "0", "ocsp server port check"); 84 my $ocsp_port = $port; 85 86 print("ocsp server ready, listening on port $ocsp_port\n"); 87 88 # openssl s_server -accept 0 -naccept 1 \ 89 # -cert server.pem -cert_chain intermediate-cert.pem \ 90 # -status_verbose -status_url http://localhost:19254/ocsp 91 my @s_server_cmd = ("s_server", "-accept", "0", "-naccept", "1", 92 "-cert", $server_pem, "-cert_chain", $intermediate_cert_pem, 93 "-status_verbose", "-status_url", "http://localhost:${ocsp_port}/ocsp"); 94 my $s_server_pid = open3(my $s_server_i, my $s_server_o, my $s_server_e = gensym, $shlib_wrap, $apps_openssl, @s_server_cmd); 95 96 # ACCEPT 0.0.0.0:45921 97 # ACCEPT [::]:45921 98 $port = "0"; 99 while (<$s_server_o>) { 100 print($_); 101 chomp; 102 if (/^ACCEPT 0.0.0.0:(\d+)/) { 103 $port = $1; 104 last; 105 } elsif (/^ACCEPT \[::\]:(\d+)/) { 106 $port = $1; 107 last; 108 } elsif (/^Using default/) { 109 ; 110 } else { 111 last; 112 } 113 } 114 ok($port ne "0", "s_server port check"); 115 my $server_port = $port; 116 117 print("s_server ready, listening on port $server_port\n"); 118 119 # openssl s_client -connect localhost:45921 -status -verify_return_error 120 my @s_client_cmd = ("s_client", "-connect", "localhost:$server_port", "-status", "-verify_return_error"); 121 my $s_client_pid = open3(my $s_client_i, my $s_client_o, my $s_client_e = gensym, $shlib_wrap, $apps_openssl, @s_client_cmd); 122 123 waitpid($s_client_pid, 0); 124 kill 'HUP', $s_server_pid, $ocsp_pid; 125 126 ### the output from s_server that we want to check is written to its stderr 127 ### cert_status: ocsp response sent: 128 129 my $resp = 0; 130 while (<$s_server_e>) { 131 print($_); 132 chomp; 133 if (/^cert_status: ocsp response sent:/) { 134 $resp = 1; 135 last; 136 } 137 } 138 ok($resp == 1, "check s_server sent ocsp response"); 139} 140 141run_test(); 142