1 # Check the status of a SSL cert on a remote server
8 local ($host, $port, $page, $ssl);
11 # Parse the URL and connect
12 ($host, $port, $page, $ssl) = &parse_http_url($_[0]->{'url'});
14 # Run the openssl command to connect
15 local $cmd = "openssl s_client -host ".quotemeta($host).
16 " -port ".quotemeta($port)." </dev/null 2>&1";
17 local $out = &backquote_with_timeout($cmd, 10);
20 return { 'up' => -1 };
23 # Extract the cert part and save
24 $certfile = &transname();
25 if ($out =~ /(-----BEGIN CERTIFICATE-----\n(.*\n)+-----END CERTIFICATE-----\n)/) {
27 &open_tempfile(CERT, ">$certfile", 0, 1);
28 &print_tempfile(CERT, $cert);
29 &close_tempfile(CERT);
34 'desc' => $text{'sslcert_ecert'} };
38 # Cert is already in a file
39 $certfile = $_[0]->{'file'};
42 # Get end date with openssl x509 -in cert.pem -inform PEM -text -noout -enddate
43 local $info = &backquote_command("openssl x509 -in ".quotemeta($certfile).
44 " -inform PEM -text -noout -enddate ".
48 &foreign_require("mailboxes");
50 if ($info =~ /Not\s*Before\s*:\s*(.*)/i) {
51 $start = &mailboxes::parse_mail_date("$1");
53 if ($info =~ /Not\s+After\s*:\s*(.*)/i) {
54 $end = &mailboxes::parse_mail_date("$1");
57 if ($start && $now < $start) {
59 $desc = &text('sslcert_estart', &make_date($start));
61 elsif ($end && $now > $end-$_[0]->{'days'}*24*60*60) {
63 $desc = &text('sslcert_eend', &make_date($end));
65 elsif ($_[0]->{'mismatch'} && $_[0]->{'url'} &&
66 $info =~ /Subject:.*CN=([a-z0-9\.\-\_\*]+)/i) {
70 $match =~ s/\*/\.\*/g; # Make perl RE
71 local @matches = ( $match );
72 if ($info =~ /Subject\s+Alternative\s+Name.*\r?\n\s*(.*)\n/) {
73 # Add UCC alternate names
77 foreach my $a (split(/[, ]+/, $alts)) {
78 if ($a =~ /^DNS:(\S+)/) {
80 $match =~ s/\*/\.\*/g; # Make perl RE
81 push(@matches, $match);
86 foreach $match (@matches) {
87 $ok++ if ($host =~ /^$match$/i);
90 $desc = &text('sslcert_ematch', "<tt>$host</tt>",
97 $desc = &text('sslcert_left', int(($end-$now)/(24*60*60)));
101 return { 'up' => $up, 'desc' => $desc };
104 sub show_sslcert_dialog
106 # URL or file to check
107 print &ui_table_row($text{'sslcert_src'},
108 &ui_radio_table("src", $_[0]->{'file'} ? 1 : 0,
109 [ [ 0, $text{'sslcert_url'},
110 &ui_textbox("url", $_[0]->{'url'}, 50) ],
111 [ 1, $text{'sslcert_file'},
112 &ui_textbox("file", $_[0]->{'file'}, 50)." ".
113 &file_chooser_button("file") ] ]), 3);
115 # Days before expiry to warn
116 print &ui_table_row($text{'sslcert_days'},
117 &ui_opt_textbox("days", $_[0]->{'days'}, 5, $text{'sslcert_when'}));
119 # Warn about mismatch
120 print &ui_table_row($text{'sslcert_mismatch'},
121 &ui_yesno_radio("mismatch", $_[0]->{'mismatch'}));
124 sub parse_sslcert_dialog
126 &has_command("openssl") || &error($text{'sslcert_eopenssl'});
128 if ($in{'src'} == 0) {
130 $in{'url'} =~ /^https:\/\/(\S+)$/ || &error($text{'sslcert_eurl'});
131 $_[0]->{'url'} = $in{'url'};
132 delete($_[0]->{'file'});
136 $in{'file'} =~ /^\// && -r $in{'file'} ||
137 &error($text{'sslcert_efile'});
138 $_[0]->{'file'} = $in{'file'};
139 delete($_[0]->{'url'});
142 # Parse number of days
143 if ($in{'days_def'}) {
144 delete($_[0]->{'days'});
147 $in{'days'} =~ /^[1-9]\d*$/ || &error($text{'sslcert_edays'});
148 $_[0]->{'days'} = $in{'days'};
152 $_[0]->{'mismatch'} = $in{'mismatch'};
153 if ($in{'mismatch'} && $in{'src'}) {
154 &error($text{'sslcert_emismatch'});