}
- public static final int CURRENT_SCHEMA_VERSION = 20;
+ public static final int CURRENT_SCHEMA_VERSION = 21;
public static final int CONNECTION_TIMEOUT = 24 * 60 * 60;
"revoked" timestamp NULL DEFAULT NULL,
"expire" timestamp NULL DEFAULT NULL,
"renewed" boolean NOT NULL DEFAULT 'false',
- "disablelogin" boolean NOT NULL DEFAULT 'false',
"pkhash" char(40) DEFAULT NULL,
"certhash" char(40) DEFAULT NULL,
"description" varchar(100) NOT NULL DEFAULT '',
PRIMARY KEY ("certId", "name")
);
-DROP TABLE IF EXISTS "clientcerts";
-CREATE TABLE "clientcerts" (
+DROP TABLE IF EXISTS "logincerts";
+CREATE TABLE "logincerts" (
"id" int NOT NULL,
- "disablelogin" boolean NOT NULL DEFAULT 'false',
PRIMARY KEY ("id")
);
"version" smallint NOT NULL,
PRIMARY KEY ("version")
);
-INSERT INTO "schemeVersion" (version) VALUES(20);
+INSERT INTO "schemeVersion" (version) VALUES(21);
DROP TABLE IF EXISTS `passwordResetTickets`;
CREATE TABLE `passwordResetTickets` (
--- /dev/null
+ALTER TABLE "certs" DROP "disablelogin";
+
+
+ALTER TABLE "clientcerts" RENAME TO "logincerts";
+DELETE FROM "logincerts" WHERE "disablelogin" = 'true';
+ALTER TABLE "logincerts" DROP "disablelogin";
}
return null;
}
+
+ public void setLoginEnabled(boolean activate) {
+ if (activate) {
+ if ( !isLoginEnabled()) {
+ try (GigiPreparedStatement prep = new GigiPreparedStatement("INSERT INTO `logincerts` SET `id`=?")) {
+ prep.setInt(1, id);
+ prep.execute();
+ }
+ }
+ } else {
+ try (GigiPreparedStatement prep = new GigiPreparedStatement("DELETE FROM `logincerts` WHERE `id`=?")) {
+ prep.setInt(1, id);
+ prep.execute();
+ }
+ }
+ }
+
+ public boolean isLoginEnabled() {
+ try (GigiPreparedStatement prep = new GigiPreparedStatement("SELECT 1 FROM `logincerts` WHERE `id`=?")) {
+ prep.setInt(1, id);
+ GigiResultSet res = prep.executeQuery();
+ return res.next();
+ }
+ }
}
}
public static CertificateOwner getByEnabledSerial(String serial) {
- try (GigiPreparedStatement prep = new GigiPreparedStatement("SELECT `memid` FROM `certs` WHERE serial=? AND `disablelogin`='f' AND `revoked` is NULL")) {
+ try (GigiPreparedStatement prep = new GigiPreparedStatement("SELECT `memid` FROM `certs` INNER JOIN `logincerts` ON `logincerts`.`id`=`certs`.`id` WHERE serial=? AND `revoked` is NULL")) {
prep.setString(1, serial.toLowerCase());
GigiResultSet res = prep.executeQuery();
if (res.next()) {
error.format(out, Page.getLanguage(req));
return false;
}
+ if (login) {
+ result.setLoginEnabled(true);
+ }
result.issue(issueDate.getFrom(), issueDate.getTo(), c.getActor()).waitFor(60000);
this.result = result;
return true;
final PrivateKey pk = kp.getPrivate();
await(c.issue(null, "2y", u));
final X509Certificate ce = c.cert();
+ c.setLoginEnabled(true);
assertNotNull(login(pk, ce));
}
String cookie = login(u.getEmail(), TEST_PASSWORD);
testFails(CertificateStatus.ISSUED, c);
X509Certificate cert = c.cert();
+ c.setLoginEnabled(true);
assertNotNull(login(pk, cert));
assertEquals(1, countRegex(IOUtils.readURL(get(cookie, Certificates.PATH)), "<td>(?:REVOKED|ISSUED)</td>"));
assertEquals(1, countRegex(IOUtils.readURL(get(cookie, Certificates.PATH + "?withRevoked")), "<td>(?:REVOKED|ISSUED)</td>"));
String key = generatePEMCSR(kp, "CN=testmail@example.com");
Certificate c = new Certificate(u, u, Certificate.buildDN("CN", "testmail@example.com"), Digest.SHA256, key, CSRType.CSR, CertificateProfile.getById(1));
final PrivateKey pk = kp.getPrivate();
+ c.setLoginEnabled(true);
await(c.issue(null, "2y", u));
URLConnection con = new URL("https://" + ServerConstants.getSecureHostNamePort()).openConnection();
final PrivateKey pk = kp.getPrivate();
await(c.issue(null, "2y", u));
final X509Certificate ce = c.cert();
+ c.setLoginEnabled(true);
String scookie = login(pk, ce);
assertTrue(isLoggedin(cookie));
await(c2.issue(null, "2y", u));
await(j1);
final X509Certificate ce = c.cert();
+ c.setLoginEnabled(true);
String scookie = login(pk, ce);
checkCertLogin(c, pk, scookie, 200);
public void testLookupSerial() throws GigiApiException, IOException, GeneralSecurityException, InterruptedException {
Certificate target2 = new Certificate(u, u, Certificate.buildDN("EMAIL", u.getEmail()), Digest.SHA256, generatePEMCSR(generateKeypair(), "EMAIL=" + u.getEmail()), CSRType.CSR, CertificateProfile.getByName("client"), new Certificate.SubjectAlternateName(SANType.EMAIL, "cats@cacert.org"));
await(target2.issue(null, "2y", u));
+ target2.setLoginEnabled(true);
assertEquals(u.getId(), Integer.parseInt(apiLookup(target2)));
}
kp = generateKeypair();
String key1 = generatePEMCSR(kp, "EMAIL=testmail@example.com");
c = new Certificate(u, u, Certificate.buildDN("EMAIL", "testmail@example.com"), Digest.SHA256, key1, CSRType.CSR, CertificateProfile.getById(1));
+ c.setLoginEnabled(true);
pk = kp.getPrivate();
await(c.issue(null, "2y", u));
ce = c.cert();
--- /dev/null
+package org.cacert.gigi.dbObjects;
+
+import static org.junit.Assert.*;
+
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+import java.security.KeyPair;
+
+import org.cacert.gigi.GigiApiException;
+import org.cacert.gigi.dbObjects.Certificate.CSRType;
+import org.cacert.gigi.testUtils.ClientBusinessTest;
+import org.junit.Test;
+
+public class TestCertificate extends ClientBusinessTest {
+
+ @Test
+ public void testSetLoginEnabled() throws GeneralSecurityException, IOException, GigiApiException {
+ KeyPair kp = generateKeypair();
+ String key = generatePEMCSR(kp, "CN=testmail@example.com");
+ Certificate c = new Certificate(u, u, Certificate.buildDN("CN", "testmail@example.com"), Digest.SHA256, key, CSRType.CSR, CertificateProfile.getById(1));
+
+ assertFalse(c.isLoginEnabled());
+ c.setLoginEnabled(true);
+ assertTrue(c.isLoginEnabled());
+ c.setLoginEnabled(true);
+ assertTrue(c.isLoginEnabled());
+ c.setLoginEnabled(false);
+ assertFalse(c.isLoginEnabled());
+ c.setLoginEnabled(false);
+ assertFalse(c.isLoginEnabled());
+ }
+}
import java.util.regex.Pattern;
import org.cacert.gigi.crypto.SPKAC;
+import org.cacert.gigi.dbObjects.CertificateOwner;
import org.cacert.gigi.dbObjects.Digest;
import org.cacert.gigi.pages.account.certs.CertificateAdd;
import org.cacert.gigi.pages.account.certs.CertificateRequest;
Date start = new Date(now);
Date end = new Date(now + MS_PER_DAY * 10);
String validity = "&validFrom=" + sdf.format(start) + "&validity=" + sdf.format(end);
- X509Certificate res = createCertWithValidity(validity);
+ X509Certificate res = createCertWithValidity(validity, false);
assertNotNull(validity, res);
assertEquals(start, res.getNotBefore());
assertEquals(end, res.getNotAfter());
}
private void testCertificateValidityRelative(int field, int amount, String length, boolean shouldsucceed) throws IOException, GeneralSecurityException, UnsupportedEncodingException, MalformedURLException, CertificateException {
- X509Certificate parsed = createCertWithValidity("&validFrom=now&validity=" + length);
+ X509Certificate parsed = createCertWithValidity("&validFrom=now&validity=" + length, false);
if (parsed == null) {
assertTrue( !shouldsucceed);
return;
assertEquals(c.getTime(), end);
}
- private X509Certificate createCertWithValidity(String validity) throws IOException, GeneralSecurityException, UnsupportedEncodingException, MalformedURLException, CertificateException {
+ private X509Certificate createCertWithValidity(String validity, boolean login) throws IOException, GeneralSecurityException, UnsupportedEncodingException, MalformedURLException, CertificateException {
PKCS10Attributes atts = buildAtts(new ObjectIdentifier[] {
CertificateRequest.OID_KEY_USAGE_SSL_CLIENT
}, new RFC822Name(email));
out.write(("csrf=" + URLEncoder.encode(csrf, "UTF-8")).getBytes("UTF-8"));
out.write(("&profile=client&CN=" + CertificateRequest.DEFAULT_CN + "&SANs=" + URLEncoder.encode("email:" + email + "\n", "UTF-8")).getBytes("UTF-8"));
out.write(("&hash_alg=SHA512&").getBytes("UTF-8"));
+ if (login) {
+ out.write(("login=1&").getBytes("UTF-8"));
+ }
out.write(validity.getBytes("UTF-8"));
String certurl = huc.getHeaderField("Location");
String resultingCN = m.group(1);
return resultingCN;
}
+
+ @Test
+ public void testSetLoginEnabled() throws IOException, GeneralSecurityException {
+ X509Certificate parsedLoginNotEnabled = createCertWithValidity("&validFrom=now&validity=1m", false);
+ assertNull(CertificateOwner.getByEnabledSerial(parsedLoginNotEnabled.getSerialNumber().toString(16)));
+
+ X509Certificate parsedLoginEnabled = createCertWithValidity("&validFrom=now&validity=1m", true);
+ assertEquals(u, CertificateOwner.getByEnabledSerial(parsedLoginEnabled.getSerialNumber().toString(16)));
+ }
}
pk = kp.getPrivate();
await(c.issue(null, "2y", u));
ce = c.cert();
+ c.setLoginEnabled(true);
} catch (IOException e) {
throw new Error(e);
} catch (GigiApiException e) {