85648fe22584cd571c84f13a6230b612a45741f7
[cacert.git] / scripts / DumpWeakCerts.pl
1 #!/usr/bin/perl
2 # Script to dump weak RSA certs (Exponent 3 or Modulus size < 1024) according to https://bugs.cacert.org/view.php?id=918
3 # and https://wiki.cacert.org/Arbitrations/a20110312.1
4
5 use strict;
6 use warnings;
7
8 use DBI;
9
10 my $cacert_db_config;
11 my $cacert_db_user;
12 my $cacert_db_password;
13
14 # Read database access data from the config file
15 eval `cat perl_mysql`;
16
17 my $dbh = DBI->connect($cacert_db_config, $cacert_db_user, $cacert_db_password, { RaiseError => 1, AutoCommit => 0 } ) || die "Cannot connect database: $DBI::errstr";
18
19 my $sth_certs;
20 my $sth_userdata;
21
22 my $cert_domid;
23 my $cert_userid;
24 my $cert_orgid;
25 my $cert_CN;
26 my $cert_expire;
27 my $cert_filename;
28 my $cert_serial;
29
30 my $user_email;
31 my $user_firstname;
32
33 my $reason;
34
35 my @row;
36
37 sub IsWeak($) {
38 my ($CertFileName) = @_;
39
40 my $ModulusSize = 0;
41 my $Exponent = 0;
42 my $result = 0;
43
44 # Do key size and exponent checking for RSA keys
45 open(CERTTEXT, '-|', "openssl x509 -in $CertFileName -noout -text") || die "Cannot start openssl";
46 while (<CERTTEXT>) {
47 if (/^ +([^ ]+) Public Key:/) {
48 last if ($1 ne "RSA");
49 }
50 if (/^ +Modulus \((\d+) bit\)/) {
51 $ModulusSize = $1;
52 }
53 if (/^ +Exponent: (\d+)/) {
54 $Exponent = $1;
55 last;
56 }
57 }
58 close(CERTTEXT);
59 if ($ModulusSize > 0 && $Exponent > 0) {
60 if ($ModulusSize < 1024 || $Exponent==3) {
61 $result = "SmallKey";
62 }
63 }
64
65 if (!$result) {
66 # Check with openssl-vulnkey
67 # This is currently not tested, if you don't know what you are doing leave it commented!
68 if (system("openssl-vulnkey -q $CertFileName") != 0) {
69 $result = "openssl-vulnkey";
70 }
71 }
72
73 return $result;
74 }
75
76 # Select only certificates expiring in more than two weeks, since two weeks will probably be needed as turnaround time
77 # Get all domain certificates
78 $sth_certs = $dbh->prepare(
79 "SELECT `dc`.`domid`, `dc`.`CN`, `dc`.`expire`, `dc`.`crt_name`, `dc`.`serial` ".
80 " FROM `domaincerts` AS `dc` ".
81 " WHERE `dc`.`revoked`=0 AND `dc`.`expire` > DATE_ADD(NOW(), INTERVAL 14 DAY)");
82 $sth_certs->execute();
83
84 $sth_userdata = $dbh->prepare(
85 "SELECT `u`.`email`, `u`.`fname` ".
86 " FROM `domains` AS `d`, `users` AS `u` ".
87 " WHERE `d`.`memid`=`u`.`id` AND `d`.`id`=?");
88
89 while(($cert_domid, $cert_CN, $cert_expire, $cert_filename, $cert_serial) = $sth_certs->fetchrow_array) {
90 if (-f $cert_filename) {
91 $reason = IsWeak($cert_filename);
92 if ($reason) {
93 $sth_userdata->execute($cert_domid);
94 ($user_email, $user_firstname) = $sth_userdata->fetchrow_array();
95 print join("\t", ('DomainCert', $user_email, $user_firstname, $cert_expire, $cert_CN, $reason, $cert_serial)). "\n";
96 $sth_userdata->finish();
97 }
98 }
99 }
100 $sth_certs->finish();
101
102 # Get all email certificates
103 $sth_certs = $dbh->prepare(
104 "SELECT `ec`.`memid`, `ec`.`CN`, `ec`.`expire`, `ec`.`crt_name`, `ec`.`serial` ".
105 " FROM `emailcerts` AS `ec` ".
106 " WHERE `ec`.`revoked`=0 AND `ec`.`expire` > DATE_ADD(NOW(), INTERVAL 14 DAY)");
107 $sth_certs->execute();
108
109 $sth_userdata = $dbh->prepare(
110 "SELECT `u`.`email`, `u`.`fname` ".
111 " FROM `users` AS `u` ".
112 " WHERE `u`.`id`=?");
113
114 while(($cert_userid, $cert_CN, $cert_expire, $cert_filename, $cert_serial) = $sth_certs->fetchrow_array) {
115 if (-f $cert_filename) {
116 $reason = IsWeak($cert_filename);
117 if ($reason) {
118 $sth_userdata->execute($cert_userid);
119 ($user_email, $user_firstname) = $sth_userdata->fetchrow_array();
120 print join("\t", ('EmailCert', $user_email, $user_firstname, $cert_expire, $cert_CN, $reason, $cert_serial)). "\n";
121 $sth_userdata->finish();
122 }
123 }
124 }
125 $sth_certs->finish();
126
127 # Get all Org Server certificates, notify all admins of the Org!
128 $sth_certs = $dbh->prepare(
129 "SELECT `dc`.`orgid`, `dc`.`CN`, `dc`.`expire`, `dc`.`crt_name`, `dc`.`serial` ".
130 " FROM `orgdomaincerts` AS `dc` ".
131 " WHERE `dc`.`revoked`=0 AND `dc`.`expire` > DATE_ADD(NOW(), INTERVAL 14 DAY)");
132 $sth_certs->execute();
133
134 $sth_userdata = $dbh->prepare(
135 "SELECT `u`.`email`, `u`.`fname` ".
136 " FROM `users` AS `u`, `org` ".
137 " WHERE `u`.`id`=`org`.`memid` and `org`.`orgid`=?");
138
139 while(($cert_orgid, $cert_CN, $cert_expire, $cert_filename, $cert_serial) = $sth_certs->fetchrow_array) {
140 if (-f $cert_filename) {
141 $reason = IsWeak($cert_filename);
142 if ($reason) {
143 $sth_userdata->execute($cert_orgid);
144 while(($user_email, $user_firstname) = $sth_userdata->fetchrow_array()) {
145 print join("\t", ('OrgServerCert', $user_email, $user_firstname, $cert_expire, $cert_CN, $reason, $cert_serial)). "\n";
146 }
147 $sth_userdata->finish();
148 }
149 }
150 }
151 $sth_certs->finish();
152
153 # Get all Org Email certificates, notify all admins of the Org!
154 $sth_certs = $dbh->prepare(
155 "SELECT `ec`.`orgid`, `ec`.`CN`, `ec`.`expire`, `ec`.`crt_name`, `ec`.`serial` ".
156 " FROM `orgemailcerts` AS `ec` ".
157 " WHERE `ec`.`revoked`=0 AND `ec`.`expire` > DATE_ADD(NOW(), INTERVAL 14 DAY)");
158 $sth_certs->execute();
159
160 $sth_userdata = $dbh->prepare(
161 "SELECT `u`.`email`, `u`.`fname` ".
162 " FROM `users` AS `u`, `org` ".
163 " WHERE `u`.`id`=`org`.`memid` and `org`.`orgid`=?");
164
165 while(($cert_orgid, $cert_CN, $cert_expire, $cert_filename, $cert_serial) = $sth_certs->fetchrow_array) {
166 if (-f $cert_filename) {
167 $reason = IsWeak($cert_filename);
168 if ($reason) {
169 $sth_userdata->execute($cert_orgid);
170 while(($user_email, $user_firstname) = $sth_userdata->fetchrow_array()) {
171 print join("\t", ('OrgEmailCert', $user_email, $user_firstname, $cert_expire, $cert_CN, $reason, $cert_serial)). "\n";
172 }
173 $sth_userdata->finish();
174 }
175 }
176 }
177 $sth_certs->finish();
178
179 $dbh->disconnect();