vibe-d / vibe-http

Future vibe.d HTTP implementation
15 stars 9 forks source link

Using InterfaceProxy to extract peerCertificates fails (assertion error) #6

Closed GallaFrancesco closed 6 years ago

GallaFrancesco commented 6 years ago

While testing ALPN with HTTP/2 I ran into the following AssertError:

core.exception.AssertError@/home/fra/_progs/saoc/vibe-core/source/vibe/internal/interfaceproxy.d(132):    
Extraction of wrong type from InterfaceProxy.    
----------------                                              
??:? _d_assert_msg [0x60187dc2]                                             
??:? nothrow @trusted vibe.internal.freelistref.FreeListRef!(vibe.stream.openssl.OpenSSLStream, true).F    
reeListRef vibe.internal.interfaceproxy.InterfaceProxy!(vibe.core.stream.Stream).InterfaceProxy.extract    
!(vibe.internal.freelistref.FreeListRef!(vibe.stream.openssl.OpenSSLStream, true).FreeListRef).extract(    
) [0xe2f1ed8b]                                                                                             
??:? @safe bool vibe.http.internal.http1.originalHandleRequest(vibe.internal.interfaceproxy.InterfacePr    
oxy!(vibe.core.stream.Stream).InterfaceProxy, vibe.core.net.TCPConnection, vibe.http.server.HTTPServerC    
ontext, vibe.http.server.HTTPServerSettings, ref bool, scope stdx.allocator.IAllocator) [0xe2f7f2cd]    
??:? @trusted void vibe.http.internal.http1.handleHTTP1Request!(vibe.core.net.TCPConnection).handleHTTP    
1Request(vibe.core.net.TCPConnection, vibe.http.server.HTTPServerContext).__lambda3() [0xe2f82451]    
??:? @safe void vibe.http.internal.http1.handleHTTP1Request!(vibe.core.net.TCPConnection).handleHTTP1Re    
quest(vibe.core.net.TCPConnection, vibe.http.server.HTTPServerContext) [0xe2f82292]    
??:? @safe void vibe.http.internal.http1.handleHTTP1RequestChain!(vibe.core.net.TCPConnection).handleHT    
TP1RequestChain(vibe.core.net.TCPConnection, vibe.http.server.HTTPServerContext) [0xe2f82000]    
??:? void vibe.core.task.TaskFuncInfo.set!(void function(vibe.core.net.TCPConnection, vibe.http.server.    
HTTPServerContext) @safe*, vibe.core.net.TCPConnection, vibe.http.server.HTTPServerContext).set(ref voi    
d function(vibe.core.net.TCPConnection, vibe.http.server.HTTPServerContext) @safe*, ref vibe.core.net.T    
CPConnection, ref vibe.http.server.HTTPServerContext).callDelegate(ref vibe.core.task.TaskFuncInfo) [0x    
e2f603bb]    
??:? void vibe.core.task.TaskFuncInfo.call() [0xe3042f99]    
??:? nothrow void vibe.core.task.TaskFiber.run() [0xe30425a1]    
??:? void core.thread.Fiber.run() [0x6018ca57]    
??:? fiber_entryPoint [0x6018be22]    
??:? [0xffffffff]    
Program exited with code -6    

[Process exited 2]

The error above regards the following snipped of code in vibe.http.internal.http1:

166     if (req.tls) {
167         version (HaveNoTLS) assert(false);
168         else {    
169             static if (is(InterfaceProxy!ConnectionStream == ConnectionStream))
170                 req.clientCertificate = (cast(TLSStream)http_stream).peerCertificate;
171             else
172                 req.clientCertificate = http_stream.extract!TLSStreamType.peerCertificate;
173                 assert(false);
174         }       
175     } 

To reproduce the error, it is sufficient to initialize an HTTPS server and send a request. The assertion error occours using both HTTP/1.1 and HTTP/2, without difference. It is to be noted that the program never enters the static if clause (line 169) and the else clause (line 172) fails before reaching assert(false).

It looks like a type check which is never true (the assert is thrown at runtime after a typeid check in vibe.internal.interfaceproxy:132), but removing the compile time checks to allow for a direct cast of http_stream to type TLSStream does not work either, so I guess we should change how the http_stream is declared / managed in case of a TLS connection.

Note: This issue affects only the use of client certificates, therefore it is not critical to HTTP/2 introduction.