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