source: apps/i2ptunnel/jsp/register.jsp @ 0ac83bd

Last change on this file since 0ac83bd was 0ac83bd, checked in by zzz <zzz@…>, 4 years ago

i2ptunnel: Enhance registration authentication page

  • Enable form
  • Switch to multipart form for getting old private key file
  • Add advanced authentications

PrivateKeyFile?: Add InputStream? constructor for i2ptunnel

  • Property mode set to 100644
File size: 16.6 KB
Line 
1<%@page contentType="text/html" import="java.io.InputStream,net.i2p.i2ptunnel.web.EditBean,net.i2p.servlet.RequestWrapper,net.i2p.client.I2PSessionException,net.i2p.client.naming.HostTxtEntry,net.i2p.data.PrivateKeyFile,net.i2p.data.SigningPrivateKey,net.i2p.util.OrderedProperties"
2%><%@page trimDirectiveWhitespaces="true"
3%><?xml version="1.0" encoding="UTF-8"?>
4<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
5<%
6  /* right now using EditBean instead of IndexBean for getSpoofedHost() */
7  /* but might want to POST to it anyway ??? */
8%>
9<jsp:useBean class="net.i2p.i2ptunnel.web.EditBean" id="editBean" scope="request" />
10<jsp:useBean class="net.i2p.i2ptunnel.web.Messages" id="intl" scope="request" />
11<%
12   RequestWrapper wrequest = new RequestWrapper(request);
13   String tun = wrequest.getParameter("tunnel");
14   int curTunnel = -1;
15   if (tun != null) {
16     try {
17       curTunnel = Integer.parseInt(tun);
18     } catch (NumberFormatException nfe) {
19       curTunnel = -1;
20     }
21   }
22%>
23<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
24<head>
25    <title><%=intl._t("Hidden Services Manager")%> - <%=intl._t("Registration Helper")%></title>
26    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
27    <meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
28    <link href="/themes/console/images/favicon.ico" type="image/x-icon" rel="shortcut icon" />
29
30    <% if (editBean.allowCSS()) {
31  %><link rel="icon" href="<%=editBean.getTheme()%>images/favicon.ico" />
32    <link href="<%=editBean.getTheme()%>default.css" rel="stylesheet" type="text/css" /> 
33    <link href="<%=editBean.getTheme()%>i2ptunnel.css" rel="stylesheet" type="text/css" />
34    <% }
35  %>
36<style type='text/css'>
37input.default { width: 1px; height: 1px; visibility: hidden; }
38</style>
39</head>
40<body id="tunnelEditPage">
41    <div id="pageHeader">
42    </div>
43<%
44
45  if (editBean.isInitialized()) {
46
47%>
48    <form method="post" enctype="multipart/form-data" action="register" accept-charset="UTF-8">
49        <div id="tunnelEditPanel" class="panel">
50            <div class="header">
51<%
52    String tunnelTypeName;
53    String tunnelType;
54    boolean valid = false;
55    if (curTunnel >= 0) {
56        tunnelTypeName = editBean.getTunnelType(curTunnel);
57        tunnelType = editBean.getInternalType(curTunnel);
58      %><h4><%=intl._t("Registration Helper")%></h4><% 
59    } else {
60        tunnelTypeName = "new";
61        tunnelType = "new";
62      %><h4>Fail</h4><p>Tunnel not found</p><% 
63    }
64    String b64 = editBean.getDestinationBase64(curTunnel);
65    String name = editBean.getSpoofedHost(curTunnel);
66    if (name == null || name.equals(""))
67        name = editBean.getTunnelName(curTunnel);
68%>
69                <input type="hidden" name="tunnel" value="<%=curTunnel%>" />
70                <input type="hidden" name="nonce" value="<%=net.i2p.i2ptunnel.web.IndexBean.getNextNonce()%>" />
71                <input type="hidden" name="type" value="<%=tunnelType%>" />
72                <input type="submit" class="default" name="action" value="Save changes" />
73            </div>
74<%
75    if (!"new".equals(tunnelType)) {     
76%>
77  <span class="comment">
78    <%=intl._t("Please be sure to select, copy, and paste the entire contents of the appropriate authentication data into the form of your favorite registration site")%>
79  </span>
80            <div class="separator">
81                <hr />
82            </div>
83            <div id="nameField" class="rowItem">
84                <label for="name" accesskey="N">
85                    <%=intl._t("Name")%>
86                </label>
87                <span class="text"><%=editBean.getTunnelName(curTunnel)%></span>
88            </div>
89<%           
90      if (("httpserver".equals(tunnelType)) || ("httpbidirserver".equals(tunnelType))) {
91          %><div id="websiteField" class="rowItem">
92                <label for="spoofedHost" accesskey="W">
93                    <%=intl._t("Website name")%>
94                </label>
95                <span class="text"><%=editBean.getSpoofedHost(curTunnel)%></span>   
96            </div>
97<%
98       }
99%>
100            <div id="destinationField" class="rowItem">
101                <label for="localDestination" accesskey="L">
102                    <%=intl._t("Local destination")%>
103                </label>
104                <textarea rows="1" style="height: 3em;" cols="60" readonly="readonly" id="localDestination" title="Read Only: Local Destination (if known)" wrap="off" spellcheck="false"><%=editBean.getDestinationBase64(curTunnel)%></textarea>               
105            </div>
106            <div class="subdivider">
107                <hr />
108            </div>
109<%
110       if (b64 == null || b64.length() < 516) {
111           %><%=intl._t("Local destination is not available. Start the tunnel.")%><%
112       } else if (name == null || name.equals("") || name.contains(" ") || !name.endsWith(".i2p")) {
113           if (("httpserver".equals(tunnelType)) || ("httpbidirserver".equals(tunnelType))) {
114               %><%=intl._t("To enable registration verification, edit tunnel and set name (or website name) to a valid host name ending in '.i2p'")%><%
115           } else {
116               %><%=intl._t("To enable registration verification, edit tunnel and set name to a valid host name ending in '.i2p'")%><%
117           }
118       } else {
119           SigningPrivateKey spk = editBean.getSigningPrivateKey(curTunnel);
120           if (spk == null) {
121               %><%=intl._t("Destination signing key is not available. Start the tunnel.")%><%
122           } else {
123               valid = true;
124               OrderedProperties props = new OrderedProperties();
125               HostTxtEntry he = new HostTxtEntry(name, b64, props);
126               he.sign(spk);
127          %><div id="sigField" class="rowItem">
128                <label for="signature">
129                    <%=intl._t("Authentication for adding host")%>
130                </label>
131                <textarea rows="1" style="height: 3em;" cols="60" readonly="readonly" id="localDestination" title="Copy and paste this to the registration site" wrap="off" spellcheck="false"><% he.writeProps(out); %></textarea>               
132            </div>
133        </div>
134        <div id="tunnelAdvancedNetworking" class="panel">
135            <div class="header">
136                <h4><%=intl._t("Advanced authentication strings")%></h4>
137            </div>
138<%
139               props.remove(HostTxtEntry.PROP_SIG);
140               props.setProperty(HostTxtEntry.PROP_ACTION, HostTxtEntry.ACTION_REMOVE);
141               he.signRemove(spk);
142          %><div id="sigField" class="rowItem">
143                <label for="signature">
144                    <%=intl._t("Authentication for removing host")%>
145                </label>
146                <textarea rows="1" style="height: 3em;" cols="60" readonly="readonly" id="localDestination" title="Copy and paste this to the registration site" wrap="off" spellcheck="false"><% he.writeRemove(out); %></textarea>               
147                <span class="comment"><%=intl._t("This will remove the entry for {0}", name)%></span>
148            </div>
149            <div class="separator">
150                <hr />
151            </div>
152<%
153               String oldname = wrequest.getParameter("oldname");
154               String olddestfile = wrequest.getFilename("olddestfile");
155               SigningPrivateKey spk2 = null;
156               String olddest = null;
157               if (olddestfile != null) {
158                   InputStream destIn = wrequest.getInputStream("olddestfile");
159                   if (destIn.available() > 0) {
160                       try {
161                           PrivateKeyFile pkf2 = new PrivateKeyFile(destIn);
162                           String oldb64 = pkf2.getDestination().toBase64();
163                           if (!b64.equals(oldb64)) {
164                               // disallow dup
165                               olddest = b64;
166                               spk2 = pkf2.getSigningPrivKey();
167                           }
168                       } catch (I2PSessionException ise) {
169                           throw new IllegalStateException("Unable to open private key file " + olddestfile, ise);
170                       }
171                   }
172               }
173               props.remove(HostTxtEntry.PROP_SIG);
174          %><div id="sigField" class="rowItem">
175                <label for="signature">
176                    <%=intl._t("Authentication for changing name")%>
177                </label>
178<%
179               if (oldname != null && oldname.length() > 0 && !oldname.equals(name)) {
180                   props.setProperty(HostTxtEntry.PROP_ACTION, HostTxtEntry.ACTION_CHANGENAME);
181                   props.setProperty(HostTxtEntry.PROP_OLDNAME, oldname);
182                   he.sign(spk);
183                %><textarea rows="1" style="height: 3em;" cols="60" readonly="readonly" id="localDestination" title="Copy and paste this to the registration site" wrap="off" spellcheck="false"><% he.writeProps(out); %></textarea>               
184                <span class="comment"><%=intl._t("This will change the name from {0} to {1}, using the same destination", oldname, name)%></span>
185<%
186               } else {
187                %><span class="comment"><%=intl._t("This tunnel must be configured with the new host name.")%></span>
188                  <span class="comment"><%=intl._t("Enter old host name below.")%></span>
189<%
190               }
191          %></div>
192            <div class="separator">
193                <hr />
194            </div>
195<%
196               props.remove(HostTxtEntry.PROP_SIG);
197          %><div id="sigField" class="rowItem">
198                <label for="signature">
199                    <%=intl._t("Authentication for adding alias")%>
200                </label>
201<%
202               if (oldname != null && oldname.length() > 0 && !oldname.equals(name)) {
203                   props.setProperty(HostTxtEntry.PROP_ACTION, HostTxtEntry.ACTION_ADDNAME);
204                   props.setProperty(HostTxtEntry.PROP_OLDNAME, oldname);
205                   he.sign(spk);
206                %><textarea rows="1" style="height: 3em;" cols="60" readonly="readonly" id="localDestination" title="Copy and paste this to the registration site" wrap="off" spellcheck="false"><% he.writeProps(out); %></textarea>               
207                <span class="comment"><%=intl._t("This will add an alias {0} for {1}, using the same destination", name, oldname)%></span>
208<%
209               } else {
210                %><span class="comment"><%=intl._t("This tunnel must be configured with the new host name.")%></span>
211                  <span class="comment"><%=intl._t("Enter old host name below.")%></span>
212<%
213               }
214          %></div>
215            <div class="separator">
216                <hr />
217            </div>
218<%
219               props.remove(HostTxtEntry.PROP_SIG);
220          %><div id="sigField" class="rowItem">
221                <label for="signature">
222                    <%=intl._t("Authentication for changing destination")%>
223                </label>
224<%
225               if (spk2 != null) {
226                   props.setProperty(HostTxtEntry.PROP_ACTION, HostTxtEntry.ACTION_CHANGEDEST);
227                   props.setProperty(HostTxtEntry.PROP_OLDDEST, olddest);
228                   he.signInner(spk2);
229                   he.sign(spk);
230                %><textarea rows="1" style="height: 3em;" cols="60" readonly="readonly" id="localDestination" title="Copy and paste this to the registration site" wrap="off" spellcheck="false"><% he.writeProps(out); %></textarea>               
231                <span class="comment"><%=intl._t("This will change the destination for {0}", name)%></span>
232<%
233               } else {
234                %><span class="comment"><%=intl._t("This tunnel must be configured with the new destination.")%></span>
235                  <span class="comment"><%=intl._t("Enter old destination below.")%></span>
236<%
237               }
238          %></div>
239            <div class="separator">
240                <hr />
241            </div>
242<%
243               props.remove(HostTxtEntry.PROP_SIG);
244               props.remove(HostTxtEntry.PROP_OLDSIG);
245          %><div id="sigField" class="rowItem">
246                <label for="signature">
247                    <%=intl._t("Authentication for adding alternate destination")%>
248                </label>
249<%
250               if (spk2 != null) {
251                   props.setProperty(HostTxtEntry.PROP_ACTION, HostTxtEntry.ACTION_ADDDEST);
252                   props.setProperty(HostTxtEntry.PROP_OLDDEST, olddest);
253                   he.signInner(spk2);
254                   he.sign(spk);
255                %><textarea rows="1" style="height: 3em;" cols="60" readonly="readonly" id="localDestination" title="Copy and paste this to the registration site" wrap="off" spellcheck="false"><% he.writeProps(out); %></textarea>               
256                <span class="comment"><%=intl._t("This will add an alternate destination for {0}", name)%></span>
257<%
258               } else {
259                %><span class="comment"><%=intl._t("This tunnel must be configured with the new destination.")%></span>
260                  <span class="comment"><%=intl._t("Enter old destination below.")%></span>
261<%
262               }
263          %></div>
264            <div class="separator">
265                <hr />
266            </div>
267<%
268               props.remove(HostTxtEntry.PROP_SIG);
269               props.remove(HostTxtEntry.PROP_OLDSIG);
270          %><div id="sigField" class="rowItem">
271                <label for="signature">
272                    <%=intl._t("Authentication for adding subdomain")%>
273                </label>
274<%
275               if (oldname != null && oldname.length() > 0 && !oldname.equals(name) && spk2 != null) {
276                   props.setProperty(HostTxtEntry.PROP_ACTION, HostTxtEntry.ACTION_ADDSUBDOMAIN);
277                   props.setProperty(HostTxtEntry.PROP_OLDNAME, oldname);
278                   props.setProperty(HostTxtEntry.PROP_OLDDEST, olddest);
279                   he.signInner(spk2);
280                   he.sign(spk);
281                %><textarea rows="1" style="height: 3em;" cols="60" readonly="readonly" id="localDestination" title="Copy and paste this to the registration site" wrap="off" spellcheck="false"><% he.writeProps(out); %></textarea>               
282                <span class="comment"><%=intl._t("This will add a subdomain {0} of {1}, with a different destination", name, oldname)%></span>
283<%
284               } else {
285                %><span class="comment"><%=intl._t("This tunnel must be configured with the new subdomain and destination.")%></span>
286                  <span class="comment"><%=intl._t("Enter higher-level domain and destination below.")%></span>
287<%
288               }
289          %></div>
290
291          <div class="footer">
292            </div>
293<%
294          }  // spk != null
295       }  // valid b64 and name
296    }  // !"new".equals(tunnelType)
297    if (!valid && curTunnel >= 0) {
298        %><a href="edit?tunnel=<%=curTunnel%>"><%=intl._t("Go back and edit the tunnel")%></a><%
299    }
300%>
301        </div>
302
303
304<%
305    if (valid) {
306%>
307        <div id="globalOperationsPanel" class="panel">
308            <div class="header">
309                <h4><%=intl._t("Specify old name and destination")%></h4>
310            </div>
311  <span class="comment">
312    <%=intl._t("This is only required for advanced authentication.")%>
313    <%=intl._t("See above for required items.")%>
314  </span>
315<%
316               String oldname = wrequest.getParameter("oldname");
317               if (oldname == null) oldname = "";
318          %><div id="sigField" class="rowItem">
319                <label for="signature">
320                    <%=intl._t("Old Host Name")%>
321                </label>
322                <input type="text" size="30" maxlength="50" name="oldname" id="name" title="Old Host Name" value="<%=oldname%>" class="freetext" />               
323            </div> 
324            <div id="sigField" class="rowItem">
325                <label for="signature">
326                    <%=intl._t("Private Key File for old Destination")%>
327                </label>
328                <input type="file" size="50%" name="olddestfile" id="name" value="" />               
329            </div> 
330            <div class="footer">
331                <div class="toolbox">
332                    <input type="hidden" value="true" name="removeConfirm" />
333                    <button id="controlCancel" class="control" type="submit" name="action" value="" title="Cancel"><%=intl._t("Cancel")%></button>
334                    <button id="controlSave" accesskey="S" class="control" type="submit" name="action" value="authenticate" title="Generate Authentication"><%=intl._t("Generate")%></button>
335                </div>
336            </div> 
337        </div>
338<%
339     } // valid
340%>
341    </form>
342    <div id="pageFooter">
343    </div>
344<%
345
346  } else {
347     %>Tunnels are not initialized yet, please reload in two minutes.<%
348  }  // isInitialized()
349
350%>
351</body>
352</html>
Note: See TracBrowser for help on using the repository browser.