Changeset e3be1d1


Ignore:
Timestamp:
Aug 10, 2014 1:56:15 PM (6 years ago)
Author:
zzz <zzz@…>
Branches:
master
Children:
4ba40b3
Parents:
6fa2a41 (diff), 22a7757 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

propagate from branch 'i2p.i2p.zzz.test2' (head c182b371bc28158dd47262b89e5bd0cdda29e07b)

to branch 'i2p.i2p' (head 4fc776f7b76b028bb890affccfdcfbefbb932c58)

Files:
1 added
28 edited
1 moved

Legend:

Unmodified
Added
Removed
  • apps/BOB/src/net/i2p/BOB/BOB.java

    r6fa2a41 re3be1d1  
    120120        public final static String PROP_CFG_VER = "BOB.CFG.VER";
    121121
     122        /** unused when started via the ClientApp interface */
    122123        private static BOB _bob;
    123124
    124         private NamedDB database;
    125         private Properties props = new Properties();
    126         private AtomicBoolean spin = new AtomicBoolean(true);
     125        private final NamedDB database;
     126        private final Properties props = new Properties();
     127        private final AtomicBoolean spin = new AtomicBoolean(true);
    127128        private static final String P_RUNNING = "RUNNING";
    128129        private static final String P_STARTING = "STARTING";
    129130        private static final String P_STOPPING = "STOPPING";
    130         private AtomicBoolean lock = new AtomicBoolean(false);
     131        private final AtomicBoolean lock = new AtomicBoolean(false);
    131132        // no longer used.
    132133        // private static int maxConnections = 0;
     
    144145         * @deprecated unused
    145146         */
    146         public static void stop() {
    147                 _bob.shutdown(null);
     147        public synchronized static void stop() {
     148                if (_bob != null)
     149                        _bob.shutdown(null);
    148150        }
    149151
     
    190192         * @param args
    191193         */
    192         public static void main(String[] args) {
     194        public synchronized static void main(String[] args) {
    193195                try {
    194196                        _bob = new BOB(I2PAppContext.getGlobalContext(), null, args);
  • apps/routerconsole/java/src/net/i2p/router/update/PluginUpdateHandler.java

    r6fa2a41 re3be1d1  
    4444        Properties props = PluginStarter.pluginProperties(_context, appName);
    4545        String oldVersion = props.getProperty("version");
    46         String xpi2pURL = props.getProperty("updateURL");
     46        String xpi2pURL = props.getProperty("updateURL.su3");
     47        if (xpi2pURL == null)
     48            xpi2pURL = props.getProperty("updateURL");
    4749        List<URI> updateSources = null;
    4850        if (xpi2pURL != null) {
  • apps/routerconsole/java/src/net/i2p/router/update/PluginUpdateRunner.java

    r6fa2a41 re3be1d1  
    22
    33import java.io.File;
     4import java.io.FileInputStream;
    45import java.io.IOException;
    56import java.lang.IllegalArgumentException;
     
    1011
    1112import net.i2p.CoreVersion;
     13import net.i2p.crypto.SU3File;
    1214import net.i2p.crypto.TrustedUpdate;
    1315import net.i2p.data.DataFormatException;
     
    122124        @Override
    123125        public void transferComplete(long alreadyTransferred, long bytesTransferred, long bytesRemaining, String url, String outputFile, boolean notModified) {
    124             boolean update = false;
    125126            updateStatus("<b>" + _("Plugin downloaded") + "</b>");
    126127            File f = new File(_updateFile);
     
    131132                return;
    132133            }
    133 
     134            boolean isSU3;
     135            try {
     136                isSU3 = isSU3File(f);
     137            } catch (IOException ioe) {
     138                f.delete();
     139                statusDone("<b>" + ioe + "</b>");
     140                return;
     141            }
     142            if (isSU3)
     143                processSU3(f, appDir, url);
     144            else
     145                processSUD(f, appDir, url);
     146        }
     147
     148        /**
     149         *  @since 0.9.15
     150         *  @return if SU3
     151         */
     152        private static boolean isSU3File(File f) throws IOException {
     153            FileInputStream fis = null;
     154            try {
     155                fis = new FileInputStream(f);
     156                for (int i = 0; i < SU3File.MAGIC.length(); i++) {
     157                    if (fis.read() != SU3File.MAGIC.charAt(i))
     158                        return false;
     159                }
     160                return true;
     161            } finally {
     162                if (fis != null) try { fis.close(); } catch (IOException ioe) {}
     163            }
     164        }
     165
     166        /**
     167         *  @since 0.9.15
     168         *  @return success
     169         */
     170        private void processSUD(File f, File appDir, String url) {
    134171            TrustedUpdate up = new TrustedUpdate(_context);
    135172            File to = new File(_context.getTempDir(), "tmp" + _context.random().nextInt() + ZIP);
     
    142179                return;
    143180            }
    144             File tempDir = new File(_context.getTempDir(), "tmp" + _context.random().nextInt() + "-unzip");
    145             if (!FileUtil.extractZip(to, tempDir, Log.ERROR)) {
    146                 f.delete();
    147                 to.delete();
    148                 FileUtil.rmdir(tempDir, false);
    149                 statusDone("<b>" + _("Plugin from {0} is corrupt", url) + "</b>");
    150                 return;
    151             }
    152             File installProps = new File(tempDir, "plugin.config");
    153             Properties props = new OrderedProperties();
    154             try {
    155                 DataHelper.loadProps(props, installProps);
    156             } catch (IOException ioe) {
    157                 f.delete();
    158                 to.delete();
    159                 FileUtil.rmdir(tempDir, false);
    160                 statusDone("<b>" + _("Plugin from {0} does not contain the required configuration file", url) + "</b>");
    161                 return;
    162             }
    163             // we don't need this anymore, we will unzip again
    164             FileUtil.rmdir(tempDir, false);
     181            Properties props = getPluginConfig(f, to, url);
     182            if (props == null)
     183                return;
    165184
    166185            // ok, now we check sigs and deal with a bad sig
     
    252271            String sudVersion = TrustedUpdate.getVersionString(f);
    253272            f.delete();
    254 
     273            processFinal(to, appDir, url, props, sudVersion, pubkey, signer);
     274        }
     275
     276        /**
     277         *  @since 0.9.15
     278         */
     279        private void processSU3(File f, File appDir, String url) {
     280            SU3File su3 = new SU3File(_context, f);
     281            File to = new File(_context.getTempDir(), "tmp" + _context.random().nextInt() + ZIP);
     282            String sudVersion;
     283            String signingKeyName;
     284            try {
     285                su3.verifyAndMigrate(to);
     286                if (su3.getFileType() != SU3File.TYPE_ZIP)
     287                    throw new IOException("bad file type");
     288                if (su3.getContentType() != SU3File.CONTENT_PLUGIN)
     289                    throw new IOException("bad content type");
     290                sudVersion = su3.getVersionString();
     291                signingKeyName = su3.getSignerString();
     292            } catch (IOException ioe) {
     293                statusDone("<b>" + ioe + ' ' + _("from {0}", url) + " </b>");
     294                f.delete();
     295                to.delete();
     296                return;
     297            }
     298            Properties props = getPluginConfig(f, to, url);
     299            if (props == null)
     300                return;
     301            String signer = props.getProperty("signer");
     302            if (signer == null || signer.length() <= 0) {
     303                f.delete();
     304                to.delete();
     305                statusDone("<b>" + _("Plugin from {0} contains an invalid key", url) + "</b>");
     306                return;
     307            }
     308            if (!signer.equals(signingKeyName)) {
     309                f.delete();
     310                to.delete();
     311                if (signingKeyName == null)
     312                    _log.error("Failed to verify plugin signature, corrupt plugin or bad signature, signed by: " + signer);
     313                else
     314                    // shouldn't happen
     315                    _log.error("Plugin signer \"" + signer + "\" does not match new signer in plugin.config file \"" + signingKeyName + "\"");
     316                statusDone("<b>" + _("Plugin signature verification of {0} failed", url) + "</b>");
     317                return;
     318            }
     319            processFinal(to, appDir, url, props, sudVersion, null, signer);
     320        }
     321
     322        /**
     323         *  @since 0.9.15
     324         *  @return null on error
     325         */
     326        private Properties getPluginConfig(File f, File to, String url) {
     327            File tempDir = new File(_context.getTempDir(), "tmp" + _context.random().nextInt() + "-unzip");
     328            if (!FileUtil.extractZip(to, tempDir, Log.ERROR)) {
     329                f.delete();
     330                to.delete();
     331                FileUtil.rmdir(tempDir, false);
     332                statusDone("<b>" + _("Plugin from {0} is corrupt", url) + "</b>");
     333                return null;
     334            }
     335            File installProps = new File(tempDir, "plugin.config");
     336            Properties props = new OrderedProperties();
     337            try {
     338                DataHelper.loadProps(props, installProps);
     339            } catch (IOException ioe) {
     340                f.delete();
     341                to.delete();
     342                statusDone("<b>" + _("Plugin from {0} does not contain the required configuration file", url) + "</b>");
     343                return null;
     344            } finally {
     345                // we don't need this anymore, we will unzip again
     346                FileUtil.rmdir(tempDir, false);
     347            }
     348            return props;
     349        }
     350
     351        /**
     352         *  @param pubkey null OK for su3
     353         *  @since 0.9.15
     354         */
     355        private void processFinal(File to, File appDir, String url, Properties props, String sudVersion, String pubkey, String signer) {
     356            boolean update = false;
    255357            String appName = props.getProperty("name");
    256358            String version = props.getProperty("version");
     
    303405                } catch (IOException ioe) {
    304406                    to.delete();
    305                     FileUtil.rmdir(tempDir, false);
    306407                    statusDone("<b>" + _("Installed plugin does not contain the required configuration file", url) + "</b>");
    307408                    return;
     
    310411                String oldKeyName = oldProps.getProperty("signer");
    311412                String oldAppName = oldProps.getProperty("name");
    312                 if ((!pubkey.equals(oldPubkey)) || (!signer.equals(oldKeyName)) || (!appName.equals(oldAppName))) {
     413                if ((pubkey != null && !pubkey.equals(oldPubkey)) || (!signer.equals(oldKeyName)) || (!appName.equals(oldAppName))) {
    313414                    to.delete();
    314415                    statusDone("<b>" + _("Signature of downloaded plugin does not match installed plugin") + "</b>");
  • apps/routerconsole/java/src/net/i2p/router/web/ConfigClientsHandler.java

    r6fa2a41 re3be1d1  
    391391    private void updatePlugin(String app) {
    392392        Properties props = PluginStarter.pluginProperties(_context, app);
    393         String url = props.getProperty("updateURL");
     393        String url = props.getProperty("updateURL.su3");
     394        if (url == null)
     395            url = props.getProperty("updateURL");
    394396        if (url == null) {
    395397            addFormError(_("No update URL specified for {0}",app));
  • apps/routerconsole/java/src/net/i2p/router/web/ConfigClientsHelper.java

    r6fa2a41 re3be1d1  
    249249                        .append("<a href=\"").append(s).append("\">").append(_("Website")).append("</a><td>&nbsp;");
    250250                }
    251                 String updateURL = stripHTML(appProps, "updateURL");
     251                String updateURL = stripHTML(appProps, "updateURL.su3");
     252                if (updateURL == null)
     253                    updateURL = stripHTML(appProps, "updateURL");
    252254                if (updateURL != null) {
    253255                    desc.append("<tr><td>")
  • apps/routerconsole/java/src/net/i2p/router/web/ConfigNetHelper.java

    r6fa2a41 re3be1d1  
    299299        buf.append("<select style=\"text-align: right !important;\" name=\"sharePercentage\">\n");
    300300        boolean found = false;
    301         for (int i = 30; i <= 110; i += 10) {
     301        for (int i = 100; i >= -10; i -= 10) {
    302302            int val = i;
    303             if (i == 110) {
     303            if (i == -10) {
    304304                if (found)
    305305                    break;
  • apps/sam/java/src/net/i2p/sam/SAMBridge.java

    r6fa2a41 re3be1d1  
    162162     * @param name name of the destination
    163163     * @return null if the name does not exist, or if it is improperly formatted
     164     * @deprecated unused
    164165     */
    165166    public Destination getDestination(String name) {
  • apps/sam/java/src/net/i2p/sam/SAMDatagramSession.java

    r6fa2a41 re3be1d1  
    1313import java.util.Properties;
    1414
     15import net.i2p.client.I2PSession;
    1516import net.i2p.client.I2PSessionException;
    1617import net.i2p.client.datagram.I2PDatagramDissector;
     
    8990                dgram = dgramMaker.makeI2PDatagram(data);
    9091        }
    91         return sendBytesThroughMessageSession(dest, dgram);
     92        // TODO pass ports through
     93        return sendBytesThroughMessageSession(dest, dgram, I2PSession.PROTO_DATAGRAM,
     94                                              I2PSession.PORT_UNSPECIFIED, I2PSession.PORT_UNSPECIFIED);
    9295    }
    9396
  • apps/sam/java/src/net/i2p/sam/SAMHandler.java

    r6fa2a41 re3be1d1  
    1414import java.util.Properties;
    1515
     16import net.i2p.I2PAppContext;
    1617import net.i2p.data.DataHelper;
    1718import net.i2p.util.I2PAppThread;
     
    5556    protected SAMHandler(SocketChannel s,
    5657                         int verMajor, int verMinor, Properties i2cpProps) throws IOException {
    57         _log = new Log(getClass());
     58        _log = I2PAppContext.getGlobalContext().logManager().getLog(getClass());
    5859        socket = s;
    5960
  • apps/sam/java/src/net/i2p/sam/SAMHandlerFactory.java

    r6fa2a41 re3be1d1  
    1010
    1111import java.io.IOException;
    12 import java.io.UnsupportedEncodingException;
     12import java.net.Socket;
     13import java.net.SocketTimeoutException;
    1314import java.nio.channels.SocketChannel;
    14 import java.nio.ByteBuffer;
    1515import java.util.Properties;
    1616import java.util.StringTokenizer;
    1717
     18import net.i2p.I2PAppContext;
    1819import net.i2p.data.DataHelper;
    1920import net.i2p.util.Log;
     
    2728    private static final String VERSION = "3.1";
    2829
     30    private static final int HELLO_TIMEOUT = 60*1000;
     31
    2932    /**
    3033     * Return the right SAM handler depending on the protocol version
     
    3740     */
    3841    public static SAMHandler createSAMHandler(SocketChannel s, Properties i2cpProps) throws SAMException {
    39         String line;
    4042        StringTokenizer tok;
    41         Log log = new Log(SAMHandlerFactory.class);
     43        Log log = I2PAppContext.getGlobalContext().logManager().getLog(SAMHandlerFactory.class);
    4244
    4345        try {
    44             line = DataHelper.readLine(s.socket().getInputStream());
     46            Socket sock = s.socket();
     47            sock.setSoTimeout(HELLO_TIMEOUT);
     48            String line = DataHelper.readLine(sock.getInputStream());
     49            sock.setSoTimeout(0);
    4550            if (line == null) {
    4651                log.debug("Connection closed by client");
     
    4853            }
    4954            tok = new StringTokenizer(line.trim(), " ");
     55        } catch (SocketTimeoutException e) {
     56            throw new SAMException("Timeout waiting for HELLO VERSION", e);
    5057        } catch (IOException e) {
    5158            throw new SAMException("Error reading from socket", e);
  • apps/sam/java/src/net/i2p/sam/SAMMessageSession.java

    r6fa2a41 re3be1d1  
    1414import java.util.Properties;
    1515
     16import net.i2p.I2PAppContext;
    1617import net.i2p.client.I2PClient;
    1718import net.i2p.client.I2PClientFactory;
     
    3435
    3536    protected final Log _log;
    36 
    37     private I2PSession session = null;
    38 
    39     private SAMMessageSessionHandler handler = null;
     37    private I2PSession session;
     38    private SAMMessageSessionHandler handler;
    4039
    4140    /**
     
    4948     */
    5049    protected SAMMessageSession(String dest, Properties props) throws IOException, DataFormatException, I2PSessionException {
    51         _log = new Log(getClass());
     50        _log = I2PAppContext.getGlobalContext().logManager().getLog(getClass());
    5251        ByteArrayInputStream bais = new ByteArrayInputStream(Base64.decode(dest));
    5352        initSAMMessageSession(bais, props);
     
    104103     * @param dest Destination
    105104     * @param data Bytes to be sent
     105     * @param proto I2CP protocol
     106     * @param fromPort I2CP from port
     107     * @param toPort I2CP to port
    106108     *
    107109     * @return True if the data was sent, false otherwise
    108      * @throws DataFormatException
    109      */
    110     protected boolean sendBytesThroughMessageSession(String dest, byte[] data) throws DataFormatException {
     110     * @throws DataFormatException on unknown / bad dest
     111     */
     112    protected boolean sendBytesThroughMessageSession(String dest, byte[] data,
     113                                                     int proto, int fromPort, int toPort) throws DataFormatException {
    111114        Destination d = SAMUtils.getDest(dest);
    112115
     
    116119
    117120        try {
    118             return session.sendMessage(d, data);
     121            return session.sendMessage(d, data, proto, fromPort, toPort);
    119122        } catch (I2PSessionException e) {
    120123            _log.error("I2PSessionException while sending data", e);
  • apps/sam/java/src/net/i2p/sam/SAMRawSession.java

    r6fa2a41 re3be1d1  
    1313import java.util.Properties;
    1414
     15import net.i2p.client.I2PSession;
    1516import net.i2p.client.I2PSessionException;
    1617import net.i2p.data.DataFormatException;
     
    7475        if (data.length > RAW_SIZE_MAX)
    7576            throw new DataFormatException("Data size limit exceeded (" + data.length + ")");
    76         return sendBytesThroughMessageSession(dest, data);
     77        // TODO pass ports through
     78        return sendBytesThroughMessageSession(dest, data, I2PSession.PROTO_DATAGRAM_RAW,
     79                                              I2PSession.PORT_UNSPECIFIED, I2PSession.PORT_UNSPECIFIED);
    7780    }
    7881
  • apps/sam/java/src/net/i2p/sam/SAMStreamSession.java

    r6fa2a41 re3be1d1  
    2626import java.util.concurrent.atomic.AtomicInteger;
    2727
     28import net.i2p.I2PAppContext;
    2829import net.i2p.I2PException;
    2930import net.i2p.client.I2PClient;
     
    108109                            Properties props,  SAMStreamReceiver recv) throws IOException, DataFormatException, SAMException {
    109110        this.recv = recv;
    110         _log = new Log(getClass());
     111        _log = I2PAppContext.getGlobalContext().logManager().getLog(getClass());
    111112        if (_log.shouldLog(Log.DEBUG))
    112                 _log.debug("SAM STREAM session instantiated");
     113            _log.debug("SAM STREAM session instantiated");
    113114
    114115        Properties allprops = (Properties) System.getProperties().clone();
  • apps/sam/java/src/net/i2p/sam/SAMUtils.java

    r6fa2a41 re3be1d1  
    124124     *
    125125     * @param name Hostname to be resolved
    126      * @param pubKey A stream to write the Destination public key (may be null)
    127126     *
    128127     * @return the Destination for the specified hostname, or null if not found
    129128     */
    130     public static Destination lookupHost(String name, OutputStream pubKey) {
     129    private static Destination lookupHost(String name) {
    131130        NamingService ns = I2PAppContext.getGlobalContext().namingService();
    132131        Destination dest = ns.lookup(name);
    133 
    134         if ((pubKey != null) && (dest != null)) {
    135             try {
    136                 dest.writeBytes(pubKey);
    137             } catch (IOException e) {
    138                 e.printStackTrace();
    139                 return null;
    140             } catch (DataFormatException e) {
    141                 e.printStackTrace();
    142                 return null;
    143             }
    144         }
    145 
    146132        return dest;
    147133    }
     
    152138     * @param s Hostname or key to be resolved
    153139     *
    154      * @return the Destination for the specified hostname, or null if not found
     140     * @return the Destination for the specified hostname, non-null
     141     * @throws DataFormatException on bad Base 64 or name not found
    155142     */
    156143    public static Destination getDest(String s) throws DataFormatException
    157144    {
    158         Destination d = new Destination() ;
    159         try {
    160                 d.fromBase64(s);
    161         } catch (DataFormatException e) {
    162                 d = lookupHost(s, null);
    163                 if ( d==null ) {
    164                         throw e ;
    165                 }
    166         }
    167         return d ;
     145        // NamingService caches b64 so just use it for everything
     146        // TODO: Add a static local cache here so SAM doesn't flush the
     147        // NamingService cache
     148        Destination d = lookupHost(s);
     149        if (d == null) {
     150            String msg;
     151            if (s.length() >= 516)
     152                msg = "Bad Base64 dest: ";
     153            else if (s.length() == 60 && s.endsWith(".b32.i2p"))
     154                msg = "Lease set not found: ";
     155            else
     156                msg = "Host name not found: ";
     157            throw new DataFormatException(msg + s);
     158        }
     159        return d;
    168160    }
    169161
  • apps/sam/java/src/net/i2p/sam/SAMv1Handler.java

    r6fa2a41 re3be1d1  
    247247                    if (destKeystream == null) {
    248248                        if (_log.shouldLog(Log.DEBUG))
    249                             _log.debug("Custom destination specified [" + dest + "] but it isnt know, creating a new one");
     249                            _log.debug("Custom destination specified [" + dest + "] but it isn't known, creating a new one");
    250250                        ByteArrayOutputStream baos = new ByteArrayOutputStream(640);
    251251                        SAMUtils.genRandomKey(baos, null);
     
    285285                        && !dir.equals("BOTH")) {
    286286                        if (_log.shouldLog(Log.DEBUG))
    287                             _log.debug("Unknow DIRECTION parameter value: [" + dir + "]");
     287                            _log.debug("Unknown DIRECTION parameter value: [" + dir + "]");
    288288                        return writeString("SESSION STATUS RESULT=I2P_ERROR MESSAGE=\"Unknown DIRECTION parameter\"\n");
    289289                    }
  • apps/sam/java/src/net/i2p/sam/SAMv3Handler.java

    r6fa2a41 re3be1d1  
    2626import java.util.StringTokenizer;
    2727
     28import net.i2p.I2PAppContext;
    2829import net.i2p.I2PException;
    2930import net.i2p.client.I2PClient;
     
    160161                                        outBuf.put(inBuf);
    161162                                        outBuf.flip();
    162                                         new I2PAppThread(new MessageDispatcher(outBuf.array()), "MessageDispatcher").start();
     163                                        // A new thread for every message is wildly inefficient...
     164                                        //new I2PAppThread(new MessageDispatcher(outBuf.array()), "MessageDispatcher").start();
     165                                        // inline
     166                                        // Even though we could be sending messages through multiple sessions,
     167                                        // that isn't a common use case, and blocking should be rare.
     168                                        // Inside router context, I2CP drops on overflow.
     169                                        (new MessageDispatcher(outBuf.array())).run();
    163170                                }
    164171                        }
     
    195202                                if (rec!=null) {
    196203                                        rec.getHandler().session.sendBytes(dest,data);
     204                                } else {
     205                                        Log log = I2PAppContext.getGlobalContext().logManager().getLog(SAMv3Handler.class);
     206                                        if (log.shouldLog(Log.WARN))
     207                                                log.warn("Dropping datagram, no session for " + nick);
    197208                                }
    198209                        } catch (Exception e) {
    199                                 // FIXME log? throw?
     210                                Log log = I2PAppContext.getGlobalContext().logManager().getLog(SAMv3Handler.class);
     211                                if (log.shouldLog(Log.WARN))
     212                                        log.warn("Error handling datagram", e);
    200213                        }
    201214                }
  • core/java/src/net/i2p/I2PAppContext.java

    r6fa2a41 re3be1d1  
    2323import net.i2p.crypto.SHA256Generator;
    2424import net.i2p.crypto.SessionKeyManager;
    25 import net.i2p.crypto.TransientSessionKeyManager;
    2625import net.i2p.data.Base64;
    2726import net.i2p.data.RoutingKeyGenerator;
     
    7776   
    7877    private StatManager _statManager;
    79     private SessionKeyManager _sessionKeyManager;
     78    protected SessionKeyManager _sessionKeyManager;
    8079    private NamingService _namingService;
    8180    private ElGamalEngine _elGamalEngine;
     
    9796    private final PortMapper _portMapper;
    9897    private volatile boolean _statManagerInitialized;
    99     private volatile boolean _sessionKeyManagerInitialized;
     98    protected volatile boolean _sessionKeyManagerInitialized;
    10099    private volatile boolean _namingServiceInitialized;
    101100    private volatile boolean _elGamalEngineInitialized;
     
    600599     * use RouterContext.clientManager.getClientSessionKeyManager(dest)
    601600     *
     601     * As of 0.9.15, this returns a dummy SessionKeyManager in I2PAppContext.
     602     * The dummy SKM does NOT handle session tags.
     603     * Overridden in RouterContext to return the full TransientSessionKeyManager.
    602604     */
    603605    public SessionKeyManager sessionKeyManager() {
     
    607609    }
    608610
    609     private void initializeSessionKeyManager() {
     611    protected void initializeSessionKeyManager() {
    610612        synchronized (_lock3) {
    611613            if (_sessionKeyManager == null)
    612614                //_sessionKeyManager = new PersistentSessionKeyManager(this);
    613                 _sessionKeyManager = new TransientSessionKeyManager(this);
     615                _sessionKeyManager = new SessionKeyManager(this);
    614616            _sessionKeyManagerInitialized = true;
    615617        }
  • core/java/src/net/i2p/crypto/SU3File.java

    r6fa2a41 re3be1d1  
    1616import java.security.PrivateKey;
    1717import java.security.PublicKey;
     18import java.security.cert.CertificateFactory;
     19import java.security.cert.X509Certificate;
    1820import java.util.ArrayList;
    1921import java.util.Arrays;
     
    5052    private String _signer;
    5153    private int _signerLength;
     54    private int _fileType = -1;
    5255    private ContentType _contentType;
    5356    private long _contentLength;
     
    5558    private boolean _headerVerified;
    5659    private SigType _sigType;
    57 
    58     private static final byte[] MAGIC = DataHelper.getUTF8("I2Psu3");
     60    private boolean _verifySignature = true;
     61    private File _certFile;
     62
     63    public static final String MAGIC = "I2Psu3";
     64    private static final byte[] MAGIC_BYTES = DataHelper.getASCII(MAGIC);
    5965    private static final int FILE_VERSION = 0;
    6066    private static final int MIN_VERSION_BYTES = 16;
    6167    private static final int VERSION_OFFSET = 40; // Signature.SIGNATURE_BYTES; avoid early ctx init
    6268
    63     private static final int TYPE_ZIP = 0;
     69    public static final int TYPE_ZIP = 0;
     70    public static final int TYPE_XML = 1;
    6471
    6572    public static final int CONTENT_UNKNOWN = 0;
     
    6774    public static final int CONTENT_PLUGIN = 2;
    6875    public static final int CONTENT_RESEED = 3;
     76    public static final int CONTENT_NEWS = 4;
    6977
    7078    private enum ContentType {
     
    7280        ROUTER(CONTENT_ROUTER, "router"),
    7381        PLUGIN(CONTENT_PLUGIN, "plugin"),
    74         RESEED(CONTENT_RESEED, "reseed")
     82        RESEED(CONTENT_RESEED, "reseed"),
     83        NEWS(CONTENT_NEWS, "news")
    7584        ;
    7685
     
    126135    }
    127136
     137    /**
     138     *  Should the signature be verified? Default true
     139     *  @since 0.9.15
     140     */
     141    public void setVerifySignature(boolean shouldVerify) {
     142        _verifySignature = shouldVerify;
     143    }
     144
     145    /**
     146     *  Use this X.509 cert file for verification instead of $I2P/certificates/content_type/foo_at_mail.i2p
     147     *  @since 0.9.15
     148     */
     149    private void setPublicKeyCertificate(File certFile) {
     150        _certFile = certFile;
     151    }
     152
     153    /**
     154     *  This does not check the signature, but it will fail if the signer is unknown,
     155     *  unless setVerifySignature(false) has been called.
     156     */
    128157    public String getVersionString() throws IOException {
    129158        verifyHeader();
     
    131160    }
    132161
     162    /**
     163     *  This does not check the signature, but it will fail if the signer is unknown,
     164     *  unless setVerifySignature(false) has been called.
     165     */
    133166    public String getSignerString() throws IOException {
    134167        verifyHeader();
     
    137170
    138171    /**
     172     *  This does not check the signature, but it will fail if the signer is unknown,
     173     *  unless setVerifySignature(false) has been called.
     174     *
    139175     *  @return null if unknown
    140176     *  @since 0.9.9
     
    146182
    147183    /**
     184     *  This does not check the signature, but it will fail if the signer is unknown,
     185     *  unless setVerifySignature(false) has been called.
     186     *
    148187     *  @return -1 if unknown
    149188     *  @since 0.9.9
     
    155194
    156195    /**
     196     *  This does not check the signature, but it will fail if the signer is unknown,
     197     *  unless setVerifySignature(false) has been called.
     198     *
     199     *  @return -1 if unknown
     200     *  @since 0.9.15
     201     */
     202    public int getFileType() throws IOException {
     203        verifyHeader();
     204        return _fileType;
     205    }
     206
     207    /**
     208     *  This does not check the signature, but it will fail if the signer is unknown,
     209     *  unless setVerifySignature(false) has been called.
     210     *
    157211     *  Throws IOE if verify vails.
    158212     */
     
    177231     */
    178232    private void verifyHeader(InputStream in) throws IOException, DataFormatException {
    179         byte[] magic = new byte[MAGIC.length];
     233        byte[] magic = new byte[MAGIC_BYTES.length];
    180234        DataHelper.read(in, magic);
    181         if (!DataHelper.eq(magic, MAGIC))
     235        if (!DataHelper.eq(magic, MAGIC_BYTES))
    182236            throw new IOException("Not an su3 file");
    183237        skip(in, 1);
     
    205259            throw new IOException("bad content length");
    206260        skip(in, 1);
    207         foo = in.read();
    208         if (foo != TYPE_ZIP)
    209             throw new IOException("bad type");
     261        _fileType = in.read();
     262        if (_fileType != TYPE_ZIP && _fileType != TYPE_XML)
     263            throw new IOException("bad file type");
    210264        skip(in, 1);
    211265        int cType = in.read();
     
    232286        _signer = DataHelper.getUTF8(data);
    233287
    234         KeyRing ring = new DirKeyRing(new File(_context.getBaseDir(), "certificates"));
    235         try {
    236             _signerPubkey = ring.getKey(_signer, _contentType.getName(), _sigType);
    237         } catch (GeneralSecurityException gse) {
    238             IOException ioe = new IOException("keystore error");
    239             ioe.initCause(gse);
    240             throw ioe;
    241         }
    242 
    243         if (_signerPubkey == null)
    244             throw new IOException("unknown signer: " + _signer);
     288        if (_verifySignature) {
     289            if (_certFile != null) {
     290                _signerPubkey = loadKey(_certFile);
     291            } else {
     292                KeyRing ring = new DirKeyRing(new File(_context.getBaseDir(), "certificates"));
     293                try {
     294                    _signerPubkey = ring.getKey(_signer, _contentType.getName(), _sigType);
     295                } catch (GeneralSecurityException gse) {
     296                    IOException ioe = new IOException("keystore error");
     297                    ioe.initCause(gse);
     298                    throw ioe;
     299                }
     300                if (_signerPubkey == null)
     301                    throw new IOException("unknown signer: " + _signer + " for content type: " + _contentType.getName());
     302            }
     303        }
    245304        _headerVerified = true;
    246305    }
     
    288347            in.mark(10);
    289348            // following is a dup of that in verifyHeader()
    290             byte[] magic = new byte[MAGIC.length];
     349            byte[] magic = new byte[MAGIC_BYTES.length];
    291350            DataHelper.read(in, magic);
    292             if (!DataHelper.eq(magic, MAGIC))
     351            if (!DataHelper.eq(magic, MAGIC_BYTES))
    293352                throw new IOException("Not an su3 file");
    294353            skip(in, 1);
     
    311370            else
    312371                skip(in, getContentOffset());
    313             if (_signerPubkey == null)
    314                 throw new IOException("unknown signer: " + _signer);
     372            if (_verifySignature) {
     373                if (_signerPubkey == null)
     374                    throw new IOException("unknown signer: " + _signer + " for content type: " + _contentType.getName());
     375            }
    315376            if (migrateTo != null)  // else verify only
    316377                out = new FileOutputStream(migrateTo);
     
    325386                tot += read;
    326387            }
    327             byte[] sha = md.digest();
    328             din.on(false);
    329             Signature signature = new Signature(_sigType);
    330             signature.readBytes(in);
    331             SimpleDataStructure hash = _sigType.getHashInstance();
    332             hash.setData(sha);
    333             //System.out.println("hash\n" + HexDump.dump(sha));
    334             //System.out.println("sig\n" + HexDump.dump(signature.getData()));
    335             rv = _context.dsa().verifySignature(signature, hash, _signerPubkey);
     388            if (_verifySignature) {
     389                byte[] sha = md.digest();
     390                din.on(false);
     391                Signature signature = new Signature(_sigType);
     392                signature.readBytes(in);
     393                SimpleDataStructure hash = _sigType.getHashInstance();
     394                hash.setData(sha);
     395                //System.out.println("hash\n" + HexDump.dump(sha));
     396                //System.out.println("sig\n" + HexDump.dump(signature.getData()));
     397                rv = _context.dsa().verifySignature(signature, hash, _signerPubkey);
     398            } else {
     399                rv = true;
     400            }
    336401        } catch (DataFormatException dfe) {
    337402            IOException ioe = new IOException("foo");
     
    353418     *
    354419     *  @param content the input file, probably in zip format
    355      *  @param contentType 0-255, 0 for zip
     420     *  @param fileType 0-255, 0 for zip
     421     *  @param contentType 0-255
    356422     *  @param version 1-255 bytes when converted to UTF-8
    357423     *  @param signer ID of the public key, 1-255 bytes when converted to UTF-8
    358424     */
    359     public void write(File content, int contentType, String version,
     425    public void write(File content, int fileType, int contentType, String version,
    360426                      String signer, PrivateKey privkey, SigType sigType) throws IOException {
    361427        InputStream in = null;
     
    366432            MessageDigest md = sigType.getDigestInstance();
    367433            out = new DigestOutputStream(new BufferedOutputStream(new FileOutputStream(_file)), md);
    368             out.write(MAGIC);
     434            out.write(MAGIC_BYTES);
    369435            out.write((byte) 0);
    370436            out.write((byte) FILE_VERSION);
     
    387453            DataHelper.writeLong(out, 8, contentLength);
    388454            out.write((byte) 0);
    389             out.write((byte) TYPE_ZIP);
     455            if (fileType < 0 || fileType > 255)
     456                throw new IllegalArgumentException("bad content type");
     457            out.write((byte) fileType);
    390458            out.write((byte) 0);
    391459            if (contentType < 0 || contentType > 255)
     
    444512            String stype = null;
    445513            String ctype = null;
     514            String ftype = null;
     515            String kfile = null;
    446516            boolean error = false;
    447             Getopt g = new Getopt("SU3File", args, "t:c:");
     517            boolean shouldVerify = true;
     518            Getopt g = new Getopt("SU3File", args, "t:c:f:k:x");
    448519            int c;
    449520            while ((c = g.getopt()) != -1) {
     
    455526                case 'c':
    456527                    ctype = g.getOptarg();
     528                    break;
     529
     530                case 'f':
     531                    ftype = g.getOptarg();
     532                    break;
     533
     534                case 'k':
     535                    kfile = g.getOptarg();
     536                    break;
     537
     538                case 'x':
     539                    shouldVerify = false;
    457540                    break;
    458541
     
    477560                props.setProperty("prng.bufferSize", "16384");
    478561                new I2PAppContext(props);
    479                 ok = signCLI(stype, ctype, a.get(0), a.get(1), a.get(2), a.get(3), a.get(4), "");
     562                ok = signCLI(stype, ctype, ftype, a.get(0), a.get(1), a.get(2), a.get(3), a.get(4), "");
    480563            } else if ("bulksign".equals(cmd)) {
    481564                Properties props = new Properties();
     
    484567                ok = bulkSignCLI(stype, ctype, a.get(0), a.get(1), a.get(2), a.get(3));
    485568            } else if ("verifysig".equals(cmd)) {
    486                 ok = verifySigCLI(a.get(0));
     569                ok = verifySigCLI(a.get(0), kfile);
    487570            } else if ("keygen".equals(cmd)) {
    488571                ok = genKeysCLI(stype, a.get(0), a.get(1), a.get(2));
    489572            } else if ("extract".equals(cmd)) {
    490                 ok = extractCLI(a.get(0), a.get(1));
     573                ok = extractCLI(a.get(0), a.get(1), shouldVerify);
    491574            } else {
    492575                showUsageCLI();
     
    503586    private static final void showUsageCLI() {
    504587        System.err.println("Usage: SU3File keygen       [-t type|code] publicKeyFile keystore.ks you@mail.i2p");
    505         System.err.println("       SU3File sign         [-c type|code] [-t type|code] inputFile.zip signedFile.su3 keystore.ks version you@mail.i2p");
    506         System.err.println("       SU3File bulksign     [-c type|code] [-t type|code] directory keystore.ks version you@mail.i2p");
     588        System.err.println("       SU3File sign         [-t type|code] [-c type|code] [-f type|code] inputFile.zip signedFile.su3 keystore.ks version you@mail.i2p");
     589        System.err.println("       SU3File bulksign     [-t type|code] [-c type|code] directory keystore.ks version you@mail.i2p");
    507590        System.err.println("       SU3File showversion  signedFile.su3");
    508         System.err.println("       SU3File verifysig    signedFile.su3");
    509         System.err.println("       SU3File extract      signedFile.su3 outFile.zip");
     591        System.err.println("       SU3File verifysig    [-k file.crt] signedFile.su3  ## -k use this pubkey cert for verification");
     592        System.err.println("       SU3File extract      [-x] [-k file.crt] signedFile.su3 outFile   ## -x don't check sig");
    510593        System.err.println(dumpTypes());
    511594    }
     
    530613            buf.append('\n');
    531614        }
     615        buf.append("Available file types (-f):\n");
     616        buf.append("      ZIP\t(code: 0) DEFAULT\n");
     617        buf.append("      XML\t(code: 1)\n");
    532618        return buf.toString();
    533619    }
     
    555641        try {
    556642            SU3File file = new SU3File(signedFile);
     643            file.setVerifySignature(false);
    557644            String versionString = file.getVersionString();
    558645            if (versionString.equals(""))
     
    575662
    576663    /**
     664     *  Zip only
    577665     *  @return success
    578666     *  @since 0.9.9
     
    594682            while (keypw.length() < 6) {
    595683                System.out.print("Enter password for key \"" + signerName + "\": ");
    596                 keypw = DataHelper.readLine(System.in).trim();
     684                keypw = DataHelper.readLine(System.in);
     685                if (keypw == null) {
     686                    System.out.println("\nEOF reading password");
     687                    return false;
     688                }
     689                keypw = keypw.trim();
    597690                if (keypw.length() > 0 && keypw.length() < 6)
    598691                    System.out.println("Key password must be at least 6 characters");
     
    609702                continue;
    610703            String signedFile = inputFile.substring(0, inputFile.length() - 4) + ".su3";
    611             boolean rv = signCLI(stype, ctype, inputFile, signedFile, privateKeyFile, version, signerName, keypw);
     704            boolean rv = signCLI(stype, ctype, null, inputFile, signedFile, privateKeyFile, version, signerName, keypw);
    612705            if (!rv)
    613706                return false;
     
    623716     *  @since 0.9.9
    624717     */
    625     private static final boolean signCLI(String stype, String ctype, String inputFile, String signedFile,
     718    private static final boolean signCLI(String stype, String ctype, String ftype, String inputFile, String signedFile,
    626719                                         String privateKeyFile, String version, String signerName, String keypw) {
    627720        SigType type = stype == null ? SigType.getByCode(Integer.valueOf(DEFAULT_SIG_CODE)) : SigType.parseSigType(stype);
     
    635728            return false;
    636729        }
    637         return signCLI(type, ct, inputFile, signedFile, privateKeyFile, version, signerName, keypw);
     730        int ft = TYPE_ZIP;
     731        if (ftype != null) {
     732            if (ftype.equalsIgnoreCase("ZIP")) {
     733                ft = TYPE_ZIP;
     734            } else if (ftype.equalsIgnoreCase("XML")) {
     735                ft = TYPE_XML;
     736            } else {
     737                try {
     738                    ft = Integer.parseInt(ftype);
     739                } catch (NumberFormatException nfe) {
     740                    ft = -1;
     741                }
     742                if (ft != TYPE_ZIP && ft != TYPE_XML) {
     743                    System.out.println("File type " + ftype + " is not supported");
     744                    return false;
     745                }
     746            }
     747        }
     748        return signCLI(type, ct, ft, inputFile, signedFile, privateKeyFile, version, signerName, keypw);
    638749    }
    639750
     
    642753     *  @since 0.9.9
    643754     */
    644     private static final boolean signCLI(SigType type, ContentType ctype, String inputFile, String signedFile,
     755    private static final boolean signCLI(SigType type, ContentType ctype, int ftype, String inputFile, String signedFile,
    645756                                         String privateKeyFile, String version, String signerName, String keypw) {
    646757        try {
    647758            while (keypw.length() < 6) {
    648759                System.out.print("Enter password for key \"" + signerName + "\": ");
    649                 keypw = DataHelper.readLine(System.in).trim();
     760                keypw = DataHelper.readLine(System.in);
     761                if (keypw == null) {
     762                    System.out.println("\nEOF reading password");
     763                    return false;
     764                }
     765                keypw = keypw.trim();
    650766                if (keypw.length() > 0 && keypw.length() < 6)
    651767                    System.out.println("Key password must be at least 6 characters");
     
    658774            }
    659775            SU3File file = new SU3File(signedFile);
    660             file.write(new File(inputFile), ctype.getCode(), version, signerName, pk, type);
     776            file.write(new File(inputFile), ftype, ctype.getCode(), version, signerName, pk, type);
    661777            System.out.println("Input file '" + inputFile + "' signed and written to '" + signedFile + "'");
    662778            return true;
     
    673789
    674790    /** @return valid */
    675     private static final boolean verifySigCLI(String signedFile) {
     791    private static final boolean verifySigCLI(String signedFile, String pkFile) {
    676792        InputStream in = null;
    677793        try {
    678794            SU3File file = new SU3File(signedFile);
     795            if (pkFile != null)
     796                file.setPublicKeyCertificate(new File(pkFile));
    679797            boolean isValidSignature = file.verify();
    680798            if (isValidSignature)
     
    694812     *  @since 0.9.9
    695813     */
    696     private static final boolean extractCLI(String signedFile, String outFile) {
     814    private static final boolean extractCLI(String signedFile, String outFile, boolean verifySig) {
    697815        InputStream in = null;
    698816        try {
    699817            SU3File file = new SU3File(signedFile);
     818            file.setVerifySignature(verifySig);
    700819            File out = new File(outFile);
    701820            boolean ok = file.verifyAndMigrate(out);
     
    741860            while (alias.length() == 0) {
    742861                System.out.print("Enter key name (example@mail.i2p): ");
    743                 alias = DataHelper.readLine(System.in).trim();
     862                alias = DataHelper.readLine(System.in);
     863                if (alias == null) {
     864                    System.out.println("\nEOF reading key name");
     865                    return false;
     866                }
     867                alias = alias.trim();
    744868            }
    745869            while (keypw.length() < 6) {
    746870                System.out.print("Enter new key password: ");
    747                 keypw = DataHelper.readLine(System.in).trim();
     871                keypw = DataHelper.readLine(System.in);
     872                if (keypw == null) {
     873                    System.out.println("\nEOF reading password");
     874                    return false;
     875                }
     876                keypw = keypw.trim();
    748877                if (keypw.length() > 0 && keypw.length() < 6)
    749878                    System.out.println("Key password must be at least 6 characters");
     
    773902        return true;
    774903    }
     904
     905    /**
     906     *  For the -k CLI option
     907     *  @return non-null, throws IOE on all errors
     908     *  @since 0.9.15
     909     */
     910    private static PublicKey loadKey(File kd) throws IOException {
     911        InputStream fis = null;
     912        try {
     913            fis = new FileInputStream(kd);
     914            CertificateFactory cf = CertificateFactory.getInstance("X.509");
     915            X509Certificate cert = (X509Certificate)cf.generateCertificate(fis);
     916            cert.checkValidity();
     917            return cert.getPublicKey();
     918        } catch (GeneralSecurityException gse) {
     919            IOException ioe = new IOException("cert error");
     920            ioe.initCause(gse);
     921            throw ioe;
     922        } finally {
     923            try { if (fis != null) fis.close(); } catch (IOException foo) {}
     924        }
     925    }
    775926}
  • core/java/src/net/i2p/crypto/SigType.java

    r6fa2a41 re3be1d1  
    179179    }
    180180
     181    /**
     182     *  @return true if supported in this JVM
     183     *  @since 0.9.15
     184     */
     185    public static boolean isAvailable(int code) {
     186        SigType type = getByCode(code);
     187        if (type == null)
     188            return false;
     189        return type.isAvailable();
     190    }
     191
     192    /**
     193     *  @param stype number or name
     194     *  @return true if supported in this JVM
     195     *  @since 0.9.15
     196     */
     197    public static boolean isAvailable(String stype) {
     198        SigType type = parseSigType(stype);
     199        if (type == null)
     200            return false;
     201        return type.isAvailable();
     202    }
     203
    181204    private static final Map<Integer, SigType> BY_CODE = new HashMap<Integer, SigType>();
    182205
  • core/java/src/net/i2p/data/Base32.java

    r6fa2a41 re3be1d1  
    5757
    5858    private final static byte BAD_ENCODING = -9; // Indicates error in encoding
     59
    5960    /** Defeats instantiation. */
    6061    private Base32() { // nop
     
    137138
    138139    /**
     140     *  Returns lower case.
     141     *  Does not add trailing '='.
     142     *
    139143     *  @param source if null will return ""
    140144     */
     
    144148
    145149    /**
     150     * Returns lower case.
     151     * Does not add trailing '='.
     152     *
    146153     * @param source The data to convert non-null
    147154     */
     
    183190     * Decodes data from Base32 notation and
    184191     * returns it as a string.
     192     * Case-insensitive.
     193     * Does not allow trailing '='.
    185194     *
    186195     * @param s the string to decode, if null returns null
     
    195204
    196205    /**
     206     * Case-insensitive.
     207     * Does not allow trailing '='.
     208     *
    197209     * @param s non-null
    198210     * @return decoded data, null on error
  • core/java/src/net/i2p/data/KeysAndCert.java

    r6fa2a41 re3be1d1  
    131131    }
    132132   
    133     /** the public key has enough randomness in it to use it by itself for speed */
     133    /** the signing key has enough randomness in it to use it by itself for speed */
    134134    @Override
    135135    public int hashCode() {
    136         if (_publicKey == null)
     136        // don't use public key, some app devs thinking of using
     137        // an all-zeros or leading-zeros public key for destinations
     138        if (_signingKey == null)
    137139            return 0;
    138         return _publicKey.hashCode();
     140        return _signingKey.hashCode();
    139141    }
    140142   
    141143    @Override
    142144    public String toString() {
    143         StringBuilder buf = new StringBuilder(64);
     145        StringBuilder buf = new StringBuilder(256);
    144146        buf.append('[').append(getClass().getSimpleName()).append(": ");
    145147        buf.append("\n\tHash: ").append(getHash().toBase64());
  • router/java/src/net/i2p/router/RouterContext.java

    r6fa2a41 re3be1d1  
    1414import net.i2p.internal.InternalClientManager;
    1515import net.i2p.router.client.ClientManagerFacadeImpl;
     16import net.i2p.router.crypto.TransientSessionKeyManager;
    1617import net.i2p.router.dummy.*;
    1718import net.i2p.router.networkdb.kademlia.FloodfillNetworkDatabaseFacade;
     
    6869    // split up big lock on this to avoid deadlocks
    6970    private volatile boolean _initialized;
    70     private final Object _lock1 = new Object(), _lock2 = new Object();
     71    private final Object _lock1 = new Object(), _lock2 = new Object(), _lock3 = new Object();
    7172
    7273    private static final List<RouterContext> _contexts = new CopyOnWriteArrayList<RouterContext>();
     
    566567        return _appManager;
    567568    }
     569
     570    /**
     571     *  As of 0.9.15, this returns a dummy SessionKeyManager in I2PAppContext.
     572     *  Overridden in RouterContext to return the full TransientSessionKeyManager.
     573     *
     574     *  @since 0.9.15
     575     */
     576    @Override
     577    protected void initializeSessionKeyManager() {
     578        synchronized (_lock3) {
     579            if (_sessionKeyManager == null)
     580                //_sessionKeyManager = new PersistentSessionKeyManager(this);
     581                _sessionKeyManager = new TransientSessionKeyManager(this);
     582            _sessionKeyManagerInitialized = true;
     583        }
     584    }
    568585}
  • router/java/src/net/i2p/router/client/ClientConnectionRunner.java

    r6fa2a41 re3be1d1  
    2626import net.i2p.client.I2PClient;
    2727import net.i2p.crypto.SessionKeyManager;
    28 import net.i2p.crypto.TransientSessionKeyManager;
    2928import net.i2p.data.Destination;
    3029import net.i2p.data.Hash;
     
    4443import net.i2p.router.JobImpl;
    4544import net.i2p.router.RouterContext;
     45import net.i2p.router.crypto.TransientSessionKeyManager;
    4646import net.i2p.util.ConcurrentHashSet;
    4747import net.i2p.util.I2PThread;
  • router/java/src/net/i2p/router/client/ClientMessageEventListener.java

    r6fa2a41 re3be1d1  
    1212
    1313import net.i2p.CoreVersion;
     14import net.i2p.crypto.SigType;
    1415import net.i2p.data.Hash;
    1516import net.i2p.data.Payload;
     
    196197                _log.debug("Signature verified correctly on create session message");
    197198        } else {
    198             if (_log.shouldLog(Log.ERROR))
    199                 _log.error("Signature verification *FAILED* on a create session message.  Hijack attempt?");
    200199            // For now, we do NOT send a SessionStatusMessage - see javadoc above
    201             _runner.disconnectClient("Invalid signature on CreateSessionMessage");
     200            int itype = in.getDestination().getCertificate().getCertificateType();
     201            SigType stype = SigType.getByCode(itype);
     202            if (stype == null || !stype.isAvailable()) {
     203                _log.error("Client requested unsupported signature type " + itype);
     204                _runner.disconnectClient("Unsupported signature type " + itype);
     205            } else {
     206                _log.error("Signature verification failed on a create session message");
     207                _runner.disconnectClient("Invalid signature on CreateSessionMessage");
     208            }
    202209            return;
    203210        }
  • router/java/src/net/i2p/router/crypto/TransientSessionKeyManager.java

    r6fa2a41 re3be1d1  
    1 package net.i2p.crypto;
     1package net.i2p.router.crypto;
    22
    33/*
     
    2626
    2727import net.i2p.I2PAppContext;
     28import net.i2p.crypto.SessionKeyManager;
     29import net.i2p.crypto.TagSetHandle;
    2830import net.i2p.data.DataHelper;
    2931import net.i2p.data.PublicKey;
  • router/java/src/net/i2p/router/transport/udp/EstablishmentManager.java

    r6fa2a41 re3be1d1  
    969969
    970970    /**
     971     *  Called from UDPReceiver.
     972     *  Accelerate response to RelayResponse if we haven't sent it yet.
     973     *
     974     *  @since 0.9.15
     975     */
     976    void receiveHolePunch(InetAddress from, int fromPort) {
     977        RemoteHostId id = new RemoteHostId(from.getAddress(), fromPort);
     978        OutboundEstablishState state = _outboundStates.get(id);
     979        if (state != null) {
     980            boolean sendNow = state.receiveHolePunch();
     981            if (sendNow) {
     982                if (_log.shouldLog(Log.WARN))
     983                    _log.warn("Hole punch from " + state + ", sending SessionRequest now");
     984                notifyActivity();
     985            } else {
     986                if (_log.shouldLog(Log.WARN))
     987                    _log.warn("Hole punch from " + state + ", already sent SessionRequest");
     988            }
     989        } else {
     990            // HolePunch received before RelayResponse, and we didn't know the IP/port, or it changed
     991            if (_log.shouldLog(Log.WARN))
     992                _log.warn("No state found for hole punch from " + from + " port " + fromPort);
     993        }
     994    }
     995
     996    /**
    971997     *  Are IP and port valid? This is only for checking the relay response.
    972998     *  Reject all IPv6, for now, even if we are configured for it.
  • router/java/src/net/i2p/router/transport/udp/OutboundEstablishState.java

    r6fa2a41 re3be1d1  
    100100    private static final long MAX_DELAY = 15*1000;
    101101
     102    private static final long WAIT_FOR_HOLE_PUNCH_DELAY = 500;
     103
    102104    /**
    103105     *  @param claimedAddress an IP/port based RemoteHostId, or null if unknown
     
    557559        if (_currentState != OutboundState.OB_STATE_PENDING_INTRO)
    558560            return; // we've already successfully been introduced, so don't overwrite old settings
    559         _nextSend = _context.clock().now() + 500; // wait briefly for the hole punching
     561        _nextSend = _context.clock().now() + WAIT_FOR_HOLE_PUNCH_DELAY; // wait briefly for the hole punching
    560562        _currentState = OutboundState.OB_STATE_INTRODUCED;
    561563        if (_claimedAddress != null && bobPort == _bobPort && DataHelper.eq(bobIP, _bobIP)) {
     
    571573            _log.info("Introduced to " + _remoteHostId + ", now lets get on with establishing");
    572574    }
     575
     576    /**
     577     *  Accelerate response to RelayResponse if we haven't sent it yet.
     578     *
     579     *  @return true if we should send the SessionRequest now
     580     *  @since 0.9.15
     581     */
     582    synchronized boolean receiveHolePunch() {
     583        if (_currentState != OutboundState.OB_STATE_INTRODUCED)
     584            return false;
     585        if (_requestSentCount > 0)
     586            return false;
     587        long now = _context.clock().now();
     588        if (_log.shouldLog(Log.WARN))
     589            _log.warn(toString() + " accelerating SessionRequest by " + (_nextSend - now) + " ms");
     590        _nextSend = now;
     591        return true;
     592    }
    573593   
    574594    /** how long have we been trying to establish this session? */
  • router/java/src/net/i2p/router/transport/udp/UDPReceiver.java

    r6fa2a41 re3be1d1  
    22
    33import java.io.IOException;
     4import java.net.DatagramPacket;
    45import java.net.DatagramSocket;
    56import java.util.Arrays;
     
    221222                //}
    222223                UDPPacket packet = UDPPacket.acquire(_context, true);
     224                DatagramPacket dpacket = packet.getPacket();
    223225
    224226                // Android ICS bug
    225227                // http://code.google.com/p/android/issues/detail?id=24748
    226228                if (_isAndroid)
    227                     packet.getPacket().setLength(UDPPacket.MAX_PACKET_SIZE);
     229                    dpacket.setLength(UDPPacket.MAX_PACKET_SIZE);
    228230               
    229231                // block before we read...
     
    237239                    //    _log.info("Before blocking socket.receive on " + System.identityHashCode(packet));
    238240                    //synchronized (Runner.this) {
    239                         _socket.receive(packet.getPacket());
     241                        _socket.receive(dpacket);
    240242                    //}
    241                     int size = packet.getPacket().getLength();
     243                    int size = dpacket.getLength();
    242244                    if (_log.shouldLog(Log.INFO))
    243245                        _log.info("After blocking socket.receive: packet is " + size + " bytes on " + System.identityHashCode(packet));
     
    267269                        // nat hole punch packets are 0 bytes
    268270                        if (_log.shouldLog(Log.INFO))
    269                             _log.info("Received a 0 byte udp packet from " + packet.getPacket().getAddress() + ":" + packet.getPacket().getPort());
     271                            _log.info("Received a 0 byte udp packet from " + dpacket.getAddress() + ":" + dpacket.getPort());
     272                        _transport.getEstablisher().receiveHolePunch(dpacket.getAddress(), dpacket.getPort());
    270273                        packet.release();
    271274                    }
  • router/java/src/org/cybergarage/xml/parser/JaxpParser.java

    r6fa2a41 re3be1d1  
    2222package org.cybergarage.xml.parser;
    2323
     24import java.io.ByteArrayInputStream;
    2425import java.io.FilterInputStream;
    2526import java.io.IOException;
     
    2829import javax.xml.parsers.DocumentBuilder;
    2930import javax.xml.parsers.DocumentBuilderFactory;
     31import javax.xml.parsers.ParserConfigurationException;
    3032
    3133import org.cybergarage.xml.Node;
     
    3436import org.w3c.dom.Document;
    3537import org.w3c.dom.NamedNodeMap;
     38import org.xml.sax.EntityResolver;
    3639import org.xml.sax.InputSource;
    3740
     
    117120               
    118121                try {
     122                        // https://www.owasp.org/index.php/XML_External_Entity_%28XXE%29_Processing
    119123                        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
     124                        factory.setValidating(false);
     125                        factory.setNamespaceAware(true);
     126                        factory.setExpandEntityReferences(false);
     127                        try {
     128                            factory.setFeature("http://xml.org/sax/features/external-general-entities", false);
     129                        } catch (ParserConfigurationException pce) {}
     130                        try {
     131                            factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
     132                        } catch (ParserConfigurationException pce) {}
     133                        try {
     134                            factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
     135                        } catch (ParserConfigurationException pce) {}
     136                        try {
     137                            factory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
     138                        } catch (ParserConfigurationException pce) {}
    120139                        DocumentBuilder builder = factory.newDocumentBuilder();
     140                        builder.setEntityResolver(new BlankingResolver());
    121141                        InputSource inSrc = new InputSource(new NullFilterInputStream(inStream));
    122142                        Document doc = builder.parse(inSrc);
     
    164184                }
    165185        }
     186
     187        /**
     188         *  I2P -
     189         *  http://stackoverflow.com/questions/5883542/disable-xml-validation-based-on-external-dtd-xsd
     190         */
     191        private static class BlankingResolver implements EntityResolver {
     192                private static final byte[] DUMMY = new byte[0];
     193
     194                public InputSource resolveEntity(String arg0, String arg1) {
     195                        return new InputSource(new ByteArrayInputStream(DUMMY));
     196                }
     197        }
    166198}
Note: See TracChangeset for help on using the changeset viewer.