1 /* vi: set sw=4 ts=4:
2 *
3 * Copyright (C) 2015 Christian Hohnstaedt.
4 *
5 * All rights reserved.
6 */
7
8 #include "RevocationList.h"
9 #include "MainWindow.h"
10 #include "NewCrl.h"
11 #include "Help.h"
12 #include "lib/asn1int.h"
13 #include "lib/pki_x509.h"
14
15 enum revCol { Cnumber, Cserial, Cdate, Creason, CiDate, Cmax };
16
17 class revListItem : public QTreeWidgetItem
18 {
19 public:
revListItem(QTreeWidget * w)20 revListItem(QTreeWidget *w) : QTreeWidgetItem(w) { };
operator <(const QTreeWidgetItem & other) const21 bool operator < (const QTreeWidgetItem &other) const
22 {
23 int col = treeWidget()->sortColumn();
24 switch (col) {
25 case Cserial: {
26 return a1int(text(Cserial)) <
27 a1int(other.text(Cserial));
28 }
29 case Cnumber:
30 return text(Cnumber).toLong() <
31 other.text(Cnumber).toLong();
32 default:
33 return QTreeWidgetItem::operator < (other);
34 }
35 }
36 };
37
setup_revRevItem(QTreeWidgetItem * item,const x509rev & revit,const pki_x509 * iss)38 static void setup_revRevItem(QTreeWidgetItem *item, const x509rev &revit,
39 const pki_x509 *iss)
40 {
41 pki_x509 *rev = iss ? iss->getBySerial(revit.getSerial()) : NULL;
42 if (rev != NULL) {
43 for (int i = 0; i < Cmax; i++)
44 item->setToolTip(i, rev->getIntName());
45 }
46 item->setText(Cserial, revit.getSerial());
47 item->setText(Cdate, revit.getDate().toSortable());
48 item->setText(Creason, revit.getReason());
49
50 item->setTextAlignment(Cnumber, Qt::AlignRight);
51 item->setTextAlignment(Cserial, Qt::AlignRight);
52
53 a1time a = revit.getInvalDate();
54 if (!a.isUndefined())
55 item->setText(CiDate, a.toSortable());
56 }
57
addRevItem(QTreeWidget * certList,const x509rev & revit,int no,const pki_x509 * iss)58 static void addRevItem(QTreeWidget *certList, const x509rev &revit,
59 int no, const pki_x509 *iss)
60 {
61 revListItem *current;
62 current = new revListItem(certList);
63 current->setText(Cnumber, QString("%1").arg(no));
64 setup_revRevItem(current, revit, iss);
65 }
66
setupRevocationView(QTreeWidget * certList,const x509revList & revList,const pki_x509 * iss)67 void RevocationList::setupRevocationView(QTreeWidget *certList,
68 const x509revList &revList, const pki_x509 *iss)
69 {
70 QStringList sl;
71 int cols, i;
72
73 certList->clear();
74
75 sl << tr("No.") << tr("Serial") << tr("Revocation") << tr("Reason") <<
76 tr("Invalidation");
77
78 cols = sl.size();
79 certList->setColumnCount(cols);
80 certList->setHeaderLabels(sl);
81 certList->setItemsExpandable(false);
82 certList->setRootIsDecorated(false);
83 certList->sortItems(Cnumber, Qt::AscendingOrder);
84
85 i=1;
86 foreach(x509rev revit, revList) {
87 addRevItem(certList, revit, i++, iss);
88 }
89 for (i=0; i<cols; i++)
90 certList->resizeColumnToContents(i);
91 certList->setSortingEnabled(true);
92 certList->setSelectionBehavior(QAbstractItemView::SelectRows);
93 certList->setSelectionMode(QAbstractItemView::ExtendedSelection);
94 }
95
RevocationList(QWidget * w)96 RevocationList::RevocationList(QWidget *w) : QDialog(w ?: mainwin)
97 {
98 QPushButton *genCrl;
99 setupUi(this);
100 setWindowTitle(XCA_TITLE);
101 image->setPixmap(QPixmap(":revImg"));
102 mainwin->helpdlg->register_ctxhelp_button(this, "crlmanage");
103
104 genCrl = buttonBox->addButton(tr("Generate CRL"),
105 QDialogButtonBox::ActionRole);
106
107 connect(genCrl, SIGNAL(clicked()), this, SLOT(gencrl()));
108 }
109
gencrl()110 void RevocationList::gencrl()
111 {
112 issuer->setRevocations(getRevList());
113 NewCrl::newCrl(this, issuer);
114 }
115
setRevList(const x509revList & rl,pki_x509 * iss)116 void RevocationList::setRevList(const x509revList &rl, pki_x509 *iss)
117 {
118 issuer = iss;
119 revList = rl;
120 setupRevocationView(certList, revList, issuer);
121 }
122
getRevList()123 const x509revList &RevocationList::getRevList()
124 {
125 return revList;
126 }
127
on_addRev_clicked()128 void RevocationList::on_addRev_clicked()
129 {
130 Revocation *revoke = new Revocation(QModelIndexList(), this);
131 if (revoke->exec()) {
132 x509rev revit = revoke->getRevocation();
133 revList << revit;
134 addRevItem(certList, revit, revList.size(), issuer);
135 }
136 }
137
on_delRev_clicked()138 void RevocationList::on_delRev_clicked()
139 {
140 QTreeWidgetItem *current = certList->currentItem();
141 x509rev rev;
142 int idx;
143
144 if (!current)
145 return;
146 idx = certList->indexOfTopLevelItem(current);
147 certList->takeTopLevelItem(idx);
148 rev.setSerial(a1int(current->text(Cserial)));
149 idx = revList.indexOf(rev);
150 if (idx != -1)
151 revList.takeAt(idx);
152 }
153
on_editRev_clicked()154 void RevocationList::on_editRev_clicked()
155 {
156 on_certList_itemDoubleClicked(certList->currentItem());
157 }
158
on_certList_itemDoubleClicked(QTreeWidgetItem * current)159 void RevocationList::on_certList_itemDoubleClicked(QTreeWidgetItem *current)
160 {
161 x509rev rev;
162 int idx;
163
164 if (!current)
165 return;
166
167 rev.setSerial(a1int(current->text(Cserial)));
168 idx = revList.indexOf(rev);
169 if (idx == -1)
170 return;
171
172 rev = revList[idx];
173
174 Revocation *revoke = new Revocation(QModelIndexList(), this);
175 revoke->setRevocation(rev);
176 if (revoke->exec()) {
177 a1time a1 = rev.getDate();
178 rev = revoke->getRevocation();
179 rev.setDate(a1);
180 revList[idx] = rev;
181 setup_revRevItem(current, rev, issuer);
182 }
183 delete revoke;
184 }
185
Revocation(QModelIndexList indexes,QWidget * w)186 Revocation::Revocation(QModelIndexList indexes, QWidget *w) : QDialog(w ?: mainwin)
187 {
188 setupUi(this);
189 setWindowTitle(XCA_TITLE);
190 mainwin->helpdlg->register_ctxhelp_button(this, "crlrevocation");
191
192 reason->addItems(x509rev::crlreasons());
193 invalid->setNow();
194
195 if (indexes.size() > 1) {
196 QList<a1int> serials;
197 QStringList sl;
198 serial->setText(QString("Batch revocation of %1 Certificates").
199 arg(indexes.size()));
200 foreach(QModelIndex idx, indexes) {
201 pki_x509 *cert = db_base::fromIndex<pki_x509>(idx);
202 if (cert)
203 serials << cert->getSerial();
204 }
205 std::sort(serials.begin(), serials.end());
206 foreach(a1int a, serials)
207 sl << a;
208 serial->setToolTip(sl.join("\n"));
209 serial->setEnabled(false);
210 } else if (indexes.size() == 1) {
211 pki_x509 *cert = db_base::fromIndex<pki_x509>(indexes[0]);
212 serial->setText(cert->getSerial());
213 serial->setEnabled(false);
214 } else {
215 serial->setValidator(
216 new QRegExpValidator(QRegExp("[A-Fa-f0-9]+"), serial));
217 }
218 }
219
getRevocation()220 x509rev Revocation::getRevocation()
221 {
222 x509rev r;
223
224 r.setSerial(a1int(serial->text()));
225 r.setInvalDate(invalid->getDate());
226 r.setDate(a1time());
227 r.setCrlNo(0);
228 r.setReason(reason->currentText());
229 return r;
230 }
231
setRevocation(x509rev r)232 void Revocation::setRevocation(x509rev r)
233 {
234 serial->setText(r.getSerial());
235 invalid->setDate(r.getInvalDate());
236 int i = reason->findText(r.getReason());
237 if (i == -1)
238 i = 0;
239 reason->setCurrentIndex(i);
240 }
241