vars.put("ra-agent", u.canVerify());
vars.put("vp", u.getVerificationPoints());
vars.put("xp", u.getExperiencePoints());
-
+ if (u.isInGroup(Group.SUPPORTER) || u.isInGroup(Group.ORG_AGENT) || u.isInGroup(Group.TTP_AGENT) || u.canVerify()) {
+ vars.put("certlogin", LoginPage.getAuthorizationContext(req).isStronglyAuthenticated());
+ vars.put("certlogininfo", true);
+ } else {
+ vars.put("certlogininfo", false);
+ }
Certificate[] c = u.getCertificates(false);
vars.put("c-no", c.length);
<h3><?=_Welcome back, ${username}!?></h3>
<h4><?=_Subscriber information?></h4>
+
+<? if($certlogininfo) { ?>
+ <? if($certlogin) { ?>
+ <div class="card card-body bg-light">
+ <p><?=_You are authenticated via certificate, so you will be able to perform all actions.?></p>
+ </div>
+ <? } else { ?>
+ <div class="alert alert-warning" role="alert">
+ <p><?=_For some actions, e.g. add verification, support, you need to be authenticated via certificate.?></p>
+ </div>
+ <? } ?>
+<? } ?>
+
<div class="card card-body bg-light">
<? if($ra-agent) { ?><p><?=_You are an RA Agent.?></p><? } ?>
<p><?=_Assigned support permissions?>: <?=$support-groups?></p>
@Override
public boolean isPermitted(AuthorizationContext ac) {
- return ac != null && ac.isInGroup(Group.SUPPORTER);
+ return ac != null && ac.isInGroup(Group.SUPPORTER) && ac.isStronglyAuthenticated();
}
}
}
public boolean canSupport() {
- return getSupporterTicketId() != null && isInGroup(Group.SUPPORTER);
+ return getSupporterTicketId() != null && isInGroup(Group.SUPPORTER) && isStronglyAuthenticated();
}
private static final SprintfCommand sp = new SprintfCommand("Logged in as {0} via {1}.", Arrays.asList("${username", "${loginMethod"));
--- /dev/null
+package club.wpia.gigi.pages;
+
+import static org.hamcrest.CoreMatchers.*;
+import static org.junit.Assert.*;
+
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.security.GeneralSecurityException;
+import java.security.KeyPair;
+import java.security.PrivateKey;
+import java.security.cert.X509Certificate;
+
+import org.junit.Test;
+
+import club.wpia.gigi.GigiApiException;
+import club.wpia.gigi.dbObjects.Certificate;
+import club.wpia.gigi.dbObjects.Certificate.CSRType;
+import club.wpia.gigi.dbObjects.Digest;
+import club.wpia.gigi.testUtils.ClientTest;
+import club.wpia.gigi.testUtils.IOUtils;
+
+public class TestMain extends ClientTest {
+
+ @Test
+ public void testPasswordLogin() throws MalformedURLException, IOException {
+ URLConnection uc = new URL("https://" + getServerName()).openConnection();
+ uc.addRequestProperty("Cookie", cookie);
+ String content = IOUtils.readURL(uc);
+
+ assertThat(content, not(containsString("via certificate")));
+
+ makeAgent(u.getId());
+ uc = new URL("https://" + getServerName()).openConnection();
+ uc.addRequestProperty("Cookie", cookie);
+ content = IOUtils.readURL(uc);
+ assertThat(content, containsString("For some actions, e.g. add verification, support, you need to be authenticated via certificate."));
+
+ }
+
+ @Test
+ public void testCertLogin() throws GeneralSecurityException, IOException, GigiApiException, InterruptedException {
+ KeyPair kp = generateKeypair();
+ String csr = generatePEMCSR(kp, "CN=" + u.getPreferredName().toString());
+ Certificate c = new Certificate(u, u, Certificate.buildDN("CN", u.getPreferredName().toString()), Digest.SHA256, csr, CSRType.CSR, getClientProfile());
+ final PrivateKey pk = kp.getPrivate();
+ await(c.issue(null, "2y", u));
+ final X509Certificate ce = c.cert();
+ c.setLoginEnabled(true);
+ cookie = login(pk, ce);
+ loginCertificate = c;
+ loginPrivateKey = pk;
+
+ URLConnection uc = new URL("https://" + getSecureServerName()).openConnection();
+ authenticate((HttpURLConnection) uc);
+ String content = IOUtils.readURL(uc);
+ assertThat(content, not(containsString("via certificate")));
+
+ makeAgent(u.getId());
+ uc = new URL("https://" + getSecureServerName()).openConnection();
+ authenticate((HttpURLConnection) uc);
+ content = IOUtils.readURL(uc);
+ assertThat(content, containsString("You are authenticated via certificate, so you will be able to perform all actions."));
+
+ }
+}
// supporter removes supporter flag
URLConnection uc = post(SupportUserDetailsPage.PATH + u.getId() + "/", "removeGroup&groupToModify=" + URLEncoder.encode(Group.SUPPORTER.getDBName(), "UTF-8"));
- assertEquals("https://" + ServerConstants.getHostNamePortSecure(Host.WWW) + MyDetails.PATH, uc.getHeaderField("Location"));
+ assertEquals("https://" + ServerConstants.getHostNamePortSecure(Host.SECURE) + MyDetails.PATH, uc.getHeaderField("Location"));
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
Group.SUPPORTER.getName().output(pw, Language.getInstance(Locale.ENGLISH), new HashMap<String, Object>());
@Test
public void testSerialSearch() throws IOException {
URLConnection uc = post(cookie, FindCertPage.PATH, "certType=serial&process=Next&cert=" + c.getSerial(), 0);
- assertEquals("https://" + ServerConstants.getHostNamePortSecure(Host.WWW) + Certificates.SUPPORT_PATH + "/" + c.getSerial(), uc.getHeaderField("Location"));
+ assertEquals("https://" + ServerConstants.getHostNamePortSecure(Host.SECURE) + Certificates.SUPPORT_PATH + "/" + c.getSerial(), uc.getHeaderField("Location"));
}
@Test
public void testEmailSearch() throws IOException {
URLConnection uc = post(cookie, FindCertPage.PATH, "certType=email&process=Next&cert=" + URLEncoder.encode(certMail, "UTF-8"), 0);
- assertEquals("https://" + ServerConstants.getHostNamePortSecure(Host.WWW) + Certificates.SUPPORT_PATH + "/" + c.getSerial(), uc.getHeaderField("Location"));
+ assertEquals("https://" + ServerConstants.getHostNamePortSecure(Host.SECURE) + Certificates.SUPPORT_PATH + "/" + c.getSerial(), uc.getHeaderField("Location"));
}
@Test
@Test
public void testRevoke() throws IOException {
URLConnection conn = post(Certificates.SUPPORT_PATH + "/" + c.getSerial(), "action=revoke");
- assertEquals("https://" + ServerConstants.getHostNamePortSecure(Host.WWW) + Certificates.SUPPORT_PATH + "/" + c.getSerial(), conn.getHeaderField("Location"));
+ assertEquals("https://" + ServerConstants.getHostNamePortSecure(Host.SECURE) + Certificates.SUPPORT_PATH + "/" + c.getSerial(), conn.getHeaderField("Location"));
for (int i = 0; i < 2; i++) {
TestMail tm = getMailReceiver().receive(i == 0 ? ServerConstants.getSupportMailAddress() : certMail);
assertThat(tm.getMessage(), CoreMatchers.containsString(certMail));
import club.wpia.gigi.GigiApiException;
import club.wpia.gigi.database.GigiPreparedStatement;
+import club.wpia.gigi.dbObjects.Certificate;
import club.wpia.gigi.dbObjects.EmailAddress;
import club.wpia.gigi.dbObjects.ObjectCache;
import club.wpia.gigi.dbObjects.User;
public class TestSEAdminPageDetails extends SEClientTest {
- public TestSEAdminPageDetails() throws IOException, GigiApiException {}
+ private Certificate cs;
+
+ public TestSEAdminPageDetails() throws IOException, GigiApiException {
+ cs = loginCertificate;
+ }
@Test
public void testUserDetailsDisplay() throws MalformedURLException, IOException {
String clientCookie = login(email, TEST_PASSWORD);
// try to open mypoints as user
+ loginCertificate = null;
HttpURLConnection uc = get(clientCookie, SupportUserDetailsPage.PATH + id + "/points");
assertEquals(403, uc.getResponseCode());
// enter verification and open mypoints as supporter
-
+ loginCertificate = cs;
makeAgent(this.id);
String location = createUniqueName();
try (GigiPreparedStatement ps = new GigiPreparedStatement("INSERT INTO `notary` SET `from`=?, `to`=?, `points`=?, `location`=?, `date`=?, `when`=? ")) {
}
private int logCountUser(String cookie) throws IOException {
- return getLogEntryCount(IOUtils.readURL(get(cookie, History.PATH)));
+ loginCertificate = null;
+ int count = getLogEntryCount(IOUtils.readURL(get(cookie, History.PATH)));
+ loginCertificate = cs;
+ return count;
}
private int getLogEntryCount(String readURL) {
public void testDomainSearch() throws MalformedURLException, UnsupportedEncodingException, IOException, GigiApiException {
URLConnection uc = post(FindUserByDomainPage.PATH, "process&domain=" + URLEncoder.encode(domainName, "UTF-8"));
- assertEquals("https://" + ServerConstants.getHostNamePortSecure(Host.WWW) + SupportUserDetailsPage.PATH + tid + "/", uc.getHeaderField("Location"));
+ assertEquals("https://" + ServerConstants.getHostNamePortSecure(Host.SECURE) + SupportUserDetailsPage.PATH + tid + "/", uc.getHeaderField("Location"));
}
@Test
public void testDomainSearchById() throws MalformedURLException, UnsupportedEncodingException, IOException, GigiApiException {
URLConnection uc = post(FindUserByDomainPage.PATH, "process&domain=#" + d.getId());
- assertEquals("https://" + ServerConstants.getHostNamePortSecure(Host.WWW) + SupportUserDetailsPage.PATH + tid + "/", uc.getHeaderField("Location"));
+ assertEquals("https://" + ServerConstants.getHostNamePortSecure(Host.SECURE) + SupportUserDetailsPage.PATH + tid + "/", uc.getHeaderField("Location"));
}
@Test
// test
URLConnection uc = post(FindUserByDomainPage.PATH, "process&domain=" + URLEncoder.encode(dom, "UTF-8"));
- assertEquals("https://" + ServerConstants.getHostNamePortSecure(Host.WWW) + SupportOrgDomainPage.PATH + d.getId(), uc.getHeaderField("Location"));
+ assertEquals("https://" + ServerConstants.getHostNamePortSecure(Host.SECURE) + SupportOrgDomainPage.PATH + d.getId(), uc.getHeaderField("Location"));
String s = IOUtils.readURL(get(cookie, SupportOrgDomainPage.PATH + d.getId()));
assertThat(s, containsString(dom));
int id = createVerifiedUser("Först", "Secönd", mail, TEST_PASSWORD);
URLConnection uc = post(cookie, FindUserByEmailPage.PATH, "process&email=" + URLEncoder.encode(mail, "UTF-8"), 0);
- assertEquals("https://" + ServerConstants.getHostNamePortSecure(Host.WWW) + SupportUserDetailsPage.PATH + id + "/", uc.getHeaderField("Location"));
+ assertEquals("https://" + ServerConstants.getHostNamePortSecure(Host.SECURE) + SupportUserDetailsPage.PATH + id + "/", uc.getHeaderField("Location"));
}
@Test
int id = createVerifiedUser("Först", "Secönd", mail, TEST_PASSWORD);
URLConnection uc = post(cookie, FindUserByEmailPage.PATH, "process&email=" + URLEncoder.encode("%@example.tld", "UTF-8"), 0);
- assertEquals("https://" + ServerConstants.getHostNamePortSecure(Host.WWW) + SupportUserDetailsPage.PATH + id + "/", uc.getHeaderField("Location"));
+ assertEquals("https://" + ServerConstants.getHostNamePortSecure(Host.SECURE) + SupportUserDetailsPage.PATH + id + "/", uc.getHeaderField("Location"));
}
@Test
createVerifiedEmail(testuser, mail2);
URLConnection uc = post(cookie, FindUserByEmailPage.PATH, "process&email=" + URLEncoder.encode(mail2, "UTF-8"), 0);
- assertEquals("https://" + ServerConstants.getHostNamePortSecure(Host.WWW) + SupportUserDetailsPage.PATH + id + "/", uc.getHeaderField("Location"));
+ assertEquals("https://" + ServerConstants.getHostNamePortSecure(Host.SECURE) + SupportUserDetailsPage.PATH + id + "/", uc.getHeaderField("Location"));
}
@Test
createVerifiedEmail(testuser, mail3);
URLConnection uc = post(cookie, FindUserByEmailPage.PATH, "process&email=" + URLEncoder.encode("%@example3.org", "UTF-8"), 0);
- assertEquals("https://" + ServerConstants.getHostNamePortSecure(Host.WWW) + SupportUserDetailsPage.PATH + id + "/", uc.getHeaderField("Location"));
+ assertEquals("https://" + ServerConstants.getHostNamePortSecure(Host.SECURE) + SupportUserDetailsPage.PATH + id + "/", uc.getHeaderField("Location"));
uc = post(cookie, FindUserByEmailPage.PATH, "process&email=" + URLEncoder.encode("%@test3.org", "UTF-8"), 0);
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
+import java.security.GeneralSecurityException;
+import java.security.KeyPair;
+import java.security.PrivateKey;
+import java.security.cert.X509Certificate;
import java.util.Random;
import org.junit.Test;
import club.wpia.gigi.GigiApiException;
+import club.wpia.gigi.dbObjects.Certificate;
+import club.wpia.gigi.dbObjects.Certificate.CSRType;
+import club.wpia.gigi.dbObjects.Digest;
import club.wpia.gigi.dbObjects.Group;
+import club.wpia.gigi.pages.admin.support.FindCertPage;
import club.wpia.gigi.pages.admin.support.FindUserByDomainPage;
import club.wpia.gigi.pages.admin.support.FindUserByEmailPage;
import club.wpia.gigi.pages.admin.support.SupportEnterTicketForm;
public TestSEAdminTicketSetting() throws IOException, GigiApiException {
grant(u, Group.SUPPORTER);
- cookie = login(email, TEST_PASSWORD);
+ try {
+ KeyPair kp = generateKeypair();
+ String csr = generatePEMCSR(kp, "CN=" + u.getPreferredName().toString());
+ Certificate c = new Certificate(u, u, Certificate.buildDN("CN", u.getPreferredName().toString()), Digest.SHA256, csr, CSRType.CSR, getClientProfile());
+ final PrivateKey pk = kp.getPrivate();
+ await(c.issue(null, "2y", u));
+ final X509Certificate ce = c.cert();
+ c.setLoginEnabled(true);
+ cookie = login(pk, ce);
+ loginCertificate = c;
+ loginPrivateKey = pk;
+ } catch (InterruptedException e) {
+ throw new GigiApiException(e.toString());
+ } catch (GeneralSecurityException e) {
+ throw new GigiApiException(e.toString());
+ }
}
@Test
public void testFulltextMailSearch() throws MalformedURLException, UnsupportedEncodingException, IOException {
assertEquals(403, get(FindUserByEmailPage.PATH).getResponseCode());
- assertEquals(302, post(cookie, SupportEnterTicketPage.PATH, "ticketno=a20140808.8&setTicket=action", 0).getResponseCode());
+ assertEquals(302, post(SupportEnterTicketPage.PATH, "ticketno=a20140808.8&setTicket=action", 0).getResponseCode());
assertEquals(200, get(FindUserByEmailPage.PATH).getResponseCode());
assertEquals(200, get(FindUserByDomainPage.PATH).getResponseCode());
- assertEquals(302, post(cookie, SupportEnterTicketPage.PATH, "ticketno=a20140808.8&deleteTicket=action", 0).getResponseCode());
+ assertEquals(302, post(SupportEnterTicketPage.PATH, "ticketno=a20140808.8&deleteTicket=action", 0).getResponseCode());
assertEquals(403, get(FindUserByEmailPage.PATH).getResponseCode());
}
// test allowed character
for (char ch : SupportEnterTicketForm.TICKET_PREFIX.toCharArray()) {
ticket = ch + "20171212.1";
- assertEquals(302, post(cookie, SupportEnterTicketPage.PATH, "ticketno=" + ticket + "&setTicket=action", 0).getResponseCode());
+ assertEquals(302, post(SupportEnterTicketPage.PATH, "ticketno=" + ticket + "&setTicket=action", 0).getResponseCode());
ticket = Character.toUpperCase(ch) + "20171212.1";
- assertEquals(302, post(cookie, SupportEnterTicketPage.PATH, "ticketno=" + ticket + "&setTicket=action", 0).getResponseCode());
+ assertEquals(302, post(SupportEnterTicketPage.PATH, "ticketno=" + ticket + "&setTicket=action", 0).getResponseCode());
alphabet = alphabet.replaceAll(Character.toString(ch), "");
}
String res = IOUtils.readURL(post(SupportEnterTicketPage.PATH, "ticketno=" + ticket + "&setTicket=action"));
assertThat(res, containsString("Ticket format malformed"));
}
+
+ @Test
+ public void testPWLogin() throws MalformedURLException, UnsupportedEncodingException, IOException {
+ String cookiePW = login(email, TEST_PASSWORD);
+ loginCertificate = null;
+ assertEquals(403, get(cookiePW, SupportEnterTicketPage.PATH).getResponseCode());
+ assertEquals(403, get(cookiePW, FindUserByEmailPage.PATH).getResponseCode());
+ assertEquals(403, get(cookiePW, FindUserByDomainPage.PATH).getResponseCode());
+ assertEquals(403, get(cookiePW, FindCertPage.PATH).getResponseCode());
+ }
+
}
package club.wpia.gigi.testUtils;
import java.io.IOException;
+import java.io.OutputStream;
import java.net.HttpURLConnection;
+import java.net.URL;
+import java.net.URLConnection;
+import java.net.URLEncoder;
+import java.security.GeneralSecurityException;
+import club.wpia.gigi.GigiApiException;
import club.wpia.gigi.dbObjects.User;
/**
}
public HttpURLConnection post(String path, String query, int formIndex) throws IOException {
- return post(cookie, path, query, formIndex);
+ String server = getServerName();
+ if (loginCertificate != null) {
+ server = getSecureServerName();
+ }
+ URLConnection uc = new URL("https://" + server + path).openConnection();
+ authenticate((HttpURLConnection) uc);
+ String csrf = getCSRF(uc, formIndex);
+
+ uc = new URL("https://" + server + path).openConnection();
+ authenticate((HttpURLConnection) uc);
+ uc.setDoOutput(true);
+ OutputStream os = uc.getOutputStream();
+ os.write(("csrf=" + URLEncoder.encode(csrf, "UTF-8") + "&" //
+ + query//
+ ).getBytes("UTF-8"));
+ os.flush();
+ return (HttpURLConnection) uc;
}
public HttpURLConnection get(String path) throws IOException {
- return get(cookie, path);
+ String server = getServerName();
+ if (loginCertificate != null) {
+ server = getSecureServerName();
+ }
+ URLConnection uc = new URL("https://" + server + path).openConnection();
+ authenticate((HttpURLConnection) uc);
+ return (HttpURLConnection) uc;
+ }
+
+ protected void authenticate(HttpURLConnection uc) throws IOException {
+ uc.addRequestProperty("Cookie", cookie);
+ if (loginCertificate != null) {
+ try {
+ authenticateClientCert(loginPrivateKey, loginCertificate.cert(), uc);
+ } catch (GeneralSecurityException | GigiApiException e) {
+ throw new IOException(e);
+ }
+ }
}
}
import java.net.URLEncoder;
import java.nio.file.Files;
import java.nio.file.Paths;
+import java.security.GeneralSecurityException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.Principal;
import club.wpia.gigi.GigiApiException;
import club.wpia.gigi.database.GigiPreparedStatement;
import club.wpia.gigi.database.GigiResultSet;
+import club.wpia.gigi.dbObjects.Certificate;
import club.wpia.gigi.dbObjects.EmailAddress;
import club.wpia.gigi.dbObjects.Group;
import club.wpia.gigi.dbObjects.Job;
private static String acceptLanguage = null;
+ protected static Certificate loginCertificate;
+
+ protected static PrivateKey loginPrivateKey;
+
public static void setAcceptLanguage(String acceptLanguage) {
ManagedTest.acceptLanguage = acceptLanguage;
}
}
public static HttpURLConnection post(String cookie, String path, String query, int formIndex) throws IOException, MalformedURLException, UnsupportedEncodingException {
- URLConnection uc = new URL("https://" + getServerName() + path).openConnection();
- uc.addRequestProperty("Cookie", cookie);
+ String server = getServerName();
+ if (loginCertificate != null) {
+ server = getSecureServerName();
+ }
+ URLConnection uc = new URL("https://" + server + path).openConnection();
+ authenticate((HttpURLConnection) uc, cookie);
String csrf = getCSRF(uc, formIndex);
- uc = new URL("https://" + getServerName() + path).openConnection();
- uc.addRequestProperty("Cookie", cookie);
+ uc = new URL("https://" + server + path).openConnection();
+ authenticate((HttpURLConnection) uc, cookie);
uc.setDoOutput(true);
OutputStream os = uc.getOutputStream();
os.write(("csrf=" + URLEncoder.encode(csrf, "UTF-8") + "&" //
}
public static HttpURLConnection get(String cookie, String path) throws IOException {
- URLConnection uc = new URL("https://" + getServerName() + path).openConnection();
- uc.addRequestProperty("Cookie", cookie);
+ String server = getServerName();
+ if (loginCertificate != null) {
+ server = getSecureServerName();
+ }
+ URLConnection uc = new URL("https://" + server + path).openConnection();
+ authenticate((HttpURLConnection) uc, cookie);
return (HttpURLConnection) uc;
}
supporter = User.getById(i);
return supporter;
}
+
+ protected static void authenticate(HttpURLConnection uc, String cookie) throws IOException {
+ uc.addRequestProperty("Cookie", cookie);
+ if (loginCertificate != null) {
+ try {
+ authenticateClientCert(loginPrivateKey, loginCertificate.cert(), uc);
+ } catch (GeneralSecurityException | GigiApiException e) {
+ throw new IOException(e);
+ }
+ }
+ }
}
import static org.junit.Assert.*;
import java.io.IOException;
+import java.security.GeneralSecurityException;
+import java.security.KeyPair;
+import java.security.PrivateKey;
+import java.security.cert.X509Certificate;
import club.wpia.gigi.GigiApiException;
+import club.wpia.gigi.dbObjects.Certificate;
+import club.wpia.gigi.dbObjects.Certificate.CSRType;
+import club.wpia.gigi.dbObjects.Digest;
import club.wpia.gigi.dbObjects.Group;
import club.wpia.gigi.pages.admin.support.SupportEnterTicketPage;
public SEClientTest() throws IOException, GigiApiException {
grant(u, Group.SUPPORTER);
- cookie = login(email, TEST_PASSWORD);
+ try {
+ KeyPair kp = generateKeypair();
+ String csr = generatePEMCSR(kp, "CN=" + u.getPreferredName().toString());
+ Certificate c = new Certificate(u, u, Certificate.buildDN("CN", u.getPreferredName().toString()), Digest.SHA256, csr, CSRType.CSR, getClientProfile());
+ final PrivateKey pk = kp.getPrivate();
+ await(c.issue(null, "2y", u));
+ final X509Certificate ce = c.cert();
+ c.setLoginEnabled(true);
+ loginCertificate = c;
+ loginPrivateKey = pk;
+ cookie = login(pk, ce);
+ } catch (InterruptedException e) {
+ throw new GigiApiException(e.toString());
+ } catch (GeneralSecurityException e) {
+ throw new GigiApiException(e.toString());
+ }
assertEquals(302, post(cookie, SupportEnterTicketPage.PATH, "ticketno=a20140808.8&setTicket=action", 0).getResponseCode());
}