1#! /usr/bin/env perl
2# Copyright 2021-2022 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 POSIX;
13use OpenSSL::Test qw/:DEFAULT data_file/;
14use File::Copy;
15
16setup('test_ca_internals');
17
18my @updatedb_tests = (
19    {
20        description => 'updatedb called before the first certificate expires',
21        filename => 'index.txt',
22        copydb => 1,
23        testdate => '990101000000Z',
24        need64bit => 0,
25        expirelist => [ ]
26    },
27    {
28        description => 'updatedb called before Y2k',
29        filename => 'index.txt',
30        copydb => 0,
31        testdate => '991201000000Z',
32        need64bit => 0,
33        expirelist => [ '1000' ]
34    },
35    {
36        description => 'updatedb called after year 2020',
37        filename => 'index.txt',
38        copydb => 0,
39        testdate => '211201000000Z',
40        need64bit => 0,
41        expirelist => [ '1001' ]
42    },
43    {
44        description => 'updatedb called in year 2049 (last year with 2 digits)',
45        filename => 'index.txt',
46        copydb => 0,
47        testdate => '491201000000Z',
48        need64bit => 1,
49        expirelist => [ '1002' ]
50    },
51    {
52        description => 'updatedb called in year 2050 (first year with 4 digits) before the last certificate expires',
53        filename => 'index.txt',
54        copydb => 0,
55        testdate => '20500101000000Z',
56        need64bit => 1,
57        expirelist => [ ]
58    },
59    {
60        description => 'updatedb called after the last certificate expired',
61        filename => 'index.txt',
62        copydb => 0,
63        testdate => '20501201000000Z',
64        need64bit => 1,
65        expirelist => [ '1003' ]
66    },
67    {
68        description => 'updatedb called for the first time after the last certificate expired',
69        filename => 'index.txt',
70        copydb => 1,
71        testdate => '20501201000000Z',
72        need64bit => 1,
73        expirelist => [ '1000',
74                        '1001',
75                        '1002',
76                        '1003' ]
77    }
78);
79
80my @unsupported_commands = (
81    {
82        command => 'unsupported'
83    }
84);
85
86# every "test_updatedb" makes 3 checks
87plan tests => 3 * scalar(@updatedb_tests) +
88              1 * scalar(@unsupported_commands);
89
90
91foreach my $test (@updatedb_tests) {
92    test_updatedb($test);
93}
94foreach my $test (@unsupported_commands) {
95    test_unsupported_commands($test);
96}
97
98
99################### subs to do tests per supported command ################
100
101sub test_unsupported_commands {
102    my ($opts) = @_;
103
104    run(
105        test(['ca_internals_test',
106                $opts->{command}
107        ]),
108        capture => 0,
109        statusvar => \my $exit
110    );
111
112    is($exit, 0, "command '".$opts->{command}."' completed without an error");
113}
114
115sub test_updatedb {
116    my ($opts) = @_;
117    my $amtexpectedexpired = scalar(@{$opts->{expirelist}});
118    my @output;
119    my $expirelistcorrect = 1;
120    my $cert;
121    my $amtexpired = 0;
122    my $skipped = 0;
123
124    if ($opts->{copydb}) {
125        copy(data_file('index.txt'), 'index.txt');
126    }
127
128    @output = run(
129        test(['ca_internals_test',
130            "do_updatedb",
131            $opts->{filename},
132            $opts->{testdate},
133            $opts->{need64bit}
134        ]),
135        capture => 1,
136        statusvar => \my $exit
137    );
138
139    foreach my $tmp (@output) {
140        ($cert) = $tmp =~ /^[\x20\x23]*[^0-9A-Fa-f]*([0-9A-Fa-f]+)=Expired/;
141        if ($tmp =~ /^[\x20\x23]*skipping test/) {
142            $skipped = 1;
143        }
144        if (defined($cert) && (length($cert) > 0)) {
145            $amtexpired++;
146            my $expirefound = 0;
147            foreach my $expire (@{$opts->{expirelist}}) {
148                if ($expire eq $cert) {
149                    $expirefound = 1;
150                }
151            }
152            if ($expirefound != 1) {
153                $expirelistcorrect = 0;
154            }
155        }
156    }
157
158    if ($skipped) {
159        $amtexpired = $amtexpectedexpired;
160        $expirelistcorrect = 1;
161    }
162    is($exit, 1, "ca_internals_test: returned EXIT_FAILURE (".$opts->{description}.")");
163    is($amtexpired, $amtexpectedexpired, "ca_internals_test: amount of expired certificates differs from expected amount (".$opts->{description}.")");
164    is($expirelistcorrect, 1, "ca_internals_test: list of expired certificates differs from expected list (".$opts->{description}.")");
165}
166