1 /* vi: set sw=4 ts=4:
2  *
3  * Copyright (C) 2001 - 2014 Christian Hohnstaedt.
4  *
5  * All rights reserved.
6  */
7 
8 
9 #include "ImportMulti.h"
10 #include "XcaWarning.h"
11 #include "MainWindow.h"
12 #include "lib/pki_base.h"
13 #include "lib/pki_pkcs7.h"
14 #include "lib/pki_pkcs12.h"
15 #include "lib/pki_crl.h"
16 #include "lib/pki_multi.h"
17 #include "lib/pki_scard.h"
18 #include "lib/pki_evp.h"
19 #include "lib/pki_temp.h"
20 #include "CrlDetail.h"
21 #include "CertDetail.h"
22 #include "KeyDetail.h"
23 
24 #include <QPushButton>
25 #include <QMessageBox>
26 #include <QLabel>
27 #include <QInputDialog>
28 #include <QUrl>
29 #include <QMimeData>
30 #include <typeinfo>
31 
ImportMulti(QWidget * parent)32 ImportMulti::ImportMulti(QWidget *parent)
33 	: QDialog(parent ?: mainwin)
34 {
35 	setupUi(this);
36 	setWindowTitle(XCA_TITLE);
37 	image->setPixmap(QPixmap(":certImg"));
38 	listView->setEditTriggers(QAbstractItemView::NoEditTriggers);
39 	mcont = new db_token();
40 	listView->setModel(mcont);
41 	listView->setIconSize(QPixmap(":key").size());
42 	listView->setSelectionMode(QAbstractItemView::ExtendedSelection);
43 	connect( listView, SIGNAL(doubleClicked(const QModelIndex &)),
44 		this, SLOT(on_butDetails_clicked()));
45 	deleteToken->hide();
46 	renameToken->hide();
47 	slotInfo->hide();
48 	setAcceptDrops(true);
49 	setWindowModality(Qt::WindowModal);
50 }
51 
tokenInfo(const slotid & s)52 void ImportMulti::tokenInfo(const slotid &s)
53 {
54 	slot = s;
55 	mcont->setSlot(slot);
56 	deleteToken->show();
57 	renameToken->show();
58 	slotInfo->show();
59 	listView->setEditTriggers(QAbstractItemView::EditKeyPressed);
60 
61 	pkcs11 p11;
62 
63 	QString info = p11.driverInfo(slot);
64 	tkInfo ti = p11.tokenInfo(slot);
65 	info += tr("\nName: %1\nModel: %2\nSerial: %3").
66 		arg(ti.label()).arg(ti.model()).arg(ti.serial());
67 
68 	slotInfo->setText(info);
69 	image->setPixmap(QPixmap(":scardImg"));
70 	heading->setText(tr("Manage security token"));
71 	setAcceptDrops(false);
72 }
73 
addItem(pki_base * pki)74 void ImportMulti::addItem(pki_base *pki)
75 {
76 	if (!pki)
77 		return;
78 
79 	if (pki->pkiSource == unknown)
80 		pki->pkiSource = imported;
81 	pki_multi *pm = dynamic_cast<pki_multi*>(pki);
82 	if (pm) {
83 		QList<pki_base*> items = pm->pull();
84 		foreach(pki_base *inner, items)
85 			addItem(inner);
86 		delete pm;
87 		return;
88 	}
89 
90 	pki_x509 *cert = dynamic_cast<pki_x509 *>(pki);
91 	pki_crl *crl = dynamic_cast<pki_crl *>(pki);
92 	pki_x509super *cert_or_req = dynamic_cast<pki_x509super *>(pki);
93 
94 	if (cert)
95 		cert->setSigner(cert->findIssuer());
96 	if (cert_or_req)
97 		cert_or_req->lookupKey();
98 	if (crl)
99 		crl->lookupIssuer();
100 
101 	if (!dynamic_cast<pki_key*>(pki) &&
102 	    !dynamic_cast<pki_x509name*>(pki))
103 	{
104 		XCA_WARN(tr("The type of the item '%1' is not recognized").
105 			arg(pki->getClassName()));
106 		delete pki;
107 		return;
108 	}
109 	mcont->inToCont(pki);
110 	mcont->rename_token_in_database(dynamic_cast<pki_scard*>(pki));
111 }
112 
openDB() const113 bool ImportMulti::openDB() const
114 {
115 	if (!Database.isOpen()) {
116 		if (mainwin->init_database(QString()) == 2)
117 			return false;
118 		if (!Database.isOpen())
119 			mainwin->load_database();
120 	}
121 	return Database.isOpen();
122 }
123 
dragEnterEvent(QDragEnterEvent * event)124 void ImportMulti::dragEnterEvent(QDragEnterEvent *event)
125 {
126 	if (event->mimeData()->hasUrls())
127 		event->acceptProposedAction();
128 }
129 
dropEvent(QDropEvent * event)130 void ImportMulti::dropEvent(QDropEvent *event)
131 {
132 	QList<QUrl> urls = event->mimeData()->urls();
133 	QUrl u;
134 	QStringList failed;
135 	pki_multi *pki = new pki_multi();
136 
137 	foreach(u, urls)
138 		pki->probeAnything(u.toLocalFile());
139 
140 	failed << pki->failed_files;
141 	importError(failed);
142 	addItem(pki);
143 	event->acceptProposedAction();
144 }
145 
on_butRemove_clicked()146 void ImportMulti::on_butRemove_clicked()
147 {
148 	QItemSelectionModel *selectionModel = listView->selectionModel();
149 	QModelIndexList indexes = selectionModel->selectedIndexes();
150 	QModelIndex index;
151 	QString items;
152 
153 	foreach(index, indexes) {
154 		if (index.column() != 0)
155 			continue;
156 		mcont->remFromCont(index);
157 		pki_base *pki = db_base::fromIndex(index);
158 		delete pki;
159 	}
160 	if (mcont->rowCount(QModelIndex()) == 0)
161 		accept();
162 }
163 
on_butOk_clicked()164 void ImportMulti::on_butOk_clicked()
165 {
166 	if (!openDB())
167 		return;
168 
169 	Transaction;
170 	if (!TransBegin())
171 		return;
172 
173 	while (mcont->rowCount(QModelIndex()))
174 		import(mcont->index(0, 0, QModelIndex()));
175 
176 	TransCommit();
177 	accept();
178 }
179 
on_butImport_clicked()180 void ImportMulti::on_butImport_clicked()
181 {
182 	QItemSelectionModel *selectionModel = listView->selectionModel();
183 	QModelIndexList indexes = selectionModel->selectedIndexes();
184 
185 	if (!openDB())
186 		return;
187 
188 	Transaction;
189 	if (!TransBegin())
190 		return;
191 	foreach(QModelIndex index, indexes) {
192 		if (index.column() != 0)
193 			continue;
194 		import(index);
195 	}
196 	TransCommit();
197 	if (mcont->rowCount(QModelIndex()) == 0)
198 		accept();
199 }
200 
on_deleteToken_clicked()201 void ImportMulti::on_deleteToken_clicked()
202 {
203 	QItemSelectionModel *selectionModel = listView->selectionModel();
204 	QModelIndexList indexes = selectionModel->selectedIndexes();
205 	QModelIndex index;
206 	QString items;
207 
208 	foreach(index, indexes) {
209 		if (index.column() != 0)
210 			continue;
211 		pki_base *pki = db_base::fromIndex(index);
212 		try {
213 			pki->deleteFromToken(slot);
214 			mcont->remFromCont(index);
215 			delete pki;
216 		} catch (errorEx &err) {
217 			XCA_ERROR(err);
218 		}
219 	}
220 }
on_renameToken_clicked()221 void ImportMulti::on_renameToken_clicked()
222 {
223 	QItemSelectionModel *selectionModel = listView->selectionModel();
224 	QModelIndexList indexes = selectionModel->selectedIndexes();
225 	QModelIndex index;
226 	QString items;
227 
228         foreach(index, indexes) {
229                 if (index.column() != 0)
230                         continue;
231 		listView->edit(index);
232 		break;
233 	}
234 }
235 
import(const QModelIndex & idx)236 pki_base *ImportMulti::import(const QModelIndex &idx)
237 {
238 	pki_base *pki = mcont->fromIndex(idx);
239 
240 	for (int i = 0; i < mcont->rowCount(idx); i++)
241 		import(mcont->index(i, 0, idx));
242 
243 	if (!pki)
244 		return NULL;
245 
246 	mcont->remFromCont(idx);
247 
248 	if (!Database.isOpen()) {
249 		delete pki;
250 		return NULL;
251 	}
252 	return Database.insert(pki);
253 }
254 
on_butDetails_clicked()255 void ImportMulti::on_butDetails_clicked()
256 {
257 	QItemSelectionModel *selectionModel = listView->selectionModel();
258 	QModelIndex index;
259 
260 	if (!selectionModel->selectedIndexes().count())
261 	        return;
262 
263 	index = selectionModel->selectedIndexes().first();
264 	pki_base *pki = db_base::fromIndex(index);
265 
266 	if (!pki)
267 		return;
268 	try {
269 		pki_x509super *pki_super = dynamic_cast<pki_x509super*>(pki);
270 		if (pki_super) {
271 			CertDetail::showCert(this, pki_super);
272 			return;
273 		}
274 		pki_key *key = dynamic_cast<pki_key*>(pki);
275 		if (key) {
276 			KeyDetail::showKey(this, key);
277 			return;
278 		}
279 		pki_crl *crl = dynamic_cast<pki_crl*>(pki);
280 		if (crl) {
281 			CrlDetail::showCrl(this, crl);
282 			return;
283 		}
284 		pki_temp *temp = dynamic_cast<pki_temp*>(pki);
285 		if (temp) {
286 			XCA_WARN(tr("Details of the item '%1' cannot be shown")
287 				.arg("XCA template"));
288 			return;
289 		}
290 		XCA_WARN(tr("The type of the item '%1' is not recognized").
291 			arg(pki->getClassName()));
292 	}
293 	catch (errorEx &err) {
294 		XCA_ERROR(err);
295 	}
296 }
297 
~ImportMulti()298 ImportMulti::~ImportMulti()
299 {
300 	QModelIndex idx = listView->currentIndex();
301 	while (idx != QModelIndex()) {
302 		mcont->remFromCont(idx);
303 		delete db_base::fromIndex(idx);
304 		idx = listView->currentIndex();
305 	}
306 	listView->setModel(NULL);
307 	delete mcont;
308 }
309 
entries()310 int ImportMulti::entries()
311 {
312 	return mcont->allItemsCount();
313 }
314 
importError(QStringList failed)315 void ImportMulti::importError(QStringList failed)
316 {
317 	if (failed.count() == 1) {
318 		XCA_INFO(tr("The file '%1' did not contain PKI data").
319 			arg(failed[0]));
320 	} else if (failed.count() > 1) {
321 		XCA_INFO(tr("The %1 files: '%2' did not contain PKI data").
322 			arg(failed.count()).
323 			arg(failed.join("', '")));
324 	}
325 }
326 
execute(int force,QStringList failed)327 void ImportMulti::execute(int force, QStringList failed)
328 {
329 	importError(failed);
330 
331 	/* if there is nothing to import don't pop up */
332 	if (entries() == 0) {
333 		accept();
334 		return;
335 	}
336 	/* if there is only 1 item and force is 0 import it silently */
337 	if (entries() == 1 && force == 0 && openDB()) {
338 		QModelIndex idx = mcont->index(0, 0, QModelIndex());
339 		pki_base *pki = import(idx);
340 		if (pki && !Settings["suppress_messages"])
341 			XCA_INFO(pki->getMsg(pki_base::msg_import).
342 				arg(pki->getIntName()));
343 		accept();
344 		return;
345 	}
346 	/* the behaviour for more than one item */
347 	exec();
348 }
349