source: apps/i2ptunnel/jsp/register.jsp @ 409207e0

Last change on this file since 409207e0 was 8c0e82d, checked in by zzz <zzz@…>, 2 years ago

i2ptunnel build restructuring:
Move Messages class from web to ui package, and from jar to war.
Build web package in a separate pass (prep for ssl helper)
API notes in javadocs
Hopefully doesn't break Android build

  • Property mode set to 100644
File size: 16.8 KB
Line 
1<%
2    // NOTE: Do the header carefully so there is no whitespace before the <?xml... line
3
4    response.setHeader("X-Frame-Options", "SAMEORIGIN");
5    response.setHeader("Content-Security-Policy", "default-src 'self'; style-src 'self' 'unsafe-inline'");
6    response.setHeader("X-XSS-Protection", "1; mode=block");
7    response.setHeader("X-Content-Type-Options", "nosniff");
8    response.setHeader("Referrer-Policy", "no-referrer");
9    response.setHeader("Accept-Ranges", "none");
10
11%><%@page pageEncoding="UTF-8"
12%><%@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"
13%><%@page
14%><?xml version="1.0" encoding="UTF-8"?>
15<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
16<%
17  /* right now using EditBean instead of IndexBean for getSpoofedHost() */
18  /* but might want to POST to it anyway ??? */
19%>
20<jsp:useBean class="net.i2p.i2ptunnel.web.EditBean" id="editBean" scope="request" />
21<jsp:useBean class="net.i2p.i2ptunnel.ui.Messages" id="intl" scope="request" />
22<%
23   RequestWrapper wrequest = new RequestWrapper(request);
24   String tun = wrequest.getParameter("tunnel");
25   int curTunnel = -1;
26   if (tun != null) {
27     try {
28       curTunnel = Integer.parseInt(tun);
29     } catch (NumberFormatException nfe) {
30       curTunnel = -1;
31     }
32   }
33%>
34<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
35<head>
36    <title><%=intl._t("Hidden Services Manager")%> - <%=intl._t("Registration Helper")%></title>
37    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
38    <link href="/themes/console/images/favicon.ico" type="image/x-icon" rel="shortcut icon" />
39
40    <% if (editBean.allowCSS()) {
41  %><link rel="icon" href="<%=editBean.getTheme()%>images/favicon.ico" />
42    <link href="<%=editBean.getTheme()%>i2ptunnel.css?<%=net.i2p.CoreVersion.VERSION%>" rel="stylesheet" type="text/css" /> 
43    <% }
44  %>
45<style type='text/css'>
46input.default { width: 1px; height: 1px; visibility: hidden; }
47</style>
48</head>
49<body id="tunnelRegistration">
50
51<%
52
53  if (editBean.isInitialized()) {
54
55%>
56    <form method="post" enctype="multipart/form-data" action="register" accept-charset="UTF-8">
57        <div class="panel" id="registration">
58<%
59    String tunnelTypeName;
60    String tunnelType;
61    boolean valid = false;
62    if (curTunnel >= 0) {
63        tunnelTypeName = editBean.getTunnelType(curTunnel);
64        tunnelType = editBean.getInternalType(curTunnel);
65      %><h2><%=intl._t("Registration Helper")%> (<%=editBean.getTunnelName(curTunnel)%>)</h2><% 
66    } else {
67        tunnelTypeName = "new";
68        tunnelType = "new";
69      %><h2>Fail</h2><p>Tunnel not found</p><% 
70    }
71    String b64 = editBean.getDestinationBase64(curTunnel);
72    String name = editBean.getSpoofedHost(curTunnel);
73    if (name == null || name.equals(""))
74        name = editBean.getTunnelName(curTunnel);
75%>
76                <input type="hidden" name="tunnel" value="<%=curTunnel%>" />
77                <input type="hidden" name="nonce" value="<%=net.i2p.i2ptunnel.web.IndexBean.getNextNonce()%>" />
78                <input type="hidden" name="type" value="<%=tunnelType%>" />
79                <input type="submit" class="default" name="action" value="Save changes" />
80<%
81    if (!"new".equals(tunnelType)) {
82%>
83
84<table>
85    <tr>
86        <td class="infohelp">
87    <%=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")%>
88        </td>
89    </tr>
90    <tr>
91        <td>
92            <b><%=intl._t("Tunnel name")%>:</b> <%=editBean.getTunnelName(curTunnel)%>
93        </td>
94    </tr>
95
96<%
97      if (("httpserver".equals(tunnelType)) || ("httpbidirserver".equals(tunnelType))) {
98          %>
99    <tr><td><b><%=intl._t("Website name")%>:</b> <%=editBean.getSpoofedHost(curTunnel)%></td></tr>
100<%
101       }
102%>
103
104<!--
105    <tr>
106        <th>
107            <b><%=intl._t("Local Destination")%></b>
108        </th>
109    </tr>
110    <tr>
111        <td>
112            <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>
113        </td>
114    </tr>
115-->
116
117<%
118       if (b64 == null || b64.length() < 516) {
119           %><tr><td class="infohelp"><%=intl._t("Local destination is not available. Start the tunnel.")%></td></tr><%
120       } else if (name == null || name.equals("") || name.contains(" ") || !name.endsWith(".i2p")) {
121           if (("httpserver".equals(tunnelType)) || ("httpbidirserver".equals(tunnelType))) {
122               %><tr><td class="infohelp"><%=intl._t("To enable registration verification, edit tunnel and set name (or website name) to a valid host name ending in '.i2p'")%></td></tr><%
123           } else {
124               %><tr><td class="infohelp"><%=intl._t("To enable registration verification, edit tunnel and set name to a valid host name ending in '.i2p'")%></td></tr><%
125           }
126       } else {
127           SigningPrivateKey spk = editBean.getSigningPrivateKey(curTunnel);
128           if (spk == null) {
129               %><tr><td class="infohelp"><%=intl._t("Destination signing key is not available. Start the tunnel.")%></td></tr><%
130           } else {
131               valid = true;
132               OrderedProperties props = new OrderedProperties();
133               HostTxtEntry he = new HostTxtEntry(name, b64, props);
134               he.sign(spk);
135          %>
136
137    <tr>
138        <th>
139            <%=intl._t("Authentication for adding host {0}", name)%>
140        </th>
141    </tr>
142    <tr>
143        <td>
144            <div class="displayText" tabindex="0" title="<%=intl._t("Copy and paste this to the registration site")%>"><% he.write(out); %></div>
145        </td>
146    </tr>
147</table>
148
149<h3><%=intl._t("Advanced authentication strings")%></h3>
150
151<%
152               props.remove(HostTxtEntry.PROP_SIG);
153               props.setProperty(HostTxtEntry.PROP_ACTION, HostTxtEntry.ACTION_REMOVE);
154               he.signRemove(spk);
155          %>
156
157<table>
158    <tr>
159        <th>
160            <%=intl._t("Authentication for removing host {0}", name)%>
161        </th>
162    </tr>
163    <tr>
164        <td>
165            <div class="displayText" tabindex="0" title="<%=intl._t("Copy and paste this to the registration site")%>"><% he.writeRemove(out); %></div>
166        </td>
167    </tr>
168
169<%
170               String oldname = wrequest.getParameter("oldname");
171               String olddestfile = wrequest.getFilename("olddestfile");
172               SigningPrivateKey spk2 = null;
173               String olddest = null;
174               if (olddestfile != null) {
175                   InputStream destIn = wrequest.getInputStream("olddestfile");
176                   if (destIn.available() > 0) {
177                       try {
178                           PrivateKeyFile pkf2 = new PrivateKeyFile(destIn);
179                           String oldb64 = pkf2.getDestination().toBase64();
180                           if (!b64.equals(oldb64)) {
181                               // disallow dup
182                               olddest = oldb64;
183                               spk2 = pkf2.getSigningPrivKey();
184                           }
185                       } catch (I2PSessionException ise) {
186                           throw new IllegalStateException("Unable to open private key file " + olddestfile, ise);
187                       }
188                   }
189               }
190               props.remove(HostTxtEntry.PROP_SIG);
191          %>
192    <tr>
193        <th>
194                    <%=intl._t("Authentication for changing name")%>
195        </th>
196    </tr>
197<%
198               if (oldname != null && oldname.length() > 0 && !oldname.equals(name)) {
199                   props.setProperty(HostTxtEntry.PROP_ACTION, HostTxtEntry.ACTION_CHANGENAME);
200                   props.setProperty(HostTxtEntry.PROP_OLDNAME, oldname);
201                   he.sign(spk);
202                %>
203    <tr>
204        <td>
205            <div class="displayText" tabindex="0" title="<%=intl._t("Copy and paste this to the registration site")%>"><% he.write(out); %></div>
206        </td>
207    </tr>
208    <tr>
209        <td class="infohelp">
210            <%=intl._t("This will change the name from {0} to {1}, using the same destination", oldname, name)%>
211        </td>
212    </tr>
213
214<%
215               } else {
216                %><tr><td class="infohelp"><%=intl._t("This tunnel must be configured with the new host name.")%>
217                  &nbsp;<%=intl._t("Enter old hostname below.")%></td></tr>
218<%
219               }
220          %>
221
222<%
223               props.remove(HostTxtEntry.PROP_SIG);
224          %>
225    <tr>
226        <th>
227                    <%=intl._t("Authentication for adding alias")%>
228        </th>
229    </tr>
230<%
231               if (oldname != null && oldname.length() > 0 && !oldname.equals(name)) {
232                   props.setProperty(HostTxtEntry.PROP_ACTION, HostTxtEntry.ACTION_ADDNAME);
233                   props.setProperty(HostTxtEntry.PROP_OLDNAME, oldname);
234                   he.sign(spk);
235                %>
236    <tr>
237        <td>
238            <div class="displayText" tabindex="0" title="<%=intl._t("Copy and paste this to the registration site")%>"><% he.write(out); %></div>
239        </td>
240    </tr>
241    <tr>
242        <td class="infohelp">
243            <%=intl._t("This will add an alias {0} for {1}, using the same destination", name, oldname)%>
244        </td>
245    </tr>
246<%
247               } else {
248                %><tr> <td class="infohelp"><%=intl._t("This tunnel must be configured with the new host name.")%>
249                  &nbsp;<%=intl._t("Enter old hostname below.")%></td></tr>
250<%
251               }
252          %>
253
254<%
255               props.remove(HostTxtEntry.PROP_SIG);
256               props.remove(HostTxtEntry.PROP_OLDNAME);
257          %>
258
259    <tr>
260        <th>
261                    <%=intl._t("Authentication for changing destination")%>
262        </th>
263    </tr>
264
265<%
266               if (spk2 != null) {
267                   props.setProperty(HostTxtEntry.PROP_ACTION, HostTxtEntry.ACTION_CHANGEDEST);
268                   props.setProperty(HostTxtEntry.PROP_OLDDEST, olddest);
269                   he.signInner(spk2);
270                   he.sign(spk);
271                %>
272
273    <tr>
274        <td>
275            <div class="displayText" tabindex="0" title="<%=intl._t("Copy and paste this to the registration site")%>"><% he.write(out); %></div>
276        </td>
277    </tr>
278    <tr>
279        <td class="infohelp">
280            <%=intl._t("This will change the destination for {0}", name)%>
281        </td>
282    </tr>
283
284<%
285               } else {
286                %><tr><td class="infohelp"><%=intl._t("This tunnel must be configured with the new destination.")%>
287                  &nbsp;<%=intl._t("Enter old destination below.")%></td></tr>
288<%
289               }
290          %>
291
292<%
293               props.remove(HostTxtEntry.PROP_SIG);
294               props.remove(HostTxtEntry.PROP_OLDSIG);
295          %>
296
297    <tr>
298        <th>
299                    <%=intl._t("Authentication for adding alternate destination")%>
300        </th>
301    </tr>
302
303<%
304               if (spk2 != null) {
305                   props.setProperty(HostTxtEntry.PROP_ACTION, HostTxtEntry.ACTION_ADDDEST);
306                   props.setProperty(HostTxtEntry.PROP_OLDDEST, olddest);
307                   he.signInner(spk2);
308                   he.sign(spk);
309                %>
310    <tr>
311        <td>
312            <div class="displayText" tabindex="0" title="<%=intl._t("Copy and paste this to the registration site")%>"><% he.write(out); %></div>
313        </td>
314    </tr>
315    <tr>
316        <td class="infohelp">
317            <%=intl._t("This will add an alternate destination for {0}", name)%>
318        </td>
319    </tr>
320<%
321               } else {
322                   // If set, use the configured alternate destination as the new alias destination,
323                   // and the configured primary destination as the inner signer.
324                   // This is backwards from all the other ones, so we have to make a second HostTxtEntry just for this.
325                   SigningPrivateKey spk3 = null;
326                   String altdest = null;
327                   String altdestfile = editBean.getAltPrivateKeyFile(curTunnel);
328                   if (altdestfile.length() > 0) {
329                       try {
330                           PrivateKeyFile pkf3 = new PrivateKeyFile(altdestfile);
331                           altdest = pkf3.getDestination().toBase64();
332                           if (!b64.equals(altdest)) {
333                               // disallow dup
334                               spk3 = pkf3.getSigningPrivKey();
335                           }
336                       } catch (Exception e) {}
337                   }
338                   if (spk3 != null) {
339                       OrderedProperties props2 = new OrderedProperties();
340                       HostTxtEntry he2 = new HostTxtEntry(name, altdest, props2);
341                       props2.setProperty(HostTxtEntry.PROP_ACTION, HostTxtEntry.ACTION_ADDDEST);
342                       props2.setProperty(HostTxtEntry.PROP_OLDDEST, b64);
343                       he2.signInner(spk);
344                       he2.sign(spk3);
345                %><tr><td><div class="displayText" tabindex="0" title="<%=intl._t("Copy and paste this to the registration site")%>"><% he2.write(out); %></div></td></tr>
346                <tr><td class="infohelp"><%=intl._t("This will add an alternate destination for {0}", name)%></td></tr>
347<%
348                   } else {
349                %><tr><td class="infohelp"><%=intl._t("This tunnel must be configured with the new destination.")%>
350                  &nbsp;<%=intl._t("Enter old destination below.")%></td></tr>
351<%
352                   }  // spk3
353               }  // spk2
354          %>
355
356<%
357
358
359               props.remove(HostTxtEntry.PROP_SIG);
360               props.remove(HostTxtEntry.PROP_OLDSIG);
361          %>
362
363    <tr>
364        <th>
365                    <%=intl._t("Authentication for adding subdomain")%>
366        </th>
367    </tr>
368<%
369               if (oldname != null && oldname.length() > 0 && !oldname.equals(name) && spk2 != null) {
370                   props.setProperty(HostTxtEntry.PROP_ACTION, HostTxtEntry.ACTION_ADDSUBDOMAIN);
371                   props.setProperty(HostTxtEntry.PROP_OLDNAME, oldname);
372                   props.setProperty(HostTxtEntry.PROP_OLDDEST, olddest);
373                   he.signInner(spk2);
374                   he.sign(spk);
375                %>
376
377    <tr>
378        <td>
379            <div class="displayText" tabindex="0" title="<%=intl._t("Copy and paste this to the registration site")%>"><% he.write(out); %></div>
380        </td>
381    </tr>
382    <tr>
383        <td class="infohelp">
384            <%=intl._t("This will add a subdomain {0} of {1}, with a different destination", name, oldname)%>
385        </td>
386    </tr>
387
388<%
389               } else {
390                %>
391    <tr>
392        <td class="infohelp">
393            <%=intl._t("This tunnel must be configured with the new subdomain and destination.")%>
394            &nbsp;<%=intl._t("Enter higher-level domain and destination below.")%>
395        </td>
396    </tr>
397
398<%
399               }
400          %>
401
402<%
403          }  // spk != null
404       }  // valid b64 and name
405    }  // !"new".equals(tunnelType)
406    if (!valid && curTunnel >= 0) {
407        %>
408    <tr>
409        <td>
410            <a href="edit?tunnel=<%=curTunnel%>"><%=intl._t("Go back and edit the tunnel")%></a>
411        </td>
412    </tr>
413        <%
414    }
415%>
416
417<%
418    if (valid) {
419%>
420
421    <tr>
422        <th>
423            <%=intl._t("Specify old name and destination")%>
424        </th>
425    </tr>
426    <tr>
427        <td class="infohelp">
428            <%=intl._t("This is only required for advanced authentication.")%>
429            &nbsp;<%=intl._t("See above for required items.")%>
430        </td>
431    </tr>
432<%
433               String oldname = wrequest.getParameter("oldname");
434               if (oldname == null) oldname = "";
435          %>
436    <tr>
437        <td>
438            <b><%=intl._t("Old hostname")%>:</b>
439            <input type="text" size="30" maxlength="50" name="oldname" id="oldName" value="<%=oldname%>" class="freetext" />
440        </td>
441    </tr>
442    <tr>
443        <td>
444            <b><%=intl._t("Private Key File for old Destination")%>:</b>
445            <input type="file" name="olddestfile" id="oldDestFile" value="" />
446        </td>
447    </tr>
448    <tr>
449        <td class="buttons">
450                    <input type="hidden" value="true" name="removeConfirm" />
451                    <a class="control" href="list"><%=intl._t("Cancel")%></a>
452                    <button id="controlSave" class="control" type="submit" name="action" value="authenticate"  title="<%=intl._t("Generate Authentication")%>"><%=intl._t("Generate")%></button>
453        </td>
454    </tr>
455
456<%
457     } // valid
458%>
459
460</table>
461</div>
462    </form>
463<%
464
465  } else {
466     %><div id="notReady"><%=intl._t("Tunnels are not initialized yet, please reload in two minutes.")%></div><%
467  }  // isInitialized()
468
469%>
470</body>
471</html>
Note: See TracBrowser for help on using the repository browser.