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