Search in sources :

Example 11 with SecureDirectory

use of net.i2p.util.SecureDirectory in project i2p.i2p by i2p.

the class WebAppStarter method startWebApp.

/**
 *  Adds and starts.
 *  Prior to 0.9.28, was not guaranteed to throw on failure.
 *  Not for routerconsole.war, it's started in RouterConsoleRunner.
 *
 *  @throws Exception just about anything, caller would be wise to catch Throwable
 *  @since public since 0.9.33, was package private
 */
public static void startWebApp(RouterContext ctx, ContextHandlerCollection server, String appName, String warPath) throws Exception {
    File tmpdir = new SecureDirectory(ctx.getTempDir(), "jetty-work-" + appName + ctx.random().nextInt());
    WebAppContext wac = addWebApp(ctx, server, appName, warPath, tmpdir);
    // _log.debug("Loading war from: " + warPath);
    LocaleWebAppHandler.setInitParams(wac, INIT_PARAMS);
    // default false, set to true so we get good logging,
    // and the caller will know it failed
    wac.setThrowUnavailableOnStartupException(true);
    wac.start();
    // Doesn't have to be right, just for presence indication
    int port = ctx.portMapper().getPort(PortMapper.SVC_CONSOLE, PortMapper.DEFAULT_CONSOLE_PORT);
    String host = ctx.portMapper().getActualHost(PortMapper.SVC_CONSOLE, "127.0.0.1");
    ctx.portMapper().register(appName, host, port);
}
Also used : WebAppContext(org.eclipse.jetty.webapp.WebAppContext) SecureDirectory(net.i2p.util.SecureDirectory) File(java.io.File)

Example 12 with SecureDirectory

use of net.i2p.util.SecureDirectory in project i2p.i2p by i2p.

the class WebAppStarter method addWebApp.

/**
 *  add but don't start
 *  This is used only by RouterConsoleRunner, which adds all the webapps first
 *  and then starts all at once.
 */
static WebAppContext addWebApp(RouterContext ctx, ContextHandlerCollection server, String appName, String warPath, File tmpdir) throws IOException {
    // the first one, so we remove any previous one here
    try {
        stopWebApp(ctx, appName);
    } catch (Throwable t) {
    }
    // To avoid ZipErrors from JarURLConnetion caching,
    // (used by Jetty JarResource and JarFileResource)
    // copy the war to a new directory if it is newer than the one we loaded originally.
    // Yes, URLConnection has a setDefaultUseCaches() method, but it's hard to get to
    // because it's non-static and the class is abstract, and we don't really want to
    // set the default to false for everything.
    long newmod = (new File(warPath)).lastModified();
    if (newmod <= 0)
        throw new IOException("Web app " + warPath + " does not exist");
    Long oldmod = warModTimes.get(warPath);
    if (oldmod == null) {
        warModTimes.put(warPath, Long.valueOf(newmod));
    } else if (oldmod.longValue() < newmod) {
        // copy war to temporary directory
        File warTmpDir = new SecureDirectory(ctx.getTempDir(), "war-copy-" + appName + ctx.random().nextInt());
        warTmpDir.mkdir();
        String tmpPath = (new File(warTmpDir, appName + ".war")).getAbsolutePath();
        if (!FileUtil.copy(warPath, tmpPath, true))
            throw new IOException("Web app failed copy from " + warPath + " to " + tmpPath);
        warPath = tmpPath;
    }
    WebAppContext wac = new WebAppContext(warPath, "/" + appName);
    tmpdir.mkdir();
    wac.setTempDirectory(tmpdir);
    // all the JSPs are precompiled, no need to extract
    wac.setExtractWAR(false);
    // this does the passwords...
    RouterConsoleRunner.initialize(ctx, wac);
    setWebAppConfiguration(wac);
    server.addHandler(wac);
    server.mapContexts();
    return wac;
}
Also used : WebAppContext(org.eclipse.jetty.webapp.WebAppContext) SecureDirectory(net.i2p.util.SecureDirectory) IOException(java.io.IOException) File(java.io.File)

Example 13 with SecureDirectory

use of net.i2p.util.SecureDirectory in project i2p.i2p by i2p.

the class ConfigFamilyHandler method processForm.

@Override
protected void processForm() {
    if (_action.equals(_t("Create 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 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 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 + '.');
}
Also used : PrivateKey(java.security.PrivateKey) SecureDirectory(net.i2p.util.SecureDirectory) InputStream(java.io.InputStream) GeneralSecurityException(java.security.GeneralSecurityException) ArrayList(java.util.ArrayList) ArrayList(java.util.ArrayList) List(java.util.List) IOException(java.io.IOException) File(java.io.File) HashMap(java.util.HashMap) Map(java.util.Map)

Example 14 with SecureDirectory

use of net.i2p.util.SecureDirectory in project i2p.i2p by i2p.

the class PluginUpdateRunner method processFinal.

/**
 *  @param pubkey null OK for su3
 *  @since 0.9.15
 */
private void processFinal(File to, File appDir, String url, Properties props, String sudVersion, String pubkey, String signer) {
    boolean update = false;
    String appName = props.getProperty("name");
    String version = props.getProperty("version");
    if (appName == null || version == null || appName.length() <= 0 || version.length() <= 0 || appName.indexOf('<') >= 0 || appName.indexOf('>') >= 0 || version.indexOf('<') >= 0 || version.indexOf('>') >= 0 || appName.startsWith(".") || appName.indexOf('/') >= 0 || appName.indexOf('\\') >= 0) {
        to.delete();
        statusDone("<b>" + _t("Plugin from {0} has invalid name or version", url) + "</b>");
        return;
    }
    if (!version.equals(sudVersion)) {
        to.delete();
        statusDone("<b>" + _t("Plugin {0} has mismatched versions", appName) + "</b>");
        return;
    }
    // set so notifyComplete() will work
    _appName = appName;
    _newVersion = version;
    String minVersion = PluginStarter.stripHTML(props, "min-i2p-version");
    if (minVersion != null && VersionComparator.comp(CoreVersion.VERSION, minVersion) < 0) {
        to.delete();
        statusDone("<b>" + _t("This plugin requires I2P version {0} or higher", minVersion) + "</b>");
        return;
    }
    minVersion = PluginStarter.stripHTML(props, "min-java-version");
    if (minVersion != null && VersionComparator.comp(System.getProperty("java.version"), minVersion) < 0) {
        to.delete();
        statusDone("<b>" + _t("This plugin requires Java version {0} or higher", minVersion) + "</b>");
        return;
    }
    boolean wasRunning = false;
    File destDir = new SecureDirectory(appDir, appName);
    if (destDir.exists()) {
        if (Boolean.valueOf(props.getProperty("install-only")).booleanValue()) {
            to.delete();
            statusDone("<b>" + _t("Downloaded plugin is for new installs only, but the plugin is already installed", url) + "</b>");
            return;
        }
        // compare previous version
        File oldPropFile = new File(destDir, "plugin.config");
        Properties oldProps = new OrderedProperties();
        try {
            DataHelper.loadProps(oldProps, oldPropFile);
        } catch (IOException ioe) {
            to.delete();
            statusDone("<b>" + _t("Installed plugin does not contain the required configuration file", url) + "</b>");
            return;
        }
        String oldPubkey = oldProps.getProperty("key");
        String oldKeyName = oldProps.getProperty("signer");
        String oldAppName = oldProps.getProperty("name");
        if ((pubkey != null && !pubkey.equals(oldPubkey)) || (!signer.equals(oldKeyName)) || (!appName.equals(oldAppName))) {
            to.delete();
            statusDone("<b>" + _t("Signature of downloaded plugin does not match installed plugin") + "</b>");
            return;
        }
        String oldVersion = oldProps.getProperty("version");
        if (oldVersion == null || VersionComparator.comp(oldVersion, version) >= 0) {
            to.delete();
            statusDone("<b>" + _t("Downloaded plugin version {0} is not newer than installed plugin", version) + "</b>");
            return;
        }
        minVersion = PluginStarter.stripHTML(props, "min-installed-version");
        if (minVersion != null && VersionComparator.comp(minVersion, oldVersion) > 0) {
            to.delete();
            statusDone("<b>" + _t("Plugin update requires installed plugin version {0} or higher", minVersion) + "</b>");
            return;
        }
        String maxVersion = PluginStarter.stripHTML(props, "max-installed-version");
        if (maxVersion != null && VersionComparator.comp(maxVersion, oldVersion) < 0) {
            to.delete();
            statusDone("<b>" + _t("Plugin update requires installed plugin version {0} or lower", maxVersion) + "</b>");
            return;
        }
        oldVersion = RouterConsoleRunner.jettyVersion();
        minVersion = PluginStarter.stripHTML(props, "min-jetty-version");
        if (minVersion != null && VersionComparator.comp(minVersion, oldVersion) > 0) {
            to.delete();
            statusDone("<b>" + _t("Plugin requires Jetty version {0} or higher", minVersion) + "</b>");
            return;
        }
        String blacklistVersion = PluginStarter.jetty9Blacklist.get(appName);
        if (blacklistVersion != null && VersionComparator.comp(version, blacklistVersion) <= 0) {
            to.delete();
            statusDone("<b>" + _t("Plugin requires Jetty version {0} or lower", "8.9999") + "</b>");
            return;
        }
        maxVersion = PluginStarter.stripHTML(props, "max-jetty-version");
        if (maxVersion != null && VersionComparator.comp(maxVersion, oldVersion) < 0) {
            to.delete();
            statusDone("<b>" + _t("Plugin requires Jetty version {0} or lower", maxVersion) + "</b>");
            return;
        }
        // do we defer extraction and installation?
        if (Boolean.valueOf(props.getProperty("router-restart-required")).booleanValue()) {
            // Yup!
            try {
                if (!FileUtil.copy(to, (new SecureFile(new SecureFile(appDir.getCanonicalPath() + "/" + appName + "/" + ZIP).getCanonicalPath())), true, true)) {
                    to.delete();
                    statusDone("<b>" + _t("Cannot copy plugin to directory {0}", destDir.getAbsolutePath()) + "</b>");
                    return;
                }
            } catch (Throwable t) {
                to.delete();
                _log.error("Error copying plugin {0}", t);
                return;
            }
            // we don't need the original file anymore.
            to.delete();
            statusDone("<b>" + _t("Plugin will be installed on next restart.") + ' ' + appName + ' ' + version + "</b>");
            return;
        }
        if (PluginStarter.isPluginRunning(appName, _context)) {
            wasRunning = true;
            try {
                if (!PluginStarter.stopPlugin(_context, appName)) {
                // failed, ignore
                }
            } catch (Throwable e) {
                // no updateStatus() for this one
                _log.error("Error stopping plugin " + appName, e);
            }
        }
        update = true;
    } else {
        if (Boolean.valueOf(props.getProperty("update-only")).booleanValue()) {
            to.delete();
            statusDone("<b>" + _t("Plugin is for upgrades only, but the plugin is not installed") + ". " + appName + ' ' + version + "</b>");
            return;
        }
        if (!destDir.mkdir()) {
            to.delete();
            statusDone("<b>" + _t("Cannot create plugin directory {0}", destDir.getAbsolutePath()) + "</b>");
            return;
        }
    }
    // Finally, extract the zip to the plugin directory
    if (!FileUtil.extractZip(to, destDir, Log.WARN)) {
        to.delete();
        statusDone("<b>" + _t("Failed to install plugin in {0}", destDir.getAbsolutePath()) + "</b>");
        return;
    }
    _updated = true;
    to.delete();
    // install != update. Changing the user's settings like this is probabbly a bad idea.
    if (Boolean.valueOf(props.getProperty("dont-start-at-install")).booleanValue()) {
        statusDone("<b>" + _t("Plugin {0} installed", appName + ' ' + version) + "</b>");
        if (!update) {
            Properties pluginProps = PluginStarter.pluginProperties();
            pluginProps.setProperty(PluginStarter.PREFIX + appName + PluginStarter.ENABLED, "false");
            PluginStarter.storePluginProperties(pluginProps);
        }
    } else if (wasRunning || PluginStarter.isPluginEnabled(appName)) {
        // start everything unless it was disabled and not running before
        try {
            if (PluginStarter.startPlugin(_context, appName)) {
                String linkName = PluginStarter.stripHTML(props, "consoleLinkName_" + Messages.getLanguage(_context));
                if (linkName == null)
                    linkName = PluginStarter.stripHTML(props, "consoleLinkName");
                String linkURL = PluginStarter.stripHTML(props, "consoleLinkURL");
                String link;
                if (linkName != null && linkURL != null)
                    link = "<a target=\"_blank\" href=\"" + linkURL + "\"/>" + linkName + ' ' + version + "</a>";
                else
                    link = appName + ' ' + version;
                statusDone("<b>" + _t("Plugin {0} installed and started", link) + "</b>");
            } else
                statusDone("<b>" + _t("Plugin {0} installed but failed to start, check logs", appName + ' ' + version) + "</b>");
        } catch (Throwable e) {
            statusDone("<b>" + _t("Plugin {0} installed but failed to start", appName + ' ' + version) + ": " + e + "</b>");
            _log.error("Error starting plugin " + appName + ' ' + version, e);
        }
    } else {
        statusDone("<b>" + _t("Plugin {0} installed", appName + ' ' + version) + "</b>");
    }
}
Also used : SecureDirectory(net.i2p.util.SecureDirectory) SecureFile(net.i2p.util.SecureFile) OrderedProperties(net.i2p.util.OrderedProperties) IOException(java.io.IOException) OrderedProperties(net.i2p.util.OrderedProperties) Properties(java.util.Properties) SecureFile(net.i2p.util.SecureFile) SU3File(net.i2p.crypto.SU3File) File(java.io.File)

Example 15 with SecureDirectory

use of net.i2p.util.SecureDirectory in project i2p.i2p by i2p.

the class PersistNews method store.

/**
 *  Store each entry.
 *  Old entries are always overwritten, as they may change even without the updated date changing.
 *
 *  @param entries each one should be "entry" at the root
 *  @return success
 */
public static boolean store(I2PAppContext ctx, List<Node> entries) {
    Log log = ctx.logManager().getLog(PersistNews.class);
    File dir = new SecureDirectory(ctx.getConfigDir(), DIR);
    if (!dir.exists())
        dir.mkdirs();
    StringBuilder buf = new StringBuilder();
    boolean rv = true;
    for (Node entry : entries) {
        Node nid = entry.getNode("id");
        if (nid == null) {
            if (log.shouldWarn())
                log.warn("entry without UUID");
            continue;
        }
        String id = nid.getValue();
        if (id == null) {
            if (log.shouldWarn())
                log.warn("entry without UUID");
            continue;
        }
        String name = idToName(ctx, id);
        File file = new File(dir, name);
        Writer out = null;
        try {
            out = new OutputStreamWriter(new GZIPOutputStream(new SecureFileOutputStream(file)));
            out.write(XML_START);
            XMLParser.toString(buf, entry);
            out.write(buf.toString());
            buf.setLength(0);
        } catch (IOException ioe) {
            if (log.shouldWarn())
                log.warn("failed store to " + file, ioe);
            rv = false;
        } finally {
            if (out != null)
                try {
                    out.close();
                } catch (IOException ioe) {
                }
        }
    }
    return rv;
}
Also used : Log(net.i2p.util.Log) SecureDirectory(net.i2p.util.SecureDirectory) GZIPOutputStream(java.util.zip.GZIPOutputStream) Node(org.cybergarage.xml.Node) OutputStreamWriter(java.io.OutputStreamWriter) SecureFileOutputStream(net.i2p.util.SecureFileOutputStream) IOException(java.io.IOException) File(java.io.File) Writer(java.io.Writer) OutputStreamWriter(java.io.OutputStreamWriter)

Aggregations

SecureDirectory (net.i2p.util.SecureDirectory)32 File (java.io.File)31 IOException (java.io.IOException)16 HashMap (java.util.HashMap)5 Properties (java.util.Properties)4 GeneralSecurityException (java.security.GeneralSecurityException)3 ArrayList (java.util.ArrayList)3 OrderedProperties (net.i2p.util.OrderedProperties)3 SecureFile (net.i2p.util.SecureFile)3 UnsupportedEncodingException (java.io.UnsupportedEncodingException)2 PrivateKey (java.security.PrivateKey)2 Map (java.util.Map)2 StringTokenizer (java.util.StringTokenizer)2 ConcurrentHashMap (java.util.concurrent.ConcurrentHashMap)2 SU3File (net.i2p.crypto.SU3File)2 WebAppContext (org.eclipse.jetty.webapp.WebAppContext)2 InputStream (java.io.InputStream)1 OutputStreamWriter (java.io.OutputStreamWriter)1 Writer (java.io.Writer)1 InetSocketAddress (java.net.InetSocketAddress)1