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 New 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 Existing 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 + '.');
}
}