rpcsrv: allow any Origin in WS connections if EnableCORSWorkaround

Break origin checks even more. Alternative to #2772.
This commit is contained in:
Roman Khimov 2022-11-09 08:55:57 +03:00
parent e3c503cee9
commit 3247aa40a7
2 changed files with 16 additions and 7 deletions

View file

@ -158,8 +158,15 @@ RPC:
where: where:
- `Enabled` denotes whether an RPC server should be started. - `Enabled` denotes whether an RPC server should be started.
- `Address` is an RPC server address to be running at. - `Address` is an RPC server address to be running at.
- `EnableCORSWorkaround` enables Cross-Origin Resource Sharing and is useful if - `EnableCORSWorkaround` turns on a set of origin-related behaviors that make
you're accessing RPC interface from the browser. RPC server wide open for connections from any origins. It enables OPTIONS
request handling for pre-flight CORS and makes the server send
`Access-Control-Allow-Origin` and `Access-Control-Allow-Headers` headers for
regular HTTP requests (allowing any origin which effectively makes CORS
useless). It also makes websocket connections work for any `Origin`
specified in the request header. This option is not recommended (reverse
proxy can be used to have proper app-specific CORS settings), but it's an
easy way to make RPC interface accessible from the browser.
- `MaxGasInvoke` is the maximum GAS allowed to spend during `invokefunction` and - `MaxGasInvoke` is the maximum GAS allowed to spend during `invokefunction` and
`invokescript` RPC-calls. `invokescript` RPC-calls.
- `MaxIteratorResultItems` - maximum number of elements extracted from iterator - `MaxIteratorResultItems` - maximum number of elements extracted from iterator

View file

@ -122,6 +122,7 @@ type (
config config.RPC config config.RPC
// wsReadLimit represents web-socket message limit for a receiving side. // wsReadLimit represents web-socket message limit for a receiving side.
wsReadLimit int64 wsReadLimit int64
upgrader websocket.Upgrader
network netmode.Magic network netmode.Magic
stateRootEnabled bool stateRootEnabled bool
coreServer *network.Server coreServer *network.Server
@ -249,10 +250,6 @@ var invalidBlockHeightError = func(index int, height int) *neorpc.Error {
return neorpc.NewRPCError("Invalid block height", fmt.Sprintf("param at index %d should be greater than or equal to 0 and less then or equal to current block height, got: %d", index, height)) return neorpc.NewRPCError("Invalid block height", fmt.Sprintf("param at index %d should be greater than or equal to 0 and less then or equal to current block height, got: %d", index, height))
} }
// upgrader is a no-op websocket.Upgrader that reuses HTTP server buffers and
// doesn't set any Error function.
var upgrader = websocket.Upgrader{}
// New creates a new Server struct. // New creates a new Server struct.
func New(chain Ledger, conf config.RPC, coreServer *network.Server, func New(chain Ledger, conf config.RPC, coreServer *network.Server,
orc OracleHandler, log *zap.Logger, errChan chan error) Server { orc OracleHandler, log *zap.Logger, errChan chan error) Server {
@ -282,11 +279,16 @@ func New(chain Ledger, conf config.RPC, coreServer *network.Server,
if orc != nil { if orc != nil {
oracleWrapped.Store(&orc) oracleWrapped.Store(&orc)
} }
var wsOriginChecker func(*http.Request) bool
if conf.EnableCORSWorkaround {
wsOriginChecker = func(_ *http.Request) bool { return true }
}
return Server{ return Server{
Server: httpServer, Server: httpServer,
chain: chain, chain: chain,
config: conf, config: conf,
wsReadLimit: int64(protoCfg.MaxBlockSize*4)/3 + 1024, // Enough for Base64-encoded content of `submitblock` and `submitp2pnotaryrequest`. wsReadLimit: int64(protoCfg.MaxBlockSize*4)/3 + 1024, // Enough for Base64-encoded content of `submitblock` and `submitp2pnotaryrequest`.
upgrader: websocket.Upgrader{CheckOrigin: wsOriginChecker},
network: protoCfg.Magic, network: protoCfg.Magic,
stateRootEnabled: protoCfg.StateRootInHeader, stateRootEnabled: protoCfg.StateRootInHeader,
coreServer: coreServer, coreServer: coreServer,
@ -431,7 +433,7 @@ func (s *Server) handleHTTPRequest(w http.ResponseWriter, httpRequest *http.Requ
) )
return return
} }
ws, err := upgrader.Upgrade(w, httpRequest, nil) ws, err := s.upgrader.Upgrade(w, httpRequest, nil)
if err != nil { if err != nil {
s.log.Info("websocket connection upgrade failed", zap.Error(err)) s.log.Info("websocket connection upgrade failed", zap.Error(err))
return return