1 /* vi: set sw=4 ts=4:
2  *
3  * Copyright (C) 2001 - 2020 Christian Hohnstaedt.
4  *
5  * All rights reserved.
6  */
7 
8 
9 #include "NewX509.h"
10 #include <QCheckBox>
11 #include <QComboBox>
12 #include <QRadioButton>
13 #include <QLineEdit>
14 #include <QListWidget>
15 #include <QMessageBox>
16 
17 #include "MainWindow.h"
18 #include "lib/x509v3ext.h"
19 #include "lib/BioByteArray.h"
20 #include "lib/func.h"
21 
22 #include "lib/openssl_compat.h"
23 
getBasicConstraints()24 x509v3ext NewX509::getBasicConstraints()
25 {
26 	QStringList cont;
27 	x509v3ext ext;
28 	QString ca[] = { "", "CA:TRUE", "CA:FALSE" };
29 	if (basicCA->currentIndex() > 0) {
30 		if (bcCritical->isChecked())
31 			cont << "critical";
32 		cont << ca[basicCA->currentIndex()];
33 		if (basicCA->currentIndex() == 1 &&
34 		   !basicPath->text().isEmpty())
35 		{
36 			cont << QString("pathlen:") +
37 				QString::number(basicPath->text().toInt());
38 		}
39 		ext.create(NID_basic_constraints, cont.join(", "), &ext_ctx);
40 	}
41 	return ext;
42 }
43 
getSubKeyIdent()44 x509v3ext NewX509::getSubKeyIdent()
45 {
46 	x509v3ext ext;
47 	if (subKey->isChecked())
48 		ext.create(NID_subject_key_identifier, "hash", &ext_ctx);
49 	return ext;
50 }
51 
52 
getOCSPstaple()53 x509v3ext NewX509::getOCSPstaple()
54 {
55 	x509v3ext ext;
56 	if (OCSPstaple->isChecked())
57 		ext.create(NID_tlsfeature,
58 #ifdef NID_tlsfeature
59 			"status_request",
60 #else
61 			"DER:30:03:02:01:05",
62 #endif
63 			&ext_ctx);
64 	return ext;
65 }
66 
getAuthKeyIdent()67 x509v3ext NewX509::getAuthKeyIdent()
68 {
69 	x509v3ext ext;
70 	if (!authKey->isChecked() || !authKey->isEnabled())
71 		return ext;
72 
73 	QString x = "keyid,issuer";
74 	ext.create(NID_authority_key_identifier, x, &ext_ctx);
75 	return ext;
76 }
77 
getKeyUsage()78 x509v3ext NewX509::getKeyUsage()
79 {
80 	QString keyusage[] = {
81 		"digitalSignature", "nonRepudiation", "keyEncipherment",
82 		"dataEncipherment", "keyAgreement", "keyCertSign",
83 		"cRLSign", "encipherOnly", "decipherOnly"
84 	};
85 
86 	QStringList cont;
87 	x509v3ext ext;
88 
89 	int rows = keyUsage->count();
90 	for (int i=0; i<rows; i++) {
91 		if (keyUsage->item(i)->isSelected())
92 			cont << keyusage[i];
93 	}
94 	if (kuCritical->isChecked() && cont.count() > 0)
95 		cont.prepend("critical");
96 	ext.create(NID_key_usage, cont.join(", "), &ext_ctx);
97 	return ext;
98 }
99 
getEkeyUsage()100 x509v3ext NewX509::getEkeyUsage()
101 {
102 	QStringList cont;
103 	x509v3ext ext;
104 
105 	int rows = ekeyUsage->count();
106 	for (int i=0; i<rows; i++) {
107 		if (ekeyUsage->item(i)->isSelected())
108 			cont << QString(OBJ_nid2sn(extkeyuse_nid[i]));
109 	}
110 	if (ekuCritical->isChecked() && cont.count() > 0)
111 		cont.prepend("critical");
112 	ext.create(NID_ext_key_usage, cont.join(", "), &ext_ctx);
113 	return ext;
114 }
115 
getSubAltName()116 x509v3ext NewX509::getSubAltName()
117 {
118 	x509v3ext ext;
119 	QString s = subAltName->text();
120 	if (pt == x509_req) {
121 		QStringList sn, sl = s.split(',');
122 		foreach (QString str, sl) {
123 			if (str != "email:copy")
124 				sn += str;
125 		}
126 		s = sn.join(",");
127 	}
128 	ext.create(NID_subject_alt_name, s, &ext_ctx);
129 	return ext;
130 }
131 
getIssAltName()132 x509v3ext NewX509::getIssAltName()
133 {
134 	x509v3ext ext;
135 	QString s = issAltName->text();
136 	if (pt == x509_req) {
137 		QStringList sn, sl = s.split(',');
138 		foreach (QString str, sl) {
139 			if (str != "issuer:copy")
140 				sn += str;
141 		}
142 		s = sn.join(",");
143 	}
144 	ext.create(NID_issuer_alt_name, s, &ext_ctx);
145 	return ext;
146 }
147 
getCrlDist()148 x509v3ext NewX509::getCrlDist()
149 {
150 	x509v3ext ext;
151 	if (!crlDist->text().isEmpty()) {
152 		ext.create(NID_crl_distribution_points, crlDist->text(), &ext_ctx);
153 	}
154 	return ext;
155 }
156 
getAuthInfAcc()157 x509v3ext NewX509::getAuthInfAcc()
158 {
159 	x509v3ext ext;
160 	if (!authInfAcc->text().isEmpty()) {
161 		ext.create(NID_info_access, authInfAcc->text(), &ext_ctx);
162 	}
163 	return ext;
164 }
165 
getAdvanced()166 extList NewX509::getAdvanced()
167 {
168 	QString conf_str;
169 	CONF *conf;
170 	extList elist;
171 	long err_line=0;
172 	STACK_OF(X509_EXTENSION) **sk, *sk_tmp = NULL;
173 	const STACK_OF(X509_EXTENSION) *csk;
174 	const char *ext_name = "default";
175 	int ret, start;
176 
177 	if (nconf_data->isReadOnly()) {
178 		conf_str = v3ext_backup;
179 	} else {
180 		conf_str = nconf_data->toPlainText();
181 	}
182 	if (conf_str.isEmpty())
183 		return elist;
184 
185 	conf = NCONF_new(NULL);
186 	ret = NCONF_load_bio(conf, BioByteArray(conf_str.toLatin1()).ro(),
187 				&err_line);
188 	if (ret != 1) {
189 		openssl_error(tr("Configfile error on line %1\n").
190 				arg(err_line));
191 		return elist;
192 	}
193 
194 	if (ext_ctx.subject_cert) {
195 		csk = X509_get0_extensions(ext_ctx.subject_cert);
196 		start = csk? sk_X509_EXTENSION_num(csk): 0;
197 	} else {
198 		sk = &sk_tmp;
199 		start = 0;
200 	}
201 
202 	X509V3_set_nconf(&ext_ctx, conf);
203 
204 	if (ext_ctx.subject_cert) {
205 		if (X509V3_EXT_add_nconf(conf, &ext_ctx,
206 				(char *) ext_name, ext_ctx.subject_cert))
207 			openssl_error();
208 		csk = X509_get0_extensions(ext_ctx.subject_cert);
209 	} else {
210 		if (X509V3_EXT_add_nconf_sk(conf, &ext_ctx, (char *)ext_name, sk))
211 			openssl_error();
212 		csk = *sk;
213 	}
214 
215 	elist.setStack(csk, start);
216 	if (!ext_ctx.subject_cert)
217 		sk_X509_EXTENSION_pop_free(sk_tmp, X509_EXTENSION_free);
218 
219 	X509V3_set_nconf(&ext_ctx, NULL);
220 	NCONF_free(conf);
221 	openssl_error();
222 	return elist;
223 }
224 
getGuiExt()225 extList NewX509::getGuiExt()
226 {
227 	extList ne;
228 
229 	ne << getBasicConstraints();
230 	ne << getSubKeyIdent();
231 	ne << getAuthKeyIdent();
232 	ne << getKeyUsage();
233 	ne << getEkeyUsage();
234 	ne << getSubAltName();
235 	ne << getIssAltName();
236 	ne << getCrlDist();
237 	ne << getAuthInfAcc();
238 	ne << getOCSPstaple();
239 	openssl_error();
240 	return ne;
241 }
242 
getAllExt()243 extList NewX509::getAllExt()
244 {
245 	extList ne;
246 	ne = getGuiExt();
247 	ne += getAdvanced();
248 	if (!Settings["disable_netscape"])
249 		ne += getNetscapeExt();
250 	return ne;
251 }
252 
getNetscapeExt()253 extList NewX509::getNetscapeExt()
254 {
255 	QString certTypeList[] = {
256 		"client", "server",  "email", "objsign",
257 		"sslCA",  "emailCA", "objCA" };
258 
259 
260 	QStringList cont;
261 	x509v3ext ext;
262 	extList el;
263 
264 	int rows = nsCertType->count();
265 	for (int i=0; i<rows; i++) {
266 		if (nsCertType->item(i)->isSelected())
267 			cont << certTypeList[i];
268 	}
269 
270 	el << ext.create(NID_netscape_cert_type, cont.join(", "), &ext_ctx);
271 	el << ext.create_ia5(NID_netscape_base_url, nsBaseUrl->text(), &ext_ctx);
272 	el << ext.create_ia5(NID_netscape_revocation_url, nsRevocationUrl->text(), &ext_ctx);
273 	el << ext.create_ia5(NID_netscape_ca_revocation_url, nsCARevocationUrl->text(), &ext_ctx);
274 	el << ext.create_ia5(NID_netscape_renewal_url, nsRenewalUrl->text(), &ext_ctx);
275 	el << ext.create_ia5(NID_netscape_ca_policy_url, nsCaPolicyUrl->text(), &ext_ctx);
276 	el << ext.create_ia5(NID_netscape_ssl_server_name, nsSslServerName->text(), &ext_ctx);
277 	el << ext.create_ia5(NID_netscape_comment, nsComment->text(), &ext_ctx);
278 	return el;
279 }
280 
initCtx(pki_x509 * subj,pki_x509 * iss,pki_x509req * req)281 void NewX509::initCtx(pki_x509 *subj, pki_x509 *iss, pki_x509req *req)
282 {
283 	X509 *s = NULL, *s1 = NULL;
284 	X509_REQ *r = NULL;
285 
286 	if (subj) s1 = subj->getCert();
287 	if (iss) s = iss->getCert();
288 	if (req) r = req->getReq();
289 
290 	X509V3_set_ctx(&ext_ctx, s, s1, r, NULL, 0);
291 }
292 
getExtDuplicates()293 extList NewX509::getExtDuplicates()
294 {
295 	int i, start, cnt, n1, n;
296 	x509v3ext e;
297 	const STACK_OF(X509_EXTENSION) *sk;
298 	extList el_dup, el;
299 	QString olist;
300 
301 	if (ext_ctx.subject_cert) {
302 		sk = X509_get0_extensions(ext_ctx.subject_cert);
303 	} else
304 		return el_dup;
305 
306 	el.setStack(sk, 0);
307 	cnt = el.size();
308 	for (start=0; start < cnt; start++) {
309 		n1 = el[start].nid();
310 		for (i = start+1; i<cnt; i++) {
311 			e = el[i];
312 			n = e.nid();
313 			if (n1 == n) {
314 				// DUPLICATE
315 				if (el_dup.idxByNid(n1) ==-1)
316 					el_dup << e;
317 
318 			}
319 		}
320         }
321 	return el_dup;
322 }
323