mirror of
https://github.com/chris2511/xca.git
synced 2026-09-12 19:51:05 +05:00
- Fix: [ 2342561 ] Checkbox disabled in template dialog
- Fix: [ 2088468 ] Create self signed w. ext."Authority Key Identifier" fails
- Start fixing
1998815: xca adds basic constraint "CA" twice resulting in invalid CA
358 lines
7.9 KiB
C++
358 lines
7.9 KiB
C++
/* vi: set sw=4 ts=4:
|
|
*
|
|
* Copyright (C) 2001 - 2007 Christian Hohnstaedt.
|
|
*
|
|
* All rights reserved.
|
|
*/
|
|
|
|
|
|
#include "NewX509.h"
|
|
#include <qcheckbox.h>
|
|
#include <qcombobox.h>
|
|
#include <qradiobutton.h>
|
|
#include <qlineedit.h>
|
|
#include <qlistwidget.h>
|
|
#include <qmessagebox.h>
|
|
#include "MainWindow.h"
|
|
#include "lib/x509v3ext.h"
|
|
|
|
|
|
x509v3ext NewX509::getBasicConstraints()
|
|
{
|
|
QStringList cont;
|
|
x509v3ext ext;
|
|
QString ca[] = { "", "CA:TRUE", "CA:FALSE" };
|
|
if (basicCA->currentIndex() > 0) {
|
|
if (bcCritical->isChecked())
|
|
cont << "critical";
|
|
cont << ca[basicCA->currentIndex()];
|
|
if (!basicPath->text().isEmpty())
|
|
cont << (QString)"pathlen:" + basicPath->text();
|
|
ext.create(NID_basic_constraints, cont.join(", "), &ext_ctx);
|
|
}
|
|
return ext;
|
|
}
|
|
|
|
void NewX509::setBasicConstraints(const x509v3ext &e)
|
|
{
|
|
if (e.nid() != NID_basic_constraints) return;
|
|
BASIC_CONSTRAINTS *bc;
|
|
x509v3ext ex = e;
|
|
bc = (BASIC_CONSTRAINTS *)ex.d2i();
|
|
if (bc) {
|
|
bcCritical->setChecked(bc->ca);
|
|
a1int pl(bc->pathlen);
|
|
basicPath->setText(QString::number(pl.getLong()));
|
|
}
|
|
}
|
|
|
|
x509v3ext NewX509::getSubKeyIdent()
|
|
{
|
|
x509v3ext ext;
|
|
if (subKey->isChecked())
|
|
ext.create(NID_subject_key_identifier, "hash", &ext_ctx);
|
|
return ext;
|
|
}
|
|
|
|
|
|
x509v3ext NewX509::getAuthKeyIdent()
|
|
{
|
|
x509v3ext ext;
|
|
if (authKey->isChecked() && authKey->isEnabled()) {
|
|
if (foreignSignRB->isChecked())
|
|
ext.create(NID_authority_key_identifier,
|
|
"keyid,issuer:always", &ext_ctx);
|
|
else
|
|
ext.create(NID_authority_key_identifier,
|
|
"keyid,issuer", &ext_ctx);
|
|
}
|
|
return ext;
|
|
}
|
|
|
|
x509v3ext NewX509::getKeyUsage()
|
|
{
|
|
QString keyusage[] = {
|
|
"digitalSignature", "nonRepudiation", "keyEncipherment",
|
|
"dataEncipherment", "keyAgreement", "keyCertSign",
|
|
"cRLSign", "encipherOnly", "decipherOnly"
|
|
};
|
|
|
|
QStringList cont;
|
|
x509v3ext ext;
|
|
|
|
int rows = keyUsage->count();
|
|
for (int i=0; i<rows; i++) {
|
|
if (keyUsage->isItemSelected(keyUsage->item(i))) {
|
|
cont << keyusage[i];
|
|
}
|
|
}
|
|
if (kuCritical->isChecked() && cont.count() > 0)
|
|
cont.prepend("critical");
|
|
ext.create(NID_key_usage, cont.join(", "), &ext_ctx);
|
|
return ext;
|
|
}
|
|
|
|
x509v3ext NewX509::getEkeyUsage()
|
|
{
|
|
QStringList cont;
|
|
x509v3ext ext;
|
|
|
|
int rows = ekeyUsage->count();
|
|
for (int i=0; i<rows; i++) {
|
|
//QListWidgetItem *li = ekeyUsage->item(i);
|
|
//printf("rows = %d, ekeyUsage = %d, %p\n", rows, i, li);
|
|
if (ekeyUsage->isItemSelected(ekeyUsage->item(i))) {
|
|
cont << (QString)OBJ_nid2sn(eku_nid[i]);
|
|
}
|
|
}
|
|
if (ekuCritical->isChecked() && cont.count() > 0)
|
|
cont.prepend("critical");
|
|
ext.create(NID_ext_key_usage, cont.join(", "), &ext_ctx);
|
|
return ext;
|
|
}
|
|
|
|
x509v3ext NewX509::getSubAltName()
|
|
{
|
|
x509v3ext ext;
|
|
QString s = subAltName->text();
|
|
if (pt == x509_req) {
|
|
QStringList sn, sl = s.split(',');
|
|
foreach (QString str, sl) {
|
|
if (str != "email:copy")
|
|
sn += str;
|
|
}
|
|
s = sn.join(",");
|
|
}
|
|
ext.create(NID_subject_alt_name, s, &ext_ctx);
|
|
return ext;
|
|
}
|
|
|
|
x509v3ext NewX509::getIssAltName()
|
|
{
|
|
x509v3ext ext;
|
|
QString s = issAltName->text();
|
|
if (pt == x509_req) {
|
|
QStringList sn, sl = s.split(',');
|
|
foreach (QString str, sl) {
|
|
if (str != "issuer:copy")
|
|
sn += str;
|
|
}
|
|
s = sn.join(",");
|
|
}
|
|
ext.create(NID_issuer_alt_name, s, &ext_ctx);
|
|
return ext;
|
|
}
|
|
|
|
x509v3ext NewX509::getCrlDist()
|
|
{
|
|
x509v3ext ext;
|
|
if (!crlDist->text().isEmpty()) {
|
|
ext.create(NID_crl_distribution_points, crlDist->text(), &ext_ctx);
|
|
}
|
|
return ext;
|
|
}
|
|
|
|
QString NewX509::getAuthInfAcc_string()
|
|
{
|
|
QString rval="";
|
|
QString aia_txt = authInfAcc->text();
|
|
aia_txt = aia_txt.trimmed();
|
|
|
|
if (!aia_txt.isEmpty()) {
|
|
rval = OBJ_nid2sn(aia_nid[aiaOid->currentIndex()]);
|
|
rval += ";" + aia_txt;
|
|
}
|
|
return rval;
|
|
}
|
|
|
|
void NewX509::setAuthInfAcc_string(QString aia_txt)
|
|
{
|
|
QStringList aia;
|
|
int nid;
|
|
|
|
aia = aia_txt.split(';');
|
|
|
|
if (aia.count() != 2)
|
|
return;
|
|
|
|
nid = OBJ_sn2nid(CCHAR(aia[0]));
|
|
|
|
for (int i=0; i < aia_nid.count(); i++) {
|
|
if (aia_nid[i] == nid) {
|
|
aiaOid->setCurrentIndex(i);
|
|
}
|
|
}
|
|
authInfAcc->setText(aia[1]);
|
|
}
|
|
|
|
x509v3ext NewX509::getAuthInfAcc()
|
|
{
|
|
x509v3ext ext;
|
|
QString aia_txt = getAuthInfAcc_string();
|
|
|
|
if (!aia_txt.isEmpty()) {
|
|
ext.create(NID_info_access, aia_txt, &ext_ctx);
|
|
}
|
|
return ext;
|
|
}
|
|
|
|
extList NewX509::getAdvanced()
|
|
{
|
|
QString conf_str;
|
|
CONF *conf;
|
|
BIO *bio;
|
|
extList elist;
|
|
long err_line=0;
|
|
STACK_OF(X509_EXTENSION) **sk, *sk_tmp = NULL;
|
|
char ext_name[] = "ext";
|
|
int ret, i, start;
|
|
|
|
conf_str = nconf_data->toPlainText();
|
|
if (conf_str.isEmpty())
|
|
return elist;
|
|
conf_str += "\n";
|
|
QStringList list = conf_str.split("\n", QString::SkipEmptyParts);
|
|
|
|
conf_str = QString("[") + ext_name + "]\n";
|
|
for (i=0; i< list.count(); i++) {
|
|
conf_str += list[i].trimmed() + "\n";
|
|
}
|
|
bio = BIO_new_mem_buf((void*)CCHAR(conf_str), conf_str.length());
|
|
if (!bio)
|
|
return elist;
|
|
conf = NCONF_new(NULL);
|
|
ret = NCONF_load_bio(conf, bio, &err_line);
|
|
if (ret != 1) {
|
|
int i = ERR_get_error();
|
|
printf("Ret: %d, ERRLINE=%ld: %s\n", ret, err_line,
|
|
ERR_error_string(i ,NULL));
|
|
|
|
QMessageBox::warning(this, XCA_TITLE,
|
|
tr("Advanced Settings Error: ") +
|
|
ERR_error_string(i ,NULL), tr("OK"));
|
|
BIO_free(bio);
|
|
return elist;
|
|
}
|
|
|
|
if (ext_ctx.subject_cert) {
|
|
sk = &ext_ctx.subject_cert->cert_info->extensions;
|
|
start = *sk ? sk_X509_EXTENSION_num(*sk) : 0;
|
|
} else {
|
|
sk = &sk_tmp;
|
|
start = 0;
|
|
}
|
|
|
|
X509V3_set_nconf(&ext_ctx, conf);
|
|
X509V3_EXT_add_nconf_sk(conf, &ext_ctx, ext_name, sk);
|
|
elist.setStack(*sk, start);
|
|
if (sk == &sk_tmp)
|
|
sk_X509_EXTENSION_pop_free(sk_tmp, X509_EXTENSION_free);
|
|
X509V3_set_nconf(&ext_ctx, NULL);
|
|
NCONF_free(conf);
|
|
BIO_free(bio);
|
|
return elist;
|
|
}
|
|
|
|
extList NewX509::getGuiExt()
|
|
{
|
|
extList ne;
|
|
|
|
ne << getBasicConstraints();
|
|
ne << getSubKeyIdent();
|
|
ne << getAuthKeyIdent();
|
|
ne << getKeyUsage();
|
|
ne << getEkeyUsage();
|
|
ne << getSubAltName();
|
|
ne << getIssAltName();
|
|
ne << getCrlDist();
|
|
ne << getAuthInfAcc();
|
|
return ne;
|
|
}
|
|
|
|
extList NewX509::getAllExt()
|
|
{
|
|
extList ne;
|
|
ne = getGuiExt();
|
|
ne += getAdvanced();
|
|
ne += getNetscapeExt();
|
|
return ne;
|
|
}
|
|
|
|
extList NewX509::getNetscapeExt()
|
|
{
|
|
QString certTypeList[] = {
|
|
"client", "server", "email", "objsign",
|
|
"sslCA", "emailCA", "objCA" };
|
|
|
|
|
|
QStringList cont;
|
|
x509v3ext ext;
|
|
extList el;
|
|
|
|
int rows = nsCertType->count();
|
|
for (int i=0; i<rows; i++) {
|
|
if (nsCertType->isItemSelected(nsCertType->item(i))) {
|
|
cont << certTypeList[i];
|
|
}
|
|
}
|
|
|
|
el << ext.create(NID_netscape_cert_type, cont.join(", "), &ext_ctx);
|
|
el << ext.create(NID_netscape_base_url, nsBaseUrl->text(), &ext_ctx);
|
|
el << ext.create(NID_netscape_revocation_url, nsRevocationUrl->text(), &ext_ctx);
|
|
el << ext.create(NID_netscape_ca_revocation_url, nsCARevocationUrl->text(), &ext_ctx);
|
|
el << ext.create(NID_netscape_renewal_url, nsRenewalUrl->text(), &ext_ctx);
|
|
el << ext.create(NID_netscape_ca_policy_url, nsCaPolicyUrl->text(), &ext_ctx);
|
|
el << ext.create(NID_netscape_ssl_server_name, nsSslServerName->text(), &ext_ctx);
|
|
el << ext.create(NID_netscape_comment, nsComment->text(), &ext_ctx);
|
|
return el;
|
|
}
|
|
|
|
void NewX509::initCtx(pki_x509 *subj, pki_x509 *iss, pki_x509req *req)
|
|
{
|
|
X509 *s = NULL, *s1 = NULL;
|
|
X509_REQ *r = NULL;
|
|
|
|
if (subj) s1 = subj->getCert();
|
|
if (iss) s = iss->getCert();
|
|
if (req) r = req->getReq();
|
|
|
|
X509V3_set_ctx(&ext_ctx, s, s1, r, NULL, 0);
|
|
}
|
|
|
|
void NewX509::checkExtDuplicates()
|
|
{
|
|
int i, start, cnt, n1, n;
|
|
X509_EXTENSION *e, *e1;
|
|
STACK_OF(X509_EXTENSION) *sk;
|
|
|
|
if (ext_ctx.subject_cert) {
|
|
sk = ext_ctx.subject_cert->cert_info->extensions;
|
|
} else
|
|
return;
|
|
|
|
cnt = sk_X509_EXTENSION_num(sk);
|
|
for (start=0; start<cnt; start++) {
|
|
e1 = sk_X509_EXTENSION_value(sk, start);
|
|
n1 = OBJ_obj2nid(X509_EXTENSION_get_object(e1));
|
|
for (i=start+1; i<cnt; i++) {
|
|
e = sk_X509_EXTENSION_value(sk, i);
|
|
n = OBJ_obj2nid(X509_EXTENSION_get_object(e));
|
|
if (n1 == n) {
|
|
// DUPLICATE
|
|
x509v3ext x;
|
|
x.set(e);
|
|
printf("DUPLICATE: %d %d, %d:%d %d\n%s\n", n, n1, cnt, start,i, CCHAR(x.getHtml()));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void NewX509::setExt(const x509v3ext &ext)
|
|
{
|
|
switch (ext.nid()) {
|
|
case NID_basic_constraints:
|
|
bcCritical->setChecked(ext.getCritical());
|
|
}
|
|
}
|
|
|