Join script should rule out retired usernames
[bpt/portal.git] / sec.mlt
diff --git a/sec.mlt b/sec.mlt
index 2983077..4bd6097 100644 (file)
--- a/sec.mlt
+++ b/sec.mlt
@@ -1,14 +1,19 @@
 <% val you = Init.getUserId ();
 val yourname = Init.getUserName ();
 
+val nodeNum = case $"node" of
+                 "" => 2
+               | node => Web.stoi node;
+val nodeName = Init.nodeName nodeNum;
+
 val uname = case $"uname" of
          "" => yourname
        | uname => uname;
 
-val socks = Sec.socketPerms uname;
-val tpe = Sec.isTpe uname;
-val cron = Sec.cronAllowed uname;
-val ftp = Sec.ftpAllowed uname;
+val socks = Sec.socketPerms {node = nodeNum, uname = uname};
+val tpe = Sec.isTpe {node = nodeNum, uname = uname};
+val cron = Sec.cronAllowed {node = nodeNum, uname = uname};
+val ftp = Sec.ftpAllowed {node = nodeNum, uname = uname};
 
 ref showNormal = true;
 
@@ -17,10 +22,10 @@ ref showNormal = true;
 if $"cmd" = "socks" then
        showNormal := false;
        val socks = $"socks";
-       %>Are you sure you want to request that socket permissions for <b><% Web.html uname %></b> be changed to <b><% Web.html socks %></b>?<br>
-       <a href="sec?cmd=socks2&uname=<% Web.urlEncode uname %>&socks=<% Web.urlEncode socks %>&msg=<% Web.urlEncode ($"msg") %>">Yes, place the request!</a><%
+       %>Are you sure you want to request that socket permissions for <b><% Web.html uname %></b> on <b><% Web.html nodeName %></b> be changed to <b><% Web.html socks %></b>?<br>
+       <a href="sec?cmd=socks2&node=<% nodeNum %>&uname=<% Web.urlEncode uname %>&socks=<% Web.urlEncode socks %>&msg=<% Web.urlEncode ($"msg") %>">Yes, place the request!</a><%
 elseif $"cmd" = "socks2" then
-       val id = Sec.Req.add (you, String.concat [uname, ": change socket permissions to ", $"socks"], $"msg");
+       val id = Sec.Req.add {usr = you, node = nodeNum, data = String.concat [uname, ": change socket permissions to ", $"socks"], msg = $"msg"};
        if not (Sec.Req.notifyNew id) then
                %><h3>Error sending e-mail notification</h3><%
        end
@@ -29,10 +34,10 @@ elseif $"cmd" = "socks2" then
 elseif $"cmd" = "tpe" then
        showNormal := false;
        val tpe = iff $"tpe" = "yes" then "on" else "off";
-       %>Are you sure you want to request that trusted-path-executables-only for <b><% Web.html uname %></b> be turned <b><% tpe %></b>?<br>
-       <a href="sec?cmd=tpe2&uname=<% Web.urlEncode uname %>&tpe=<% tpe %>&msg=<% Web.urlEncode ($"msg") %>">Yes, place the request!</a><%
+       %>Are you sure you want to request that trusted-path-executables-only for <b><% Web.html uname %></b> on <b><% Web.html nodeName %></b> be turned <b><% tpe %></b>?<br>
+       <a href="sec?cmd=tpe2&node=<% nodeNum %>&uname=<% Web.urlEncode uname %>&tpe=<% tpe %>&msg=<% Web.urlEncode ($"msg") %>">Yes, place the request!</a><%
 elseif $"cmd" = "tpe2" then
-       val id = Sec.Req.add (you, String.concat [uname, ": turn tpe ", $"tpe"], $"msg");
+       val id = Sec.Req.add {usr = you, node = nodeNum, data = String.concat [uname, ": turn tpe ", $"tpe"], msg = $"msg"};
        if not (Sec.Req.notifyNew id) then
                %><h3>Error sending e-mail notification</h3><%
        end
@@ -41,11 +46,11 @@ elseif $"cmd" = "tpe2" then
 elseif $"cmd" = "cron" then
        showNormal := false;
        val cron = iff $"cron" = "yes" then "enabled" else "disabled";
-       %>Are you sure you want to request that <tt>cron</tt> permissions for <b><% Web.html uname %></b> be <b><% cron %></b>?<br>
-       <a href="sec?cmd=cron2&uname=<% Web.urlEncode uname %>&cron=<% cron %>&msg=<% Web.urlEncode ($"msg") %>">Yes, place the request!</a><%
+       %>Are you sure you want to request that <tt>cron</tt> permissions for <b><% Web.html uname %></b> on <b><% Web.html nodeName %></b> be <b><% cron %></b>?<br>
+       <a href="sec?cmd=cron2&node=<% nodeNum %>&uname=<% Web.urlEncode uname %>&cron=<% cron %>&msg=<% Web.urlEncode ($"msg") %>">Yes, place the request!</a><%
 elseif $"cmd" = "cron2" then
        val cron = iff $"cron" = "enabled" then "enable" else "disable";
-       val id = Sec.Req.add (you, String.concat [uname, ": ", cron, " cron access"], $"msg");
+       val id = Sec.Req.add {usr = you, node = nodeNum, data = String.concat [uname, ": ", cron, " cron access"], msg = $"msg"};
        if not (Sec.Req.notifyNew id) then
                %><h3>Error sending e-mail notification</h3><%
        end
@@ -54,11 +59,11 @@ elseif $"cmd" = "cron2" then
 elseif $"cmd" = "ftp" then
        showNormal := false;
        val ftp = iff $"ftp" = "yes" then "enabled" else "disabled";
-       %>Are you sure you want to request that FTP permissions for <b><% Web.html uname %></b> be <b><% ftp %></b>?<br>
-       <a href="sec?cmd=ftp2&uname=<% Web.urlEncode uname %>&ftp=<% ftp %>&msg=<% Web.urlEncode ($"msg") %>">Yes, place the request!</a><%
+       %>Are you sure you want to request that FTP permissions for <b><% Web.html uname %></b> on <b><% Web.html nodeName %></b> be <b><% ftp %></b>?<br>
+       <a href="sec?cmd=ftp2&node=<% nodeNum %>&uname=<% Web.urlEncode uname %>&ftp=<% ftp %>&msg=<% Web.urlEncode ($"msg") %>">Yes, place the request!</a><%
 elseif $"cmd" = "ftp2" then
        val ftp = iff $"ftp" = "enabled" then "enable" else "disable";
-       val id = Sec.Req.add (you, String.concat [uname, ": ", ftp, " FTP access"], $"msg");
+       val id = Sec.Req.add {usr = you, node = nodeNum, data = String.concat [uname, ": ", ftp, " FTP access"], msg = $"msg"};
        if not (Sec.Req.notifyNew id) then
                %><h3>Error sending e-mail notification</h3><%
        end
@@ -67,14 +72,26 @@ elseif $"cmd" = "ftp2" then
 elseif $"cmd" = "rule" then
        showNormal := false;
        val rule = $"rule";
-       %>Are you sure you want to request the firewall rule <b><% Web.html uname %>&nbsp;<% Web.html rule %></b>?<br>
-       <a href="sec?cmd=rule2&uname=<% Web.urlEncode uname %>&rule=<% Web.urlEncode rule %>&msg=<% Web.urlEncode ($"msg") %>">Yes, place the request!</a><%
+
+       if Sec.validRule rule then
+               %>Are you sure you want to request the firewall rule <b><% Web.html uname %>&nbsp;<% Web.html rule %></b> on <b><% Web.html nodeName %></b>?<br>
+       <a href="sec?cmd=rule2&node=<% nodeNum %>&uname=<% Web.urlEncode uname %>&rule=<% Web.urlEncode rule %>&msg=<% Web.urlEncode ($"msg") %>">Yes, place the request!</a><%
+       else
+               %>"<% Web.html rule %>" is not a valid firewall rule! Please reread <a href="http://wiki.hcoop.net/wiki/FirewallRules">the instructions</a>, and remember to leave off the initial username portion.<%
+       end
+
 elseif $"cmd" = "rule2" then
-       val id = Sec.Req.add (you, String.concat ["Add firewall rule \"", uname, " ", $"rule", "\""], $"msg");
-       if not (Sec.Req.notifyNew id) then
-               %><h3>Error sending e-mail notification</h3><%
+       val rule = $"rule";
+
+       if Sec.validRule rule then
+               val id = Sec.Req.add {usr = you, node = nodeNum, data = String.concat ["Add firewall rule \"", uname, " ", rule, "\""], msg = $"msg"};
+               if not (Sec.Req.notifyNew id) then
+                       %><h3>Error sending e-mail notification</h3><%
+               end
+               %><h3>Request added</h3><%
+       else
+               %>"<% Web.html rule %>" is not a valid firewall rule! Please reread <a href="http://wiki.hcoop.net/wiki/FirewallRules">the instructions</a>, and remember to leave off the initial username portion.<%
        end
-       %><h3>Request added</h3><%
 
 elseif $"modRule" <> "" then
        showNormal := false;
@@ -83,11 +100,11 @@ elseif $"modRule" <> "" then
        if oldRule = rule then
                %>You didn't modify the textbox for this rule before clicking the button, so there is no request to be made.<%
        else
-               %>Are you sure you want to request that firewall rule <b><% Web.html uname %>&nbsp;<% Web.html oldRule %></b> be replaced by <b><% Web.html uname %>&nbsp;<% Web.html rule %></b>?<br>
-               <a href="sec?uname=<% Web.urlEncode uname %>&modRule2=<% Web.urlEncode oldRule %>&rule=<% Web.urlEncode rule %>&msg=<% Web.urlEncode ($"msg") %>">Yes, place the request!</a><%
+               %>Are you sure you want to request that firewall rule <b><% Web.html uname %>&nbsp;<% Web.html oldRule %></b> be replaced by <b><% Web.html uname %>&nbsp;<% Web.html rule %></b> on <b><% Web.html nodeName %></b>?<br>
+               <a href="sec?node=<% nodeNum %>&uname=<% Web.urlEncode uname %>&modRule2=<% Web.urlEncode oldRule %>&rule=<% Web.urlEncode rule %>&msg=<% Web.urlEncode ($"msg") %>">Yes, place the request!</a><%
        end
 elseif $"modRule2" <> "" then
-       val id = Sec.Req.add (you, String.concat ["Change firewall rule \"", uname, " ", $"modRule2", "\" to \"", uname, " ", $"rule", "\""], $"msg");
+       val id = Sec.Req.add {usr = you, node = nodeNum, data = String.concat ["Change firewall rule \"", uname, " ", $"modRule2", "\" to \"", uname, " ", $"rule", "\""], msg = $"msg"};
        if not (Sec.Req.notifyNew id) then
                %><h3>Error sending e-mail notification</h3><%
        end
@@ -96,10 +113,10 @@ elseif $"modRule2" <> "" then
 elseif $"delRule" <> "" then
        showNormal := false;
        val oldRule = $"delRule";
-       %>Are you sure you want to request that firewall rule <b><% Web.html uname %>&nbsp;<% Web.html oldRule %></b> be <b>deleted</b>?<br>
-       <a href="sec?uname=<% Web.urlEncode uname %>&delRule2=<% Web.urlEncode oldRule %>&msg=<% Web.urlEncode ($"msg") %>">Yes, place the request!</a><%
+       %>Are you sure you want to request that firewall rule <b><% Web.html uname %>&nbsp;<% Web.html oldRule %></b> on <b><% Web.html nodeName %></b> be <b>deleted</bD>?<br>
+       <a href="sec?node=<% nodeNum %>&uname=<% Web.urlEncode uname %>&delRule2=<% Web.urlEncode oldRule %>&msg=<% Web.urlEncode ($"msg") %>">Yes, place the request!</a><%
 elseif $"delRule2" <> "" then
-       val id = Sec.Req.add (you, String.concat ["Delete firewall rule \"", uname, " ", $"delRule2", "\""], $"msg");
+       val id = Sec.Req.add {usr = you, node = nodeNum, data = String.concat ["Delete firewall rule \"", uname, " ", $"delRule2", "\""], msg = $"msg"};
        if not (Sec.Req.notifyNew id) then
                %><h3>Error sending e-mail notification</h3><%
        end
@@ -115,7 +132,8 @@ elseif $"cmd" = "open" then
 <br><hr><br>
 <table class="blanks">
 <tr> <td>By:</td> <td><a href="user?id=<% #usr req %>"><% name %></a></td> </tr>
-<tr> <td>Time:</td> <td><% #stamp req %></td> </tr>
+<tr> <td>Time:</td> <td><% #stamp req %> (<% Util.diffFromNow (#stamp req) %> ago)</td></tr>
+<tr> <td>Node:</td> <td><% Web.html (Init.nodeName (#node req)) %></td> </tr>
 <tr> <td>Request:</td> <td><% #data req %></td> </tr>
 <tr> <td>Msg:</td> <td colspan="2"><% Web.html (#msg req) %></td> </tr>
 </table>
@@ -135,7 +153,8 @@ elseif $"cmd" = "list" then
 <br><hr><br>
 <table class="blanks">
 <tr> <td>By:</td> <td colspan="2"><a href="user?id=<% #usr req %>"><% name %></a></td> </tr>
-<tr> <td>Time:</td> <td colspan="2"><% #stamp req %></td> </tr>
+<tr> <td>Time:</td> <td colspan="2"><% #stamp req %> (<% Util.diffFromNow (#stamp req) %> ago)</td></tr>
+<tr> <td>Node:</td> <td><% Web.html (Init.nodeName (#node req)) %></td> </tr>
 <tr> <td>Request:</td> <td><% #data req %></td> </tr>
 <tr> <td>Reason:</td> <td colspan="2"><% Web.html (#msg req) %></td> </tr>
 </table>
@@ -158,12 +177,16 @@ elseif $"mod" <> "" then
 <input type="hidden" name="save" value="<% id %>">
 <table class="blanks">
 <tr> <td>Requestor:</td> <td><a href="user?id=<% #usr req %>"><% #name user %></a></td> </tr>
-<tr> <td>Time:</td> <td><% #stamp req %></td> </tr>
+<tr> <td>Time:</td> <td><% #stamp req %> (<% Util.diffFromNow (#stamp req) %> ago)</td></tr>
 <tr> <td>Status:</td> <td><select name="status">
        <option value="0"<% if #status req = Sec.Req.NEW then %> selected<% end %>>New</option>
        <option value="1"<% if #status req = Sec.Req.INSTALLED then %> selected<% end %>>Installed</option>
        <option value="2"<% if #status req = Sec.Req.REJECTED then %> selected<% end %>>Rejected</option>
 </select></td> </tr>
+<tr> <td>Node:</td> <td><select name="node">
+<% foreach node in Init.listNodes () do %>
+       <option value="<% #id node %>"<% if nodeNum = #node req then %> selected<% end %>><% Web.html (#name node) %> (<% Web.html (#descr node) %>)</option>
+<% end %></select></td> </tr>
 <tr> <td>Request:</td> <td><input name="req" value="<% #data req %>"></td> </tr>
 <tr> <td>Message:</td> <td><textarea name="msg" rows="10" cols="80" wrap="soft"><% Web.html (#msg req) %></textarea></td> </tr>
 <tr> <td><input type="submit" value="Save"></td> </tr>
@@ -177,11 +200,9 @@ elseif $"mod" <> "" then
        val req = Sec.Req.lookup id;
        val oldStatus = #status req;
        val newStatus = Sec.Req.statusFromInt (Web.stoi ($"status"));
-       Sec.Req.modify {req with data = $"req", msg = $"msg", status = newStatus};
-       if oldStatus <> newStatus then
-               if not (Sec.Req.notifyMod (oldStatus, newStatus, Init.getUserName(), id)) then
-                       %><h3>Error sending e-mail notification</h3><%
-               end
+       Sec.Req.modify {req with node = nodeNum, data = $"req", msg = $"msg", status = newStatus};
+       if not (Sec.Req.notifyMod {old = oldStatus, new = newStatus, changer = Init.getUserName(), req = id}) then
+               %><h3>Error sending e-mail notification</h3><%
        end
        %><h3>Request modified</h3>
        Back to: <a href="sec?cmd=open">open requests</a>, <a href="sec?cmd=list">all requests</a>
@@ -192,7 +213,7 @@ elseif $"mod" <> "" then
        val id = Web.stoi ($"del");
        val req = Sec.Req.lookup id;
        val user = Init.lookupUser (#usr req)
-       %><h3>Are you sure you want to delete request by <% #name user %> for "<% #data req %>"?</h3>
+       %><h3>Are you sure you want to delete request by <% #name user %> for "<% #data req %>" on <% Web.html (Init.nodeName (#node req)) %>?</h3>
        <a href="sec?del2=<% id %>">Yes, I'm sure!</a>
 
 <% elseif $"del2" <> "" then
@@ -207,15 +228,33 @@ elseif $"mod" <> "" then
 
 if showNormal then %>
 
+<table class="blanks">
 <form action="sec" method="post">
-<b>Your users:</b> <select name="uname">
+<input type="hidden" name="uname" value="<% Web.html uname %>">
+<tr> <td>Machines:</td> <td><select name="node">
+<% foreach node in Init.listNodes () do %>
+       <option value="<% #id node %>"<% if nodeNum = #id node then %> selected<% end %>><% Web.html (#name node) %> (<% Web.html (#descr node) %>)</option>
+<% end %></select></td>
+<td><input type="submit" value="Switch"></td> </tr>
+</form>
+<form action="sec" method="post">
+<input type="hidden" name="node" value="<% nodeNum %>">
+<tr> <td>Your users:</td> <td><select name="uname">
 <% foreach name in (yourname :: Sec.findSubusers yourname) do %>
        <option value="<% name %>"<% if uname = name then %> selected<% end %>><% name %></option>
-<% end %></select> <input type="submit" value="Switch"> </form>
+<% end %></select></td>
+<td><input type="submit" value="Switch"></td> </tr>
+</form>
+</table>
+
+<!--h3>Request socket permissions change</h3>
+
+<p>You need to request socket permissions before you are able to open any network connections. While you will be limited by firewall rules even then, any requests for firewall rules you enter in the "Reason" blank here <b>will be ignored</b>. Please use the separate form at the bottom of this page for that. There is no need to wait until a request for socket permissions has been granted before starting to request firewall rules.</p>
 
-<h3>Request socket permissions change</h3>
+<p>Keep in mind that, if your request is granted, it will never apply to existing log-in sessions. Close them and re-connect to take advantage of your new privileges.</p>
 
 <form action="sec" method="post">
+<input type="hidden" name="node" value="<% nodeNum %>">
 <input type="hidden" name="uname" value="<% uname %>">
 <input type="hidden" name="cmd" value="socks">
 <table class="blanks">
@@ -233,6 +272,7 @@ if showNormal then %>
 <h3>Request change to your execute permissions</h3>
 
 <form action="sec" method="post">
+<input type="hidden" name="node" value="<% nodeNum %>">
 <input type="hidden" name="uname" value="<% uname %>">
 <input type="hidden" name="cmd" value="tpe">
 <table class="blanks">
@@ -243,11 +283,12 @@ if showNormal then %>
 <tr> <td>Reason:</td> <td><textarea name="msg" wrap="soft" rows="3" cols="80"></textarea></td> </tr>
 <tr> <td><input type="submit" value="Request"></td> </tr>
 </table>
-</form>
+</form-->
 
 <h3>Request change to your <tt>cron</tt> permissions</h3>
 
 <form action="sec" method="post">
+<input type="hidden" name="node" value="<% nodeNum %>">
 <input type="hidden" name="uname" value="<% uname %>">
 <input type="hidden" name="cmd" value="cron">
 <table class="blanks">
@@ -265,6 +306,7 @@ if showNormal then %>
 <p>Please read <a href="http://wiki.hcoop.net/wiki/FileTransfer">our wiki instructions on file transfer</a> before requesting FTP access. Almost everyone should use alternative protocols to FTP that provide superior security benefits.</p>
 
 <form action="sec" method="post">
+<input type="hidden" name="node" value="<% nodeNum %>">
 <input type="hidden" name="uname" value="<% uname %>">
 <input type="hidden" name="cmd" value="ftp">
 <table class="blanks">
@@ -277,13 +319,14 @@ if showNormal then %>
 </table>
 </form>
 
-<% val rules = Sec.findFirewallRules uname;
+<% val rules = Sec.findFirewallRules {node = nodeNum, uname = uname};
 switch rules of
   _::_ => %>
 <h3>Your firewall rules</h3>
 
 <% foreach rule in rules do %>
 <form action="sec" method="post">
+<input type="hidden" name="node" value="<% nodeNum %>">
 <input type="hidden" name="uname" value="<% uname %>">
 <input type="hidden" name="modRule" value="<% Web.html rule %>">
 <input name="rule" value="<% Web.html rule %>">
@@ -295,11 +338,16 @@ end%>
 
 <h3>Request a new firewall rule</h3>
 
+<p><b>This form isn't needed yet to allow you to use any port.  However, if you request a rule here, you can be sure it will be added when we first implement firewalls on our new servers.  Otherwise, your custom services may stop working.</b></p>
+
 <p>You can find a description of rule formats <a href="http://wiki.hcoop.net/wiki/FirewallRules">on our wiki</a>. Enter here the rule you want, without the initial <tt>user</tt> portion.</p>
 
-<p>Please note that <b>your firewall rule will be useless</b> if you don't first request the corresponding socket privileges at the top of this page.</p>
+<p>Please note that <b>your firewall rule will be useless</b> if you don't first request the corresponding socket privileges at the top of this page. Also, common ports like 80 (HTTP) are open to everyone with socket permissions. Verify that you can't access a port after socket permissions have been granted before requesting a special rule here.</p>
+
+<p>We very rarely grant requests for Client rules that don't include remote host whitelists. For example, important security concerns make it a bad idea for us to give anybody blanket IRC permissions. Instead, request specific servers. We will refuse such requests that include networks that are popularly considered fronts for illegal activity.</p>
 
 <form action="sec" method="post">
+<input type="hidden" name="node" value="<% nodeNum %>">
 <input type="hidden" name="uname" value="<% uname %>">
 <input type="hidden" name="cmd" value="rule">
 <table class="blanks">