comparison src/luan/host/WebHandler.java @ 1330:f41919741100

fix security
author Franklin Schmidt <fschmidt@gmail.com>
date Mon, 11 Feb 2019 01:38:55 -0700
parents 307e76ccd0d6
children 11b7e11f9ed5
comparison
equal deleted inserted replaced
1329:5a39b006acd1 1330:f41919741100
5 import org.slf4j.LoggerFactory; 5 import org.slf4j.LoggerFactory;
6 import luan.webserver.Handler; 6 import luan.webserver.Handler;
7 import luan.webserver.Request; 7 import luan.webserver.Request;
8 import luan.webserver.Response; 8 import luan.webserver.Response;
9 import luan.webserver.handlers.DomainHandler; 9 import luan.webserver.handlers.DomainHandler;
10 import luan.Luan;
10 import luan.LuanState; 11 import luan.LuanState;
11 import luan.LuanException; 12 import luan.LuanException;
12 import luan.LuanTable; 13 import luan.LuanTable;
13 import luan.modules.IoLuan; 14 import luan.LuanFunction;
14 import luan.modules.JavaLuan; 15 import luan.LuanClosure;
16 import luan.modules.BasicLuan;
15 import luan.modules.http.LuanHandler; 17 import luan.modules.http.LuanHandler;
16 import luan.modules.logging.LuanLogger; 18 import luan.modules.logging.LuanLogger;
17 19
18 20
19 public class WebHandler implements Handler { 21 public class WebHandler implements Handler {
20 private static final Logger logger = LoggerFactory.getLogger(WebHandler.class); 22 private static final Logger logger = LoggerFactory.getLogger(WebHandler.class);
23
24 private static final class LuanRuntimeException extends RuntimeException {
25 final LuanException e;
26
27 LuanRuntimeException(LuanException e) {
28 this.e = e;
29 }
30 }
21 31
22 private static final DomainHandler.Factory factory = new DomainHandler.Factory() { 32 private static final DomainHandler.Factory factory = new DomainHandler.Factory() {
23 public Handler newHandler(String domain) { 33 public Handler newHandler(String domain) {
24 File dir = new File(sitesDir,domain); 34 File dir = new File(sitesDir,domain);
25 if( !dir.exists() /* && !recover(dir) */ ) 35 if( !dir.exists() /* && !recover(dir) */ )
38 initLuan(luan,dirStr,domain,true); 48 initLuan(luan,dirStr,domain,true);
39 return new LuanHandler(luan); 49 return new LuanHandler(luan);
40 } 50 }
41 }; 51 };
42 52
43 public static String allowJavaFileName = "allow_java"; // change for security 53 public static String securityPassword = "password"; // change for security
44 private static final DomainHandler domainHandler = new DomainHandler(factory); 54 private static final DomainHandler domainHandler = new DomainHandler(factory);
45 private static String sitesDir = null; 55 private static String sitesDir = null;
46 56
47 public static boolean isServing() { 57 public static boolean isServing() {
48 return sitesDir != null; 58 return sitesDir != null;
88 throw new RuntimeException("couldn't rename "+from+" to "+dir); 98 throw new RuntimeException("couldn't rename "+from+" to "+dir);
89 logger.info("recovered "+name+" from "+from); 99 logger.info("recovered "+name+" from "+from);
90 return true; 100 return true;
91 } 101 }
92 */ 102 */
93 static LuanTable initLuan(LuanState luan,String dir,String domain,boolean logging) { 103 static void initLuan(LuanState luan,String dir,String domain,boolean logging) {
94 LuanTable init; 104 security(luan,dir);
95 try { 105 try {
96 init = (LuanTable)luan.eval( 106 LuanFunction fn = BasicLuan.load_file(luan,"classpath:luan/host/init.luan");
97 "local Luan = require 'luan:Luan.luan'\n" 107 fn.call(luan,new Object[]{dir,domain,logging});
98 +"local f = Luan.load_file 'classpath:luan/host/Init.luan'\n"
99 +"return f('"+dir+"','"+domain+"',"+logging+")\n"
100 );
101 } catch(LuanException e) { 108 } catch(LuanException e) {
102 throw new RuntimeException(e); 109 throw new LuanRuntimeException(e);
103 } 110 }
104 File allowJavaFile = new File(dir,"site/private/"+allowJavaFileName);
105 if( !allowJavaFile.exists() ) {
106 JavaLuan.setSecurity( luan, javaSecurity );
107 IoLuan.setSecurity( luan, ioSecurity(dir) );
108 }
109 return init;
110 } 111 }
111 112
112 public static void removeHandler(String domain) { 113 public static void removeHandler(String domain) {
113 domainHandler.removeHandler(domain); 114 domainHandler.removeHandler(domain);
114 } 115 }
115 116
116 public static void loadHandler(String domain) { 117 public static void loadHandler(String domain) throws LuanException {
117 domainHandler.getHandler(domain); 118 try {
119 domainHandler.getHandler(domain);
120 } catch(LuanRuntimeException e) {
121 throw e.e;
122 }
118 } 123 }
119 124
120 private static final IoLuan.Security ioSecurity(String dir) { 125 private static final void security(LuanState luan,String dir) {
121 final String siteUri = "file:" + dir + "/site"; 126 final String siteUri = "file:" + dir + "/site";
122 return new IoLuan.Security() { 127 Luan.Security security = new Luan.Security() {
123 public void check(LuanState luan,String name) throws LuanException { 128 public void check(LuanState luan,LuanClosure closure,String op,Object... args)
124 if( name.startsWith("file:") ) { 129 throws LuanException
125 if( name.contains("..") ) 130 {
126 throw new LuanException("Security violation - '"+name+"' contains '..'"); 131 if( op.equals("uri") ) {
127 if( !(name.equals(siteUri) || name.startsWith(siteUri+"/")) ) 132 String name = (String)args[0];
128 throw new LuanException("Security violation - '"+name+"' outside of site dir"); 133 if( name.startsWith("file:") ) {
129 } 134 if( name.contains("..") )
130 else if( name.startsWith("classpath:luan/host/") ) { 135 throw new LuanException("Security violation - '"+name+"' contains '..'");
131 throw new LuanException("Security violation"); 136 if( !(name.equals(siteUri) || name.startsWith(siteUri+"/")) )
132 } 137 throw new LuanException("Security violation - '"+name+"' outside of site dir");
133 else if( name.startsWith("os:") || name.startsWith("bash:") ) { 138 }
134 throw new LuanException("Security violation"); 139 else if( name.startsWith("classpath:luan/host/") ) {
140 throw new LuanException("Security violation");
141 }
142 else if( name.startsWith("os:") || name.startsWith("bash:") ) {
143 throw new LuanException("Security violation");
144 }
145 } else {
146 String name = closure.sourceName;
147 if( !(
148 name.startsWith("luan:")
149 || name.startsWith("classpath:")
150 || name.matches("^file:[^/]+$")
151 ) )
152 throw new LuanException("Security violation - only luan:* modules can load Java");
153 if( name.equals("luan:logging/Logging") )
154 throw new LuanException("Security violation - cannot reload Logging");
135 } 155 }
136 } 156 }
137 }; 157 };
158 Luan.setSecurity(luan,security);
138 } 159 }
139 160
140 private static final JavaLuan.Security javaSecurity = new JavaLuan.Security() {
141 public void check(LuanState luan,String name) throws LuanException {
142 if( !(name.startsWith("luan:") || name.matches("^file:[^/]+$")) )
143 throw new LuanException("Security violation - only luan:* modules can load Java");
144 if( name.equals("luan:logging/Logging") )
145 throw new LuanException("Security violation - cannot reload Logging");
146 }
147 };
148 } 161 }