Coverage Summary for Class: JsonRpcWeb3FilterHandler (co.rsk.rpc.netty)

Class Class, % Method, % Line, %
JsonRpcWeb3FilterHandler 0% (0/1) 0% (0/6) 0% (0/55)


1 package co.rsk.rpc.netty; 2  3 import co.rsk.rpc.OriginValidator; 4 import io.netty.channel.ChannelFutureListener; 5 import io.netty.channel.ChannelHandler; 6 import io.netty.channel.ChannelHandlerContext; 7 import io.netty.channel.SimpleChannelInboundHandler; 8 import io.netty.handler.codec.http.*; 9 import org.ethereum.rpc.HttpUtils; 10 import org.slf4j.Logger; 11 import org.slf4j.LoggerFactory; 12  13 import java.net.*; 14 import java.util.ArrayList; 15 import java.util.List; 16  17 /** 18  * Created by ajlopez on 18/10/2017. 19  */ 20  21 @ChannelHandler.Sharable 22 public class JsonRpcWeb3FilterHandler extends SimpleChannelInboundHandler<FullHttpRequest> { 23  private static final Logger logger = LoggerFactory.getLogger("jsonrpc"); 24  private final List<String> rpcHost; 25  private final InetAddress rpcAddress; 26  private final List<String> acceptedHosts; 27  28  private OriginValidator originValidator; 29  30  public JsonRpcWeb3FilterHandler(String corsDomains, InetAddress rpcAddress, List<String> rpcHost) { 31  this.originValidator = new OriginValidator(corsDomains); 32  this.rpcHost = rpcHost; 33  this.rpcAddress = rpcAddress; 34  this.acceptedHosts = getAcceptedHosts(); 35  } 36  37  private List<String> getAcceptedHosts() { 38  List<String> hosts = new ArrayList<>(); 39  if (isAcceptedAddress(rpcAddress)) { 40  hosts.add(rpcAddress.getHostName()); 41  hosts.add(rpcAddress.getHostAddress()); 42  } else { 43  for (String host : rpcHost) { 44  try { 45  InetAddress hostAddress = InetAddress.getByName(host); 46  if (!hostAddress.isAnyLocalAddress()) { 47  hosts.add(hostAddress.getHostAddress()); 48  hosts.add(hostAddress.getHostName()); 49  } else { 50  logger.warn("Wildcard address is not allowed on rpc host property {}", hostAddress); 51  } 52  } catch (UnknownHostException e) { 53  logger.warn("Invalid Host defined on rpc.host", e); 54  } 55  } 56  } 57  return hosts; 58  } 59  60  @Override 61  protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) throws Exception { 62  HttpResponse response; 63  HttpMethod httpMethod = request.getMethod(); 64  HttpHeaders headers = request.headers(); 65  66  // when a request has multiple host fields declared it would be equivalent to a comma separated list 67  // the request will be inmediately rejected since it won't be parsed as a valid URI 68  // and won't work to match an item on rpc.host 69  String hostHeader = headers.get(HttpHeaders.Names.HOST); 70  String parsedHeader = parseHostHeader(hostHeader); 71  72  if (!acceptedHosts.contains(parsedHeader)) { 73  logger.debug("Invalid header HOST {}", hostHeader); 74  response = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.BAD_REQUEST); 75  ctx.write(response).addListener(ChannelFutureListener.CLOSE); 76  return; 77  } 78  79  if (HttpMethod.POST.equals(httpMethod)) { 80  81  String mimeType = HttpUtils.getMimeType(headers.get(HttpHeaders.Names.CONTENT_TYPE)); 82  String origin = headers.get(HttpHeaders.Names.ORIGIN); 83  String referer = headers.get(HttpHeaders.Names.REFERER); 84  85  if (!"application/json".equals(mimeType) && !"application/json-rpc".equals(mimeType)) { 86  logger.debug("Unsupported content type"); 87  response = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.UNSUPPORTED_MEDIA_TYPE); 88  } else if (origin != null && !this.originValidator.isValidOrigin(origin)) { 89  logger.debug("Invalid origin"); 90  response = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.BAD_REQUEST); 91  } else if (referer != null && !this.originValidator.isValidReferer(referer)) { 92  logger.debug("Invalid referer"); 93  response = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.BAD_REQUEST); 94  } 95  else { 96  ctx.fireChannelRead(request); 97  return; 98  } 99  } else { 100  response = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.NOT_IMPLEMENTED); 101  } 102  103  ctx.write(response).addListener(ChannelFutureListener.CLOSE); 104  } 105  106  private String parseHostHeader(String hostHeader) { 107  try { 108  // WORKAROUND: add any scheme to make the resulting URI valid. 109  URI uri = new URI("my://" + hostHeader); // may throw URISyntaxException 110  return uri.getHost(); 111  } catch (URISyntaxException e) { 112  return hostHeader; 113  } 114  } 115  116  private boolean isAcceptedAddress(final InetAddress address) { 117  // Check if the address is a valid special local or loop back 118  if (address.isLoopbackAddress() ) { 119  return true; 120  } 121  // Check if the address is defined on any interface 122  try { 123  return !address.isAnyLocalAddress() && NetworkInterface.getByInetAddress(address) != null; 124  } catch (SocketException se) { 125  return false; 126  } 127  } 128  129 }