forked from I2P_Developers/i2p.i2p
Crypto: New utils to support private key import/export
Console: New /configfamily, /exportfamily
This commit is contained in:
@ -0,0 +1,109 @@
|
||||
package net.i2p.router.web;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import net.i2p.crypto.CertUtil;
|
||||
import net.i2p.crypto.KeyStoreUtil;
|
||||
import net.i2p.router.crypto.FamilyKeyCrypto;
|
||||
import net.i2p.util.SecureDirectory;
|
||||
|
||||
/**
|
||||
* @since 0.9.25
|
||||
*/
|
||||
public class ConfigFamilyHandler extends FormHandler {
|
||||
|
||||
@Override
|
||||
protected void processForm() {
|
||||
|
||||
if (_action.equals(_t("Create Router Family"))) {
|
||||
String family = getJettyString("family");
|
||||
String old = _context.getProperty(FamilyKeyCrypto.PROP_FAMILY_NAME);
|
||||
if (family == null || family.trim().length() <= 0) {
|
||||
addFormError(_t("You must enter a family name"));
|
||||
} else if (old != null) {
|
||||
addFormError("Family already configured: " + family);
|
||||
} else if (family.contains("/") || family.contains("\\")) {
|
||||
addFormError("Bad characters in Family: " + family);
|
||||
} else if (_context.router().saveConfig(FamilyKeyCrypto.PROP_FAMILY_NAME, family.trim())) {
|
||||
addFormNotice(_t("Configuration saved successfully."));
|
||||
addFormError(_t("Restart required to take effect"));
|
||||
} else {
|
||||
addFormError(_t("Error saving the configuration (applied but not saved) - please see the error logs"));
|
||||
}
|
||||
} else if (_action.equals(_t("Join Router Family"))) {
|
||||
InputStream in = _requestWrapper.getInputStream("file");
|
||||
try {
|
||||
// non-null but zero bytes if no file entered, don't know why
|
||||
if (in == null || in.available() <= 0) {
|
||||
addFormError(_t("You must enter a file"));
|
||||
return;
|
||||
}
|
||||
// load data
|
||||
PrivateKey pk = CertUtil.loadPrivateKey(in);
|
||||
List<X509Certificate> certs = CertUtil.loadCerts(in);
|
||||
String family = CertUtil.getSubjectValue(certs.get(0), "CN");
|
||||
if (family == null) {
|
||||
addFormError("Bad certificate - No Subject CN");
|
||||
}
|
||||
if (family.endsWith(FamilyKeyCrypto.CN_SUFFIX) && family.length() > FamilyKeyCrypto.CN_SUFFIX.length())
|
||||
family = family.substring(0, family.length() - FamilyKeyCrypto.CN_SUFFIX.length());
|
||||
// store to keystore
|
||||
File ks = new SecureDirectory(_context.getConfigDir(), "keystore");
|
||||
if (!ks.exists());
|
||||
ks.mkdirs();
|
||||
ks = new File(ks, FamilyKeyCrypto.KEYSTORE_PREFIX + family + FamilyKeyCrypto.KEYSTORE_SUFFIX);
|
||||
String keypw = KeyStoreUtil.randomString();
|
||||
KeyStoreUtil.storePrivateKey(ks, KeyStoreUtil.DEFAULT_KEYSTORE_PASSWORD, family, keypw, pk, certs);
|
||||
// store certificate
|
||||
File cf = new SecureDirectory(_context.getConfigDir(), "certificates");
|
||||
if (!cf.exists());
|
||||
cf.mkdirs();
|
||||
cf = new SecureDirectory(cf, "family");
|
||||
if (!ks.exists());
|
||||
ks.mkdirs();
|
||||
cf = new File(cf, family + FamilyKeyCrypto.CERT_SUFFIX);
|
||||
// ignore failure
|
||||
KeyStoreUtil.exportCert(ks, KeyStoreUtil.DEFAULT_KEYSTORE_PASSWORD, family, cf);
|
||||
// save config
|
||||
Map<String, String> changes = new HashMap<String, String>();
|
||||
changes.put(FamilyKeyCrypto.PROP_FAMILY_NAME, family);
|
||||
changes.put(FamilyKeyCrypto.PROP_KEY_PASSWORD, keypw);
|
||||
changes.put(FamilyKeyCrypto.PROP_KEYSTORE_PASSWORD, KeyStoreUtil.DEFAULT_KEYSTORE_PASSWORD);
|
||||
if (_context.router().saveConfig(changes, null)) {
|
||||
addFormNotice("Family key configured for router family: " + family);
|
||||
addFormError(_t("Restart required to take effect"));
|
||||
} else {
|
||||
addFormError(_t("Error saving the configuration (applied but not saved) - please see the error logs"));
|
||||
}
|
||||
} catch (GeneralSecurityException gse) {
|
||||
addFormError(_t("Load from file failed") + " - " + gse);
|
||||
} catch (IOException ioe) {
|
||||
addFormError(_t("Load from file failed") + " - " + ioe);
|
||||
} finally {
|
||||
// it's really a ByteArrayInputStream but we'll play along...
|
||||
try { in.close(); } catch (IOException ioe) {}
|
||||
}
|
||||
} else if (_action.equals(_t("Leave Router Family"))) {
|
||||
List<String> removes = new ArrayList<String>();
|
||||
removes.add(FamilyKeyCrypto.PROP_FAMILY_NAME);
|
||||
removes.add(FamilyKeyCrypto.PROP_KEY_PASSWORD);
|
||||
removes.add(FamilyKeyCrypto.PROP_KEYSTORE_PASSWORD);
|
||||
if (_context.router().saveConfig(null, removes)) {
|
||||
addFormNotice(_t("Configuration saved successfully."));
|
||||
addFormError(_t("Restart required to take effect"));
|
||||
} else {
|
||||
addFormError(_t("Error saving the configuration (applied but not saved) - please see the error logs"));
|
||||
}
|
||||
}
|
||||
//addFormError(_t("Unsupported") + ' ' + _action + '.');
|
||||
}
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
package net.i2p.router.web;
|
||||
|
||||
import net.i2p.router.crypto.FamilyKeyCrypto;
|
||||
|
||||
/**
|
||||
* @since 0.9.25
|
||||
*/
|
||||
public class ConfigFamilyHelper extends HelperBase {
|
||||
|
||||
public String getFamily() {
|
||||
return _context.getProperty(FamilyKeyCrypto.PROP_FAMILY_NAME, "");
|
||||
}
|
||||
|
||||
public String getKeyPW() {
|
||||
return _context.getProperty(FamilyKeyCrypto.PROP_KEY_PASSWORD, "");
|
||||
}
|
||||
}
|
@ -19,13 +19,13 @@ public class ConfigNavHelper extends HelperBase {
|
||||
private static final String pages[] =
|
||||
{"", "net", "ui", "sidebar", "home", "service", "update", "tunnels",
|
||||
"clients", "peer", "keyring", "logging", "stats",
|
||||
"reseed", "advanced" };
|
||||
"reseed", "advanced", "family" };
|
||||
|
||||
private static final String titles[] =
|
||||
{_x("Bandwidth"), _x("Network"), _x("UI"), _x("Summary Bar"), _x("Home Page"),
|
||||
_x("Service"), _x("Update"), _x("Tunnels"),
|
||||
_x("Clients"), _x("Peers"), _x("Keyring"), _x("Logging"), _x("Stats"),
|
||||
_x("Reseeding"), _x("Advanced") };
|
||||
_x("Reseeding"), _x("Advanced"), _x("Router Family") };
|
||||
|
||||
/** @since 0.9.19 */
|
||||
private static class Tab {
|
||||
|
Reference in New Issue
Block a user