Changeset 2abd59e for apps


Ignore:
Timestamp:
May 24, 2019 5:42:11 PM (11 months ago)
Author:
zzz <zzz@…>
Branches:
master
Children:
c2e2cc2
Parents:
47c64c2e
Message:

i2ptunnel: Per-client auth config
Hide encryption key for per-client auth
User-select: all for dest and reg fields

Location:
apps/i2ptunnel
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • apps/i2ptunnel/java/src/net/i2p/i2ptunnel/ui/GeneralHelper.java

    r47c64c2e r2abd59e  
    570570            String authType = getProperty(tunnel, "i2cp.leaseSetAuthType", "0");
    571571            if (authType.equals("2")) {
    572                 // shared PSK key
    573                 rv = 4;
    574                 // per-client PSK key
    575                 // TODO
    576                 //rv = 6;
     572                if (getProperty(tunnel, "i2cp.leaseSetClient.psk.0", null) != null) {
     573                    // per-client PSK key
     574                    rv = 6;
     575                } else {
     576                    // shared PSK key
     577                    rv = 4;
     578                }
    577579            } else if (authType.equals("1")) {
    578580                rv = 8;
     
    596598    public String getBlindedPassword(int tunnel) {
    597599        return getProperty(tunnel, "i2cp.leaseSetSecret", "");
     600    }
     601   
     602    /**
     603     *  List of b64 name : b64key
     604     *  Pubkeys for DH, privkeys for PSK
     605     *  @param isDH true for DH, false for PSK
     606     *  @return non-null
     607     *  @since 0.9.41
     608     */
     609    public List<String> getClientAuths(int tunnel, boolean isDH) {
     610        List<String> rv = new ArrayList<String>(4);
     611        String pfx = isDH ? "i2cp.leaseSetClient.dh." : "i2cp.leaseSetClient.psk.";
     612        int i = 0;
     613        String p;
     614        while ((p = getProperty(tunnel, pfx + i, null)) != null) {
     615             rv.add(p);
     616             i++;
     617        }
     618        return rv;
    598619    }
    599620
     
    869890                    TunnelConfig._nonProxyNoShowSet.contains(key))
    870891                    continue;
     892                if (key.startsWith("i2cp.leaseSetClient."))
     893                    continue;
    871894                sorted.put(key, (String)e.getValue());
    872895            }
  • apps/i2ptunnel/java/src/net/i2p/i2ptunnel/ui/TunnelConfig.java

    r47c64c2e r2abd59e  
    33import java.security.GeneralSecurityException;
    44import java.util.Arrays;
     5import java.util.ArrayList;
     6import java.util.Collections;
    57import java.util.HashSet;
     8import java.util.List;
    69import java.util.Map;
    710import java.util.Properties;
     
    1518import net.i2p.crypto.SigType;
    1619import net.i2p.data.Base64;
     20import net.i2p.data.DataHelper;
    1721import net.i2p.data.Destination;
    1822import net.i2p.data.SimpleDataStructure;
     
    7882    private String _filterDefinition;
    7983    private int _encryptMode;
     84    private String[] _clientNames;
     85    private String[] _clientKeys;
     86    private Set<Integer> _clientRevocations;
     87    // b64name : b64key
     88    private String _newClientName;
     89    private String _newClientKey;
     90    private boolean _addClientAuth;
    8091
    8192    public TunnelConfig() {
     
    270281        else
    271282            _otherOptions.remove("i2cp.leaseSetSecret");
     283    }
     284
     285    /**
     286     * Multiple entries in form
     287     * @since 0.9.41
     288     */
     289    public void addClientNames(String[] s) {
     290       _clientNames = s;
     291    }
     292
     293    /**
     294     * Multiple entries in form
     295     * Handles either order addClientName/addClientKey
     296     * @since 0.9.41
     297     */
     298    public void addClientKeys(String[] s) {
     299       _clientKeys = s;
     300    }
     301
     302    /**
     303     * Multiple entries in form
     304     * @since 0.9.41
     305     */
     306    public void revokeClients(String[] s) {
     307        _clientRevocations = new HashSet<Integer>(4);
     308        for (String k : s) {
     309            try {
     310                _clientRevocations.add(Integer.valueOf(Integer.parseInt(k)));
     311            } catch (NumberFormatException nfe) {}
     312        }
     313    }
     314
     315    /**
     316     * Handles either order newClientName/newClientKey
     317     * @since 0.9.41
     318     */
     319    public void newClientName(String s) {
     320        _newClientName = s;
     321    }
     322
     323    /**
     324     * Handles either order newClientName/newClientKey
     325     * @since 0.9.41
     326     */
     327    public void newClientKey(String s) {
     328        _newClientKey = s;
     329    }
     330
     331    /**
     332     * @since 0.9.41
     333     */
     334    public void setAddClient(boolean val) {
     335        _addClientAuth = val;
    272336    }
    273337
     
    858922            break;
    859923
     924        }
     925
     926        // per-client keys
     927        String pfx;
     928        if (_encryptMode == 6 || _encryptMode == 7) {
     929            pfx = OPT + "i2cp.leaseSetClient.psk.";
     930        } else if (_encryptMode == 8 || _encryptMode == 9) {
     931            pfx = OPT + "i2cp.leaseSetClient.dh.";
     932        } else {
     933            pfx = null;
     934        }
     935        List<String> clientAuth = null;
     936        if (pfx != null) {
     937            if (_clientNames != null && _clientKeys != null && _clientNames.length == _clientKeys.length) {
     938                clientAuth = new ArrayList<String>(4);
     939            } else if (_addClientAuth || _encryptMode == 6 || _encryptMode == 7) {
     940                // force one client for per-client PSK
     941                clientAuth = new ArrayList<String>(1);
     942                if (!_addClientAuth) {
     943                    _addClientAuth = true;
     944                    if (_newClientName == null || _newClientName.length() == 0)
     945                        _newClientName = Base64.encode(DataHelper.getUTF8(GeneralHelper._t("Client", _context) + " 1"));
     946                }
     947            }
     948        }
     949        if (pfx != null && clientAuth != null) {
     950            if (_clientNames != null && _clientKeys != null && _clientNames.length == _clientKeys.length) {
     951                for (int i = 0; i < _clientNames.length; i++) {
     952                    if (_clientRevocations != null && _clientRevocations.contains(Integer.valueOf(i)))
     953                       continue;
     954                    String name = _clientNames[i];
     955                    String key = _clientKeys[i];
     956                    byte[] b = Base64.decode(key);
     957                    if (b == null || b.length != 32)
     958                       continue;
     959                    if (name.length() > 0)
     960                        name = Base64.encode(DataHelper.getUTF8(name));
     961                    else
     962                        name = Base64.encode(DataHelper.getUTF8(GeneralHelper._t("Client", _context) + ' ' + (i + 1)));
     963                    clientAuth.add(name + ':' + key);
     964                }
     965            }
     966            if (_addClientAuth && _newClientName != null) {
     967                String name = _newClientName;
     968                if (name.length() > 0)
     969                    name = Base64.encode(DataHelper.getUTF8(name));
     970                else
     971                    name = Base64.encode(DataHelper.getUTF8(GeneralHelper._t("Client", _context) + ' ' + (clientAuth.size() + 1)));
     972                String key;
     973                if (_encryptMode == 6 || _encryptMode == 7) {
     974                    byte[] b = new byte[32];
     975                    _context.random().nextBytes(b);
     976                    key = Base64.encode(b);
     977                    clientAuth.add(name + ':' + key);
     978                } else if (_encryptMode == 8 || _encryptMode == 9) {
     979                    key = _newClientKey;
     980                    byte[] b = Base64.decode(key);
     981                    if (b != null && b.length == 32) {
     982                        // key required for DH
     983                        clientAuth.add(name + ':' + key);
     984                    }
     985                }
     986            }
     987            int i = 0;
     988            for (String auth : clientAuth) {
     989                config.put(pfx + i, auth);
     990                i++;
     991            }
    860992        }
    861993    }
     
    9341066         "inbound.randomKey", "outbound.randomKey", "i2cp.leaseSetSigningPrivateKey", "i2cp.leaseSetPrivateKey",
    9351067         I2PTunnelServer.PROP_ALT_PKF,
    936          "i2cp.leaseSetSecret", "i2cp.leaseSetType", "i2cp.leaseSetAuthType"
     1068         "i2cp.leaseSetSecret", "i2cp.leaseSetType", "i2cp.leaseSetAuthType", "i2cp.leaseSetPrivKey"
    9371069        };
    9381070    private static final String _httpServerOpts[] = {
  • apps/i2ptunnel/java/src/net/i2p/i2ptunnel/web/EditBean.java

    r47c64c2e r2abd59e  
    225225    public String getBlindedPassword(int tunnel) {
    226226        return _helper.getBlindedPassword(tunnel);
     227    }
     228   
     229    /**
     230     *  List of b64 name : b64key
     231     *  Pubkeys for DH, privkeys for PSK
     232     *  @param isDH true for DH, false for PSK
     233     *  @return non-null
     234     *  @since 0.9.41
     235     */
     236    public List<String> getClientAuths(int tunnel, boolean isDH) {
     237        return _helper.getClientAuths(tunnel, isDH);
    227238    }
    228239   
  • apps/i2ptunnel/java/src/net/i2p/i2ptunnel/web/IndexBean.java

    r47c64c2e r2abd59e  
    873873    }
    874874
     875    /**
     876     * Multiple entries in form
     877     * @since 0.9.41
     878     */
     879    public void setNofilter_clientName(String[] s) {
     880        if (s != null) {
     881            _config.addClientNames(s);
     882        }
     883    }
     884
     885
     886    /**
     887     * Multiple entries in form
     888     * @since 0.9.41
     889     */
     890    public void setclientKey(String[] s) {
     891        if (s != null) {
     892            _config.addClientKeys(s);
     893        }
     894    }
     895
     896    /**
     897     * Multiple entries in form
     898     * Values are integers
     899     * @since 0.9.41
     900     */
     901    public void setRevokeClient(String[] s) {
     902        if (s != null) {
     903            _config.revokeClients(s);
     904        }
     905    }
     906
     907    /**
     908     * @since 0.9.41
     909     */
     910    public void setNofilter_newClientName(String s) {
     911        if (s != null) {
     912            _config.newClientName(s.trim());
     913        }
     914    }
     915
     916    /**
     917     * @since 0.9.41
     918     */
     919    public void setNewClientKey(String s) {
     920        if (s != null) {
     921            _config.newClientKey(s.trim());
     922        }
     923    }
     924
     925    /**
     926     * @since 0.9.41
     927     */
     928    public void setAddClient(String moo) {
     929        _config.setAddClient(true);
     930    }
     931
    875932    /** @since 0.8.9 */
    876933    public void setDCC(String moo) {
  • apps/i2ptunnel/jsp/editServer.jsi

    r47c64c2e r2abd59e  
    156156        </tr><tr>
    157157            <td>
    158                 <div class="displayText" title="<%=intl._t("Read Only: Local Destination (if known)")%>" tabindex="0" onblur="resetScrollLeft(this)"><%=editBean.getDestinationBase64(curTunnel)%></div>
     158                <div class="displayText" style="user-select: all;" title="<%=intl._t("Read Only: Local Destination (if known)")%>" tabindex="0" onblur="resetScrollLeft(this)"><%=editBean.getDestinationBase64(curTunnel)%></div>
    159159            </td><td>
    160160                    <% String value3 = editBean.getPrivateKeyFile(curTunnel);
     
    486486        </tr><tr>
    487487            <td>
     488<%
     489                if (allowBlinding && editBean.isAdvanced()) {
     490%>
     491                <b><%=intl._t("Optional lookup password")%>:</b>
     492<%
     493                } // allowBlinding
     494%>
     495            </td><td>
     496<%
     497                // even if not shown, we need to preserve the param as a hidden input below
     498                // as it's the key we use to decrypt the PSK/DH LS on the router side
     499                boolean showSharedKey = curEncryptMode.equals("1") || curEncryptMode.equals("4") || curEncryptMode.equals("5");
     500                if (showSharedKey) {
     501%>
    488502                <b><%=intl._t("Encryption Key")%></b>
    489             </td><td>
     503<%
     504                } // showSharedKey
     505%>
     506            </td>
     507        </tr><tr>
     508            <td>
    490509<%
    491510                if (allowBlinding && editBean.isAdvanced()) {
    492511%>
    493                 <b><%=intl._t("Optional lookup password")%>:</b>
     512                <input type="password" name="nofilter_blindedPassword" title="<%=intl._t("Set password required to access this service")%>" value="<%=editBean.getBlindedPassword(curTunnel)%>" class="freetext password" />
    494513<%
    495514                } // allowBlinding
    496515%>
    497             </td>
    498         </tr><tr>
    499             <td>
    500                 <textarea rows="1" style="height: 3em;" cols="44" id="leasesetKey" name="encryptKey" title="<%=intl._t("Encryption key required to access this service")%>" wrap="off" readonly="readonly"><%=editBean.getEncryptKey(curTunnel)%></textarea>
    501             </td><td>
     516            </td><td>
     517                <input type="<%=showSharedKey ? "text" : "hidden"%>" style="user-select: all;" size="44" id="leasesetKey" name="encryptKey" title="<%=intl._t("Encryption key required to access this service")%>" readonly="readonly" value="<%=editBean.getEncryptKey(curTunnel)%>" class="freetext"/>
     518            </td>
     519        </tr>
    502520<%
    503521                if (allowBlinding && editBean.isAdvanced()) {
    504 %>
    505                 <input type="password" name="nofilter_blindedPassword" title="<%=intl._t("Set password required to access this service")%>" value="<%=editBean.getBlindedPassword(curTunnel)%>" class="freetext password" />
    506 <%
     522                    boolean pskClient = curEncryptMode.equals("6") || curEncryptMode.equals("7");
     523                    boolean dhClient = curEncryptMode.equals("8") || curEncryptMode.equals("9");
     524                    if (pskClient || dhClient) {
     525                        // b64Name:b64Key
     526                        java.util.List<String> clientAuths = editBean.getClientAuths(curTunnel, dhClient);
     527                        if (!clientAuths.isEmpty()) {
     528%>
     529        <tr><td><b><%=intl._t("Revoke?")%>&nbsp;&nbsp;&nbsp;&nbsp;<%=intl._t("Client Name")%></b></td><td><b><%=intl._t("Client Key")%></b></td></tr>
     530<%
     531                            int i = 0;
     532                            for (String clientAuth : clientAuths) {
     533                                String[] split = net.i2p.data.DataHelper.split(clientAuth, ":", 2);
     534                                String cname, ckey;
     535                                if (split.length == 2) {
     536                                    cname = split[0];
     537                                    ckey = split[1];
     538                                } else {
     539                                    cname = "";
     540                                    ckey = split[0];
     541                                }
     542                                if (cname.length() > 0) {
     543                                    cname = net.i2p.data.DataHelper.escapeHTML(net.i2p.data.DataHelper.getUTF8(net.i2p.data.Base64.decode(cname)));
     544                                } else {
     545                                    cname = intl._t("Client") + ' ' + (i + 1);
     546                                }
     547%>
     548                <tr>
     549                <td><input value="<%=i%>" type="checkbox" name="revokeClient" class="tickbox" />
     550                    <input type="text" value="<%=cname%>" size="44" name="nofilter_clientName" class="freetext" /></td>
     551                <td><input type="text" id="leasesetKey" style="user-select: all;" value="<%=ckey%>" size="44" name="clientKey" readonly="readonly" class="freetext" />
     552                </tr>
     553<%
     554                                i++;
     555                            } // for
     556                        } // isEmpty
     557%>
     558        <tr><td><b><%=intl._t("Add?")%>&nbsp;&nbsp;&nbsp;&nbsp;<%=intl._t("Client Name")%></b></td><td>
     559<%
     560                            if (dhClient) {
     561%>
     562                    <b><%=intl._t("Client Key")%></b>
     563<%
     564                            } // dhClient
     565%>
     566                </td></tr><tr>
     567                <td><input value="1" type="checkbox" name="addClient" class="tickbox" />
     568                    <input type="text" value="<%=intl._t("Client") + ' ' + (clientAuths.size() + 1)%>" size="44" name="nofilter_newClientName" class="freetext" /></td>
     569                <td>
     570<%
     571                            if (dhClient) {
     572%>
     573                    <input type="text" id="leasesetKey" value="" size="44" maxlength="44" name="newClientKey" class="freetext" />
     574<%
     575                            } // dhClient
     576%>
     577                </td></tr>
     578<%
     579                    } // pskClient || dhClient
    507580                } // allowBlinding
    508 %>
    509             </td>
    510         </tr>
    511 <%
    512581            } // !isOffline
    513582%>
  • apps/i2ptunnel/jsp/register.jsp

    r47c64c2e r2abd59e  
    151151    <tr>
    152152        <td>
    153             <div class="displayText" tabindex="0" title="<%=intl._t("Copy and paste this to the registration site")%>"><% he.write(out); %></div>
     153            <div class="displayText" tabindex="0" style="user-select: all; "title="<%=intl._t("Copy and paste this to the registration site")%>"><% he.write(out); %></div>
    154154        </td>
    155155    </tr>
     
    172172    <tr>
    173173        <td>
    174             <div class="displayText" tabindex="0" title="<%=intl._t("Copy and paste this to the registration site")%>"><% he.writeRemove(out); %></div>
     174            <div class="displayText" tabindex="0" style="user-select: all;" title="<%=intl._t("Copy and paste this to the registration site")%>"><% he.writeRemove(out); %></div>
    175175        </td>
    176176    </tr>
     
    212212    <tr>
    213213        <td>
    214             <div class="displayText" tabindex="0" title="<%=intl._t("Copy and paste this to the registration site")%>"><% he.write(out); %></div>
     214            <div class="displayText" tabindex="0" style="user-select: all;" title="<%=intl._t("Copy and paste this to the registration site")%>"><% he.write(out); %></div>
    215215        </td>
    216216    </tr>
     
    245245    <tr>
    246246        <td>
    247             <div class="displayText" tabindex="0" title="<%=intl._t("Copy and paste this to the registration site")%>"><% he.write(out); %></div>
     247            <div class="displayText" tabindex="0" style="user-select: all;" title="<%=intl._t("Copy and paste this to the registration site")%>"><% he.write(out); %></div>
    248248        </td>
    249249    </tr>
     
    282282    <tr>
    283283        <td>
    284             <div class="displayText" tabindex="0" title="<%=intl._t("Copy and paste this to the registration site")%>"><% he.write(out); %></div>
     284            <div class="displayText" tabindex="0" style="user-select: all;" title="<%=intl._t("Copy and paste this to the registration site")%>"><% he.write(out); %></div>
    285285        </td>
    286286    </tr>
     
    319319    <tr>
    320320        <td>
    321             <div class="displayText" tabindex="0" title="<%=intl._t("Copy and paste this to the registration site")%>"><% he.write(out); %></div>
     321            <div class="displayText" tabindex="0" style="user-select: all;" title="<%=intl._t("Copy and paste this to the registration site")%>"><% he.write(out); %></div>
    322322        </td>
    323323    </tr>
     
    352352                       he2.signInner(spk);
    353353                       he2.sign(spk3);
    354                 %><tr><td><div class="displayText" tabindex="0" title="<%=intl._t("Copy and paste this to the registration site")%>"><% he2.write(out); %></div></td></tr>
     354                %><tr><td><div class="displayText" tabindex="0" style="user-select: all;" title="<%=intl._t("Copy and paste this to the registration site")%>"><% he2.write(out); %></div></td></tr>
    355355                <tr><td class="infohelp"><%=intl._t("This will add an alternate destination for {0}", name)%></td></tr>
    356356<%
     
    386386    <tr>
    387387        <td>
    388             <div class="displayText" tabindex="0" title="<%=intl._t("Copy and paste this to the registration site")%>"><% he.write(out); %></div>
     388            <div class="displayText" tabindex="0" style="user-select: all;" title="<%=intl._t("Copy and paste this to the registration site")%>"><% he.write(out); %></div>
    389389        </td>
    390390    </tr>
Note: See TracChangeset for help on using the changeset viewer.