Changeset fef59141


Ignore:
Timestamp:
Jun 28, 2014 2:14:39 PM (6 years ago)
Author:
zzz <zzz@…>
Branches:
master
Children:
4407373
Parents:
f191e50
Message:

SAM: Cherrypick from patch in ticket #1318:

  • Add SIGNATURE_TYPE support to GENERATE and CREATE
  • Don't NPE checking dest+privkeys
  • Simplify HELLO checking
  • Don't require two params in HELLO message
  • Make MIN parameter optional too
  • Version checking fixes
  • Bump version to 3.1, only visible if requested
  • Cleanups, javadocs
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • apps/sam/java/src/net/i2p/sam/SAMHandlerFactory.java

    rf191e50 rfef59141  
    2525class SAMHandlerFactory {
    2626
    27     private static final String VERSION = "3.0";
     27    private static final String VERSION = "3.1";
    2828
    2929    /**
     
    5454        }
    5555
    56         // Message format: HELLO VERSION MIN=v1 MAX=v2
    57         if (tok.countTokens() != 4) {
    58             throw new SAMException("Bad format in HELLO message");
     56        // Message format: HELLO VERSION [MIN=v1] [MAX=v2]
     57        if (tok.countTokens() < 2) {
     58            throw new SAMException("Must start with HELLO VERSION");
    5959        }
    60         if (!tok.nextToken().equals("HELLO")) {
    61             throw new SAMException("Bad domain in HELLO message");
    62         }
    63         {
    64             String opcode;
    65             if (!(opcode = tok.nextToken()).equals("VERSION")) {
    66                 throw new SAMException("Unrecognized HELLO message opcode: '"
    67                                        + opcode + "'");
    68             }
     60        if (!tok.nextToken().equals("HELLO") ||
     61            !tok.nextToken().equals("VERSION")) {
     62            throw new SAMException("Must start with HELLO VERSION");
    6963        }
    7064
    7165        Properties props = SAMUtils.parseParams(tok);
    72         if (props.isEmpty()) {
    73             throw new SAMException("No parameters in HELLO VERSION message");
    74         }
    7566
    7667        String minVer = props.getProperty("MIN");
    7768        if (minVer == null) {
    78             throw new SAMException("Missing MIN parameter in HELLO VERSION message");
     69            //throw new SAMException("Missing MIN parameter in HELLO VERSION message");
     70            // MIN optional as of 0.9.14
     71            minVer = "1";
    7972        }
    8073
     
    127120     */
    128121    private static String chooseBestVersion(String minVer, String maxVer) {
     122        if (VersionComparator.comp(VERSION, minVer) >= 0 &&
     123            VersionComparator.comp(VERSION, maxVer) <= 0)
     124            return VERSION;
    129125        // in VersionComparator, "3" < "3.0" so
    130126        // use comparisons carefully
    131         if (VersionComparator.comp("3.0", minVer) >= 0) {
    132             // Documentation said:
    133             // In order to force protocol version 3.0, the values of $min and $max
    134             // must be "3.0".
    135             int maxcomp = VersionComparator.comp("3", maxVer);
    136             if (maxcomp == 0 || maxVer.equals("3.0"))
    137                 return "3.0";  // spoof version
    138             if (maxcomp < 0)
    139                 return VERSION;
    140         }
     127        if (VersionComparator.comp("3.0", minVer) >= 0 &&
     128            VersionComparator.comp("3", maxVer) <= 0)
     129            return "3.0";
    141130        if (VersionComparator.comp("2.0", minVer) >= 0 &&
    142131            VersionComparator.comp("2", maxVer) <= 0)
     
    148137    }
    149138
    150     /* Get the major protocol version from a string */
     139    /* Get the major protocol version from a string, or -1 */
    151140    private static int getMajor(String ver) {
    152         if ( (ver == null) || (ver.indexOf('.') < 0) )
     141        if (ver == null)
    153142            return -1;
     143        int dot = ver.indexOf(".");
     144        if (dot == 0)
     145            return -1;
     146        if (dot > 0)
     147            ver = ver.substring(0, dot);
    154148        try {
    155             String major = ver.substring(0, ver.indexOf("."));
    156             return Integer.parseInt(major);
     149            return Integer.parseInt(ver);
    157150        } catch (NumberFormatException e) {
    158             return -1;
    159         } catch (ArrayIndexOutOfBoundsException e) {
    160151            return -1;
    161152        }
    162153    }
    163154
    164     /* Get the minor protocol version from a string */
     155    /* Get the minor protocol version from a string, or -1 */
    165156    private static int getMinor(String ver) {
    166157        if ( (ver == null) || (ver.indexOf('.') < 0) )
  • apps/sam/java/src/net/i2p/sam/SAMUtils.java

    rf191e50 rfef59141  
    2121import net.i2p.client.I2PClientFactory;
    2222import net.i2p.client.naming.NamingService;
     23import net.i2p.crypto.SigType;
    2324import net.i2p.data.Base64;
    2425import net.i2p.data.DataFormatException;
     
    3839
    3940    /**
    40      * Generate a random destination key
    41      *
    42      * @param priv Stream used to write the private key
    43      * @param pub Stream used to write the public key (may be null)
     41     * Generate a random destination key using DSA_SHA1 signature type.
     42     * Caller must close streams. Fails silently.
     43     *
     44     * @param priv Stream used to write the destination and private keys
     45     * @param pub Stream used to write the destination (may be null)
    4446     */
    4547    public static void genRandomKey(OutputStream priv, OutputStream pub) {
     48        genRandomKey(priv, pub, SigType.DSA_SHA1);
     49    }
     50
     51    /**
     52     * Generate a random destination key.
     53     * Caller must close streams. Fails silently.
     54     *
     55     * @param priv Stream used to write the destination and private keys
     56     * @param pub Stream used to write the destination (may be null)
     57     * @param sigType what signature type
     58     * @since 0.9.14
     59     */
     60    public static void genRandomKey(OutputStream priv, OutputStream pub, SigType sigType) {
    4661        //_log.debug("Generating random keys...");
    4762        try {
    4863            I2PClient c = I2PClientFactory.createClient();
    49             Destination d = c.createDestination(priv);
     64            Destination d = c.createDestination(priv, sigType);
    5065            priv.flush();
    5166
     
    86101     */
    87102    public static boolean checkPrivateDestination(String dest) {
    88         ByteArrayInputStream destKeyStream = new ByteArrayInputStream(Base64.decode(dest));
     103        byte[] b = Base64.decode(dest);
     104        if (b == null || b.length < 663)
     105            return false;
     106        ByteArrayInputStream destKeyStream = new ByteArrayInputStream(b);
    89107        try {
    90108                Destination d = new Destination();
  • apps/sam/java/src/net/i2p/sam/SAMv1Handler.java

    rf191e50 rfef59141  
    2525import net.i2p.client.I2PClient;
    2626import net.i2p.client.I2PSessionException;
     27import net.i2p.crypto.SigType;
    2728import net.i2p.data.Base64;
    2829import net.i2p.data.DataFormatException;
     
    321322
    322323               
    323   SAMStreamSession newSAMStreamSession(String destKeystream, String direction, Properties props )
     324  private SAMStreamSession newSAMStreamSession(String destKeystream, String direction, Properties props )
    324325    throws IOException, DataFormatException, SAMException
    325326  {
     
    331332
    332333        if (opcode.equals("GENERATE")) {
    333             if (!props.isEmpty()) {
    334                 if (_log.shouldLog(Log.DEBUG))
    335                     _log.debug("Properties specified in DEST GENERATE message");
    336                 return false;
    337             }
    338 
    339             ByteArrayOutputStream priv = new ByteArrayOutputStream();
    340             ByteArrayOutputStream pub = new ByteArrayOutputStream();
     334            String sigTypeStr = props.getProperty("SIGNATURE_TYPE");
     335            SigType sigType;
     336            if (sigTypeStr != null) {
     337                sigType = SigType.parseSigType(sigTypeStr);
     338                if (sigType == null) {
     339                    writeString("DEST REPLY RESULT=I2P_ERROR MESSAGE=\"SIGNATURE_TYPE " +
     340                                sigTypeStr + " unsupported\"\n");
     341                    return false;
     342                }
     343            } else {
     344                sigType = SigType.DSA_SHA1;
     345            }
     346
     347            ByteArrayOutputStream priv = new ByteArrayOutputStream(663);
     348            ByteArrayOutputStream pub = new ByteArrayOutputStream(387);
    341349           
    342             SAMUtils.genRandomKey(priv, pub);
     350            SAMUtils.genRandomKey(priv, pub, sigType);
    343351            return writeString("DEST REPLY"
    344352                               + " PUB="
     
    348356                               + "\n");
    349357        } else {
     358            writeString("DEST REPLY RESULT=I2P_ERROR MESSAGE=\"DEST GENERATE required\"");
    350359            if (_log.shouldLog(Log.DEBUG))
    351360                _log.debug("Unrecognized DEST message opcode: \"" + opcode + "\"");
  • apps/sam/java/src/net/i2p/sam/SAMv3Handler.java

    rf191e50 rfef59141  
    2929import net.i2p.client.I2PClient;
    3030import net.i2p.client.I2PSessionException;
     31import net.i2p.crypto.SigType;
    3132import net.i2p.data.Base64;
    3233import net.i2p.data.DataFormatException;
     
    488489                                props.remove("DESTINATION");
    489490
    490 
    491491                                if (dest.equals("TRANSIENT")) {
    492492                                        if (_log.shouldLog(Log.DEBUG))
    493493                                                _log.debug("TRANSIENT destination requested");
    494                                         ByteArrayOutputStream priv = new ByteArrayOutputStream(640);
    495                                         SAMUtils.genRandomKey(priv, null);
     494                                        String sigTypeStr = props.getProperty("SIGNATURE_TYPE");
     495                                        SigType sigType;
     496                                        if (sigTypeStr != null) {
     497                                                sigType = SigType.parseSigType(sigTypeStr);
     498                                                if (sigType == null) {
     499                                                        return writeString("SESSION STATUS RESULT=I2P_ERROR MESSAGE=\"SIGNATURE_TYPE "
     500                                                                           + sigTypeStr + " unsupported\"\n");
     501                                                }
     502                                                props.remove("SIGNATURE_TYPE");
     503                                        } else {
     504                                                sigType = SigType.DSA_SHA1;
     505                                        }
     506                                        ByteArrayOutputStream priv = new ByteArrayOutputStream(663);
     507                                        SAMUtils.genRandomKey(priv, null, sigType);
    496508
    497509                                        dest = Base64.encode(priv.toByteArray());
     
    499511                                        if (_log.shouldLog(Log.DEBUG))
    500512                                                _log.debug("Custom destination specified [" + dest + "]");
    501                                 }
    502 
    503                                 if (!SAMUtils.checkPrivateDestination(dest))
    504                                         return writeString("SESSION STATUS RESULT=INVALID_KEY\n");
     513                                        if (!SAMUtils.checkPrivateDestination(dest))
     514                                                return writeString("SESSION STATUS RESULT=INVALID_KEY\n");
     515                                }
     516
    505517
    506518                                nick = props.getProperty("ID");
  • history.txt

    rf191e50 rfef59141  
     12014-06-28 zzz
     2 * SAM:
     3   - Support SIGNATURE_TYPE, bump to 3.1 (ticket #1318)
     4   - Private key checking fixes (ticket #1318)
     5   - Parameter parsing fixes (ticket #1325)
     6   - Cleanups
     7
     82014-06-24 zzz
     9 * Streaming; Drop the preliminary channel implementations,
     10   as they don't work and can't ever work as designed.
     11
    1122014-06-23 zzz
    213 * Streaming:
  • router/java/src/net/i2p/router/RouterVersion.java

    rf191e50 rfef59141  
    1919    public final static String ID = "Monotone";
    2020    public final static String VERSION = CoreVersion.VERSION;
    21     public final static long BUILD = 9;
     21    public final static long BUILD = 10;
    2222
    2323    /** for example "-test" */
Note: See TracChangeset for help on using the changeset viewer.