certificate backend

This commit is contained in:
Zlatin Balevsky
2019-12-09 14:26:39 +00:00
parent 3b1349b643
commit 42c48a8e37
7 changed files with 267 additions and 7 deletions

View File

@ -10,17 +10,20 @@ import net.i2p.crypto.DSAEngine
import net.i2p.data.Signature import net.i2p.data.Signature
import net.i2p.data.SigningPrivateKey import net.i2p.data.SigningPrivateKey
import net.i2p.data.SigningPublicKey import net.i2p.data.SigningPublicKey
import net.i2p.data.Base64
class Certificate { class Certificate {
private final byte version private final byte version
private final InfoHash infoHash private final InfoHash infoHash
private final Name name, comment final Name name, comment
private final long timestamp final long timestamp
private final Persona issuer final Persona issuer
private final byte[] sig private final byte[] sig
private volatile byte [] payload private volatile byte [] payload
private String base64;
Certificate(InputStream is) { Certificate(InputStream is) {
version = (byte) (is.read() & 0xFF) version = (byte) (is.read() & 0xFF)
if (version > Constants.FILE_CERT_VERSION) if (version > Constants.FILE_CERT_VERSION)
@ -131,6 +134,15 @@ class Certificate {
os.write(payload) os.write(payload)
} }
public String toBase64() {
if (base64 == null) {
ByteArrayOutputStream baos = new ByteArrayOutputStream()
write(baos)
base64 = Base64.encode(baos.toByteArray())
}
return base64;
}
@Override @Override
public int hashCode() { public int hashCode() {
version.hashCode() ^ infoHash.hashCode() ^ timestamp.hashCode() ^ name.hashCode() ^ issuer.hashCode() ^ Objects.hashCode(comment) version.hashCode() ^ infoHash.hashCode() ^ timestamp.hashCode() ^ name.hashCode() ^ issuer.hashCode() ^ Objects.hashCode(comment)

View File

@ -32,7 +32,8 @@ class CertificateClient {
fetcherThread.execute({ fetcherThread.execute({
Endpoint endpoint = null Endpoint endpoint = null
try { try {
eventBus.publish(new CertificateFetchEvent(status : CertificateFetchStatus.CONNECTING)) eventBus.publish(new CertificateFetchEvent(status : CertificateFetchStatus.CONNECTING,
user : e.host, infoHash : e.infoHash))
endpoint = connector.connect(e.host.destination) endpoint = connector.connect(e.host.destination)
String infoHashString = Base64.encode(e.infoHash.getRoot()) String infoHashString = Base64.encode(e.infoHash.getRoot())
@ -62,7 +63,8 @@ class CertificateClient {
int count = Integer.parseInt(headers['Count']) int count = Integer.parseInt(headers['Count'])
// start pulling the certs // start pulling the certs
eventBus.publish(new CertificateFetchEvent(status : CertificateFetchStatus.FETCHING, count : count)) eventBus.publish(new CertificateFetchEvent(status : CertificateFetchStatus.FETCHING, count : count,
user : e.host, infoHash : e.infoHash))
DataInputStream dis = new DataInputStream(is) DataInputStream dis = new DataInputStream(is)
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
@ -77,11 +79,14 @@ class CertificateClient {
continue continue
} }
if (cert.infoHash == e.infoHash) if (cert.infoHash == e.infoHash)
eventBus.publish(new CertificateFetchedEvent(certificate : cert)) eventBus.publish(new CertificateFetchedEvent(certificate : cert, user : e.host, infoHash : e.infoHash))
} }
eventBus.publish(new CertificateFetchEvent(status : CertificateFetchStatus.DONE, count : count,
user : e.host, infoHash : e.infoHash))
} catch (Exception bad) { } catch (Exception bad) {
log.log(Level.WARNING,"Fetching certificates failed", bad) log.log(Level.WARNING,"Fetching certificates failed", bad)
eventBus.publish(new CertificateFetchEvent(status : CertificateFetchStatus.FAILED)) eventBus.publish(new CertificateFetchEvent(status : CertificateFetchStatus.FAILED,
user : e.host, infoHash : e.infoHash))
} finally { } finally {
endpoint?.close() endpoint?.close()
} }

View File

@ -1,8 +1,12 @@
package com.muwire.core.filecert package com.muwire.core.filecert
import com.muwire.core.Event import com.muwire.core.Event
import com.muwire.core.InfoHash
import com.muwire.core.Persona
class CertificateFetchEvent extends Event { class CertificateFetchEvent extends Event {
CertificateFetchStatus status CertificateFetchStatus status
int count int count
Persona user
InfoHash infoHash
} }

View File

@ -1,7 +1,11 @@
package com.muwire.core.filecert package com.muwire.core.filecert
import com.muwire.core.Event import com.muwire.core.Event
import com.muwire.core.InfoHash
import com.muwire.core.Persona
class CertificateFetchedEvent extends Event { class CertificateFetchedEvent extends Event {
Certificate certificate Certificate certificate
Persona user
InfoHash infoHash
} }

View File

@ -0,0 +1,101 @@
package com.muwire.webui;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import com.muwire.core.Core;
import com.muwire.core.InfoHash;
import com.muwire.core.Persona;
import com.muwire.core.filecert.Certificate;
import com.muwire.core.filecert.CertificateFetchEvent;
import com.muwire.core.filecert.CertificateFetchStatus;
import com.muwire.core.filecert.CertificateFetchedEvent;
import com.muwire.core.filecert.UIFetchCertificatesEvent;
import com.muwire.core.filecert.UIImportCertificateEvent;
public class CertificateManager {
private final Core core;
private final Map<Persona, Map<InfoHash,CertificateRequest>> requests = new ConcurrentHashMap<>();
public CertificateManager(Core core) {
this.core = core;
}
public void onCertificateFetchEvent(CertificateFetchEvent e) {
Map<InfoHash, CertificateRequest> map = requests.get(e.getUser());
if (map == null)
return;
CertificateRequest request = map.get(e.getInfoHash());
if (request == null)
return;
request.status = e.getStatus();
if (request.status == CertificateFetchStatus.FETCHING)
request.totalCertificates = e.getCount();
}
public void onCertificateFetchedEvent(CertificateFetchedEvent e) {
Map<InfoHash, CertificateRequest> map = requests.get(e.getUser());
if (map == null)
return;
CertificateRequest request = map.get(e.getInfoHash());
if (request == null)
return;
request.certificates.add(e.getCertificate());
}
void request(Persona user, InfoHash infoHash) {
CertificateRequest request = new CertificateRequest(user, infoHash);
Map<InfoHash, CertificateRequest> requestsFromUser = requests.get(user);
if (requestsFromUser == null) {
requestsFromUser = new ConcurrentHashMap<>();
requests.put(user, requestsFromUser);
}
requestsFromUser.put(infoHash, request);
UIFetchCertificatesEvent event = new UIFetchCertificatesEvent();
event.setHost(user);
event.setInfoHash(infoHash);
core.getEventBus().publish(event);
}
CertificateRequest get(Persona user, InfoHash infoHash) {
Map<InfoHash, CertificateRequest> map = requests.get(user);
if (map == null)
return null;
return map.get(infoHash);
}
void importCertificate(Certificate certificate) {
UIImportCertificateEvent event = new UIImportCertificateEvent();
event.setCertificate(certificate);
core.getEventBus().publish(event);
}
static class CertificateRequest {
private final Persona user;
private final InfoHash infoHash;
private volatile CertificateFetchStatus status;
private volatile int totalCertificates;
private Set<Certificate> certificates;
CertificateRequest(Persona user, InfoHash infoHash) {
this.user = user;
this.infoHash = infoHash;
}
CertificateFetchStatus getStatus() {
return status;
}
int totalCertificates() {
return totalCertificates;
}
Set<Certificate> getCertificates() {
return certificates;
}
}
}

View File

@ -0,0 +1,127 @@
package com.muwire.webui;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.muwire.core.InfoHash;
import com.muwire.core.Persona;
import com.muwire.core.filecert.Certificate;
import com.muwire.webui.CertificateManager.CertificateRequest;
import net.i2p.data.Base64;
import net.i2p.data.DataHelper;
public class CertificateServlet extends HttpServlet {
private CertificateManager certificateManager;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String userB64 = req.getParameter("user");
Persona user;
try {
user = new Persona(new ByteArrayInputStream(Base64.decode(userB64)));
} catch (Exception bad) {
resp.sendError(403, "Bad param");
return;
}
String infoHashB64 = req.getParameter("infoHash");
InfoHash infoHash;
try {
infoHash = new InfoHash(Base64.decode(infoHashB64));
} catch (Exception bad) {
resp.sendError(403, "Bad param");
return;
}
CertificateRequest request = certificateManager.get(user, infoHash);
if (request == null) {
resp.sendError(404,"Not found");
return;
}
StringBuilder sb = new StringBuilder();
sb.append("<?xml version='1.0' encoding='UTF-8'?>");
sb.append("<CertificateRequest>");
sb.append("<Status>").append(request.getStatus().toString()).append("</Status>");
sb.append("<Total>").append(request.totalCertificates()).append("</Total>");
sb.append("<Certificates>");
for (Certificate certificate : request.getCertificates()) {
sb.append("<Certificate>");
sb.append("<Issuer>").append(certificate.getIssuer().getHumanReadableName()).append("</Issuer>");
sb.append("<Name>").append(Util.escapeHTMLinXML(certificate.getName().getName())).append("</Name>");
if (certificate.getComment() != null)
sb.append("<Comment>").append(Util.escapeHTMLinXML(certificate.getComment().getName())).append("</Comment>");
sb.append("<Timestamp>").append(DataHelper.formatTime(certificate.getTimestamp())).append("</Timestamp>");
sb.append("<Base64>").append(certificate.toBase64()).append("</Base64>");
sb.append("</Certificate>");
}
sb.append("</Certificates>");
sb.append("</CertificateRequest>");
resp.setContentType("text/xml");
resp.setCharacterEncoding("UTF-8");
resp.setDateHeader("Expires", 0);
resp.setHeader("Pragma", "no-cache");
resp.setHeader("Cache-Control", "no-store, max-age=0, no-cache, must-revalidate");
byte[] out = sb.toString().getBytes("UTF-8");
resp.setContentLength(out.length);
resp.getOutputStream().write(out);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String action = req.getParameter("action");
if (action == null) {
resp.sendError(403, "Bad param");
return;
}
if (action.equals("fetch")) {
String userB64 = req.getParameter("user");
Persona user;
try {
user = new Persona(new ByteArrayInputStream(Base64.decode(userB64)));
} catch (Exception bad) {
resp.sendError(403, "Bad param");
return;
}
String infoHashB64 = req.getParameter("infoHash");
InfoHash infoHash;
try {
infoHash = new InfoHash(Base64.decode(infoHashB64));
} catch (Exception bad) {
resp.sendError(403, "Bad param");
return;
}
certificateManager.request(user, infoHash);
} else if (action.equals("import")) {
String certB64 = req.getParameter("base64");
Certificate certificate;
try {
certificate = new Certificate(new ByteArrayInputStream(Base64.decode(certB64)));
} catch (Exception bad) {
resp.sendError(403, "Bad param");
return;
}
certificateManager.importCertificate(certificate);
}
}
@Override
public void init(ServletConfig config) throws ServletException {
certificateManager = (CertificateManager) config.getServletContext().getAttribute("certificateManager");
}
}

View File

@ -22,6 +22,8 @@ import com.muwire.core.UILoadedEvent;
import com.muwire.core.connection.ConnectionEvent; import com.muwire.core.connection.ConnectionEvent;
import com.muwire.core.connection.DisconnectionEvent; import com.muwire.core.connection.DisconnectionEvent;
import com.muwire.core.download.DownloadStartedEvent; import com.muwire.core.download.DownloadStartedEvent;
import com.muwire.core.filecert.CertificateFetchEvent;
import com.muwire.core.filecert.CertificateFetchedEvent;
import com.muwire.core.files.AllFilesLoadedEvent; import com.muwire.core.files.AllFilesLoadedEvent;
import com.muwire.core.files.FileDownloadedEvent; import com.muwire.core.files.FileDownloadedEvent;
import com.muwire.core.files.FileHashedEvent; import com.muwire.core.files.FileHashedEvent;
@ -148,12 +150,17 @@ public class MuWireClient {
TrustManager trustManager = new TrustManager(); TrustManager trustManager = new TrustManager();
core.getEventBus().register(TrustEvent.class, trustManager); core.getEventBus().register(TrustEvent.class, trustManager);
CertificateManager certificateManager = new CertificateManager(core);
core.getEventBus().register(CertificateFetchedEvent.class, certificateManager);
core.getEventBus().register(CertificateFetchEvent.class, certificateManager);
servletContext.setAttribute("searchManager", searchManager); servletContext.setAttribute("searchManager", searchManager);
servletContext.setAttribute("downloadManager", downloadManager); servletContext.setAttribute("downloadManager", downloadManager);
servletContext.setAttribute("connectionCounter", connectionCounter); servletContext.setAttribute("connectionCounter", connectionCounter);
servletContext.setAttribute("fileManager", fileManager); servletContext.setAttribute("fileManager", fileManager);
servletContext.setAttribute("browseManager", browseManager); servletContext.setAttribute("browseManager", browseManager);
servletContext.setAttribute("trustManager", trustManager); servletContext.setAttribute("trustManager", trustManager);
servletContext.setAttribute("certificateManager", certificateManager);
core.getEventBus().publish(new UILoadedEvent()); core.getEventBus().publish(new UILoadedEvent());
} }