secureContextFactory.setNeedClientAuth(false);
final SslContextFactory staticContextFactory = generateSSLContextFactory(conf, "static");
final SslContextFactory apiContextFactory = generateSSLContextFactory(conf, "api");
+ apiContextFactory.setWantClientAuth(true);
try {
secureContextFactory.start();
staticContextFactory.start();
import java.io.IOException;
import java.io.InputStreamReader;
+import java.security.GeneralSecurityException;
+import java.security.cert.X509Certificate;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
+import org.cacert.gigi.GigiApiException;
+import org.cacert.gigi.dbObjects.Certificate;
+import org.cacert.gigi.dbObjects.Certificate.CertificateStatus;
+import org.cacert.gigi.dbObjects.User;
+import org.cacert.gigi.pages.LoginPage;
+import org.cacert.gigi.pages.account.certs.CertificateRequest;
+import org.cacert.gigi.util.Job;
+import org.cacert.gigi.util.PEM;
+
public class GigiAPI extends HttpServlet {
@Override
strB.append(buffer, 0, len);
}
System.out.println(strB);
+ return;
+ }
+ X509Certificate cert = LoginPage.getCertificateFromRequest(req);
+ if (cert == null) {
+ resp.sendError(403, "Error, cert authing required.");
+ return;
+ }
+ String serial = LoginPage.extractSerialFormCert(cert);
+ User u = LoginPage.fetchUserBySerial(serial);
+
+ if (pi.equals("/account/certs/new")) {
+
+ if ( !req.getMethod().equals("POST")) {
+ resp.sendError(500, "Error, POST required.");
+ return;
+ }
+ if (req.getQueryString() != null) {
+ resp.sendError(500, "Error, no query String allowed.");
+ return;
+ }
+ String csr = req.getParameter("csr");
+ if (csr == null) {
+ resp.sendError(500, "Error, no CSR found");
+ return;
+ }
+ try {
+ CertificateRequest cr = new CertificateRequest(u, csr);
+ Certificate result = cr.draft();
+ Job job = result.issue(null, "2y");
+ job.waitFor(60000);
+ if (result.getStatus() != CertificateStatus.ISSUED) {
+ resp.sendError(510, "Error, issuing timed out");
+ return;
+ }
+ resp.getWriter().println(PEM.encode("CERTIFICATE", result.cert().getEncoded()));
+ } catch (GeneralSecurityException e) {
+ e.printStackTrace();
+ } catch (GigiApiException e) {
+ e.printStackTrace();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
}
}
}
public boolean beforeTemplate(HttpServletRequest req, HttpServletResponse resp) throws IOException {
String redir = (String) req.getSession().getAttribute(LOGIN_RETURNPATH);
if (req.getSession().getAttribute("loggedin") == null) {
- X509Certificate[] cert = (X509Certificate[]) req.getAttribute("javax.servlet.request.X509Certificate");
- if (cert != null && cert[0] != null) {
- tryAuthWithCertificate(req, cert[0]);
+ X509Certificate cert = getCertificateFromRequest(req);
+ if (cert != null) {
+ tryAuthWithCertificate(req, cert);
}
if (req.getMethod().equals("POST")) {
try {
}
private void tryAuthWithCertificate(HttpServletRequest req, X509Certificate x509Certificate) {
- String serial = x509Certificate.getSerialNumber().toString(16).toUpperCase();
+ String serial = extractSerialFormCert(x509Certificate);
+ User user = fetchUserBySerial(serial);
+ if (user == null) {
+ return;
+ }
+ loginSession(req, user);
+ req.getSession().setAttribute(CERT_SERIAL, serial);
+ req.getSession().setAttribute(CERT_ISSUER, x509Certificate.getIssuerDN());
+ req.getSession().setAttribute(LOGIN_METHOD, "Certificate");
+ }
+
+ public static String extractSerialFormCert(X509Certificate x509Certificate) {
+ return x509Certificate.getSerialNumber().toString(16).toUpperCase();
+ }
+
+ public static User fetchUserBySerial(String serial) {
GigiPreparedStatement ps = DatabaseConnection.getInstance().prepare("SELECT `memid` FROM `certs` WHERE `serial`=? AND `disablelogin`='0' AND `revoked` is NULL");
ps.setString(1, serial);
GigiResultSet rs = ps.executeQuery();
+ User user = null;
if (rs.next()) {
- loginSession(req, User.getById(rs.getInt(1)));
- req.getSession().setAttribute(CERT_SERIAL, serial);
- req.getSession().setAttribute(CERT_ISSUER, x509Certificate.getIssuerDN());
- req.getSession().setAttribute(LOGIN_METHOD, "Certificate");
+ user = User.getById(rs.getInt(1));
}
rs.close();
+ return user;
+ }
+
+ public static X509Certificate getCertificateFromRequest(HttpServletRequest req) {
+ X509Certificate[] cert = (X509Certificate[]) req.getAttribute("javax.servlet.request.X509Certificate");
+ X509Certificate uc = null;
+ if (cert != null && cert[0] != null) {
+ uc = cert[0];
+ }
+ return uc;
}
private static final Group LOGIN_BLOCKED = Group.getByString("blockedlogin");
if (req.getParameter("CCA") == null) {
error.mergeInto(new GigiApiException("You need to accept the CCA."));
}
+ Certificate result = null;
try {
result = cr.draft();
} catch (GigiApiException e) {
error.mergeInto(e);
}
- if ( !error.isEmpty()) {
+ if ( !error.isEmpty() || result == null) {
error.format(out, Page.getLanguage(req));
return false;
}
result.issue(issueDate.getFrom(), issueDate.getTo()).waitFor(60000);
+ this.result = result;
return true;
} else {
throw new GigiApiException("Error no action.");
import java.util.Arrays;
import java.util.Base64;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.TreeSet;
}
}
- GigiApiException error = new GigiApiException();
- this.SANs = verifySANs(error, false, SANs);
- if ( !error.isEmpty()) {
- throw error;
- }
+ this.SANs = SANs;
pk = parsed.getSubjectPublicKeyInfo();
String sign = getSignatureAlgorithm(data);
guessDigest(sign);
pk = parsed.getPubkey();
String sign = getSignatureAlgorithm(data);
guessDigest(sign);
-
+ this.SANs = new HashSet<>();
this.csr = "SPKAC=" + cleanedSPKAC;
this.csrType = CSRType.SPKAC;
return true;
}
- private Set<SubjectAlternateName> verifySANs(GigiApiException error, boolean server, TreeSet<SubjectAlternateName> parseSANBox) {
+ private Set<SubjectAlternateName> verifySANs(GigiApiException error, boolean server, Set<SubjectAlternateName> sANs2) {
Set<SubjectAlternateName> filteredSANs = new LinkedHashSet<>();
- for (SubjectAlternateName san : parseSANBox) {
+ for (SubjectAlternateName san : sANs2) {
if (san.getType() == SANType.DNS) {
if (u.isValidDomain(san.getName()) && server) {
if (pDNS == null) {
subject.put("EMAIL", pMail);
}
}
+ this.SANs = verifySANs(error, server, SANs);
if (org != null) {
subject.put("O", org.getName());
subject.put("C", org.getState());
--- /dev/null
+package org.cacert.gigi.api;
+
+import static org.junit.Assert.*;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.net.URLEncoder;
+import java.security.KeyPair;
+import java.security.PrivateKey;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.util.Collection;
+
+import org.cacert.gigi.dbObjects.Certificate;
+import org.cacert.gigi.dbObjects.Certificate.CSRType;
+import org.cacert.gigi.dbObjects.CertificateProfile;
+import org.cacert.gigi.testUtils.ClientTest;
+import org.cacert.gigi.testUtils.IOUtils;
+import org.junit.Test;
+
+import sun.security.x509.X500Name;
+
+public class IssueCert extends ClientTest {
+
+ @Test
+ public void testIssueCert() throws Exception {
+ KeyPair kp = generateKeypair();
+ String key1 = generatePEMCSR(kp, "CN=testmail@example.com");
+ Certificate c = new Certificate(u, Certificate.buildDN("CN", "testmail@example.com"), "sha256", key1, CSRType.CSR, CertificateProfile.getById(1));
+ final PrivateKey pk = kp.getPrivate();
+ c.issue(null, "2y").waitFor(60000);
+ final X509Certificate ce = c.cert();
+ HttpURLConnection connection = (HttpURLConnection) new URL("https://" + getServerName().replaceFirst("^www.", "api.") + "/account/certs/new").openConnection();
+ authenticateClientCert(pk, ce, connection);
+ connection.setDoOutput(true);
+ OutputStream os = connection.getOutputStream();
+ os.write(("csr=" + URLEncoder.encode(generatePEMCSR(kp, "CN=a b"), "UTF-8")).getBytes());
+ os.flush();
+ assertEquals(connection.getResponseCode(), 200);
+ String cert = IOUtils.readURL(new InputStreamReader(connection.getInputStream(), "UTF-8"));
+ CertificateFactory cf = CertificateFactory.getInstance("X509");
+ Collection<? extends java.security.cert.Certificate> certs = cf.generateCertificates(new ByteArrayInputStream(cert.getBytes()));
+ assertEquals("a b", ((X500Name) ((X509Certificate) certs.iterator().next()).getSubjectDN()).getCommonName());
+ }
+}
String[] res = fillOutForm("CSR=" + URLEncoder.encode(pem, "UTF-8"));
assertArrayEquals(new String[] {
- "mail", "a b", "dns:a." + uniq + ".tld\ndns:b." + uniq + ".tld\nemail:" + email + "\n", Digest.SHA384.toString()
+ "mail", "a b", "email:" + email + "\ndns:a." + uniq + ".tld\ndns:b." + uniq + ".tld\n", Digest.SHA384.toString()
}, res);
}
mainProps.setProperty("name.secure", testProps.getProperty("name.secure"));
mainProps.setProperty("name.www", testProps.getProperty("name.www"));
mainProps.setProperty("name.static", testProps.getProperty("name.static"));
+ mainProps.setProperty("name.api", testProps.getProperty("name.api"));
mainProps.setProperty("https.port", testProps.getProperty("serverPort.https"));
mainProps.setProperty("http.port", testProps.getProperty("serverPort.http"));