Create your web server with http.sys with NTLM authentication

  • EDIT: If you plan to use only Vista, Windows Server 2008 or later version of Windows, please check this updated version for HTTP.SYS 2.0
  • Since Windows 2003, Microsoft Windows expose a high performance HTTP API which is use as the core of II6. As this API have been backported to Win XP SP2, it can now be used on all supported version of Windows. Correctly implemented, this API allows to create high performance web server directly in third party process without using IIS. In this post I will present complete sample of how to use the HTTP API for an high performance web server with a full NTLM authentication implementation.
     

    What is HTTP.SYS

    With IIS 6.0, Microsoft has included the HTTP server directly into the Windows kernel with a special device driver called HTTP.SYS. While initially only available on Windows 2003, the driver and his associated API was back ported to Windows XP SP2. HTTP.SYS is the real core of all subsequent version IIS. The worker processes connect to HTTP.SYS and receive requests via a kernel queue. With this system, contrary to IIS 5, there is no need of using IPC between a server process and the worker:

    Create your own server

    The HTTP.SYS API is well documented by Microsoft and quite easy to use. The first step is to create your own kernel queue inside your process, then attach it to a set of URL:

    bool HttpServerStart(DWORD webPort)
    {
    	wchar_t urlTemplate[128];
     
    	_snwprintf_s(urlTemplate,sizeof(urlTemplate)/sizeof(wchar_t),
    		sizeof(urlTemplate)/sizeof(wchar_t),
    		L"http://+:%d/",webPort);
    	DBGINF("HTTP Url : [{0}]") % urlTemplate;
     
    	HTTPAPI_VERSION ver = HTTPAPI_VERSION_1;
    	ULONG ret = HttpInitialize(ver,HTTP_INITIALIZE_SERVER,NULL);
    	if(ret!=NO_ERROR)
    	{
    		DBGERR("HttpInitialize failed : {0}") % DBGWINERR(ret);
    		return false;
    	}
     
    	ret = HttpCreateHttpHandle(&g_hReqQueue, 0);
    	if(ret!=NO_ERROR)
    	{
    		DBGERR("HttpCreateHttpHandle failed : {0}") % DBGWINERR(ret);
    		return false;
    	}
     
    	ret = HttpAddUrl(g_hReqQueue, urlTemplate,NULL);
    	if(ret!=NO_ERROR)
    	{
    		DBGERR("HttpAddUrl failed : {0}") % DBGWINERR(ret);
    		return false;
    	}
     
    	InitializeCriticalSection(&sg_csConnections);
     
    	if(!BindIoCompletionCallback(g_hReqQueue,ServerIOCompletionRoutine, 0 ))
    	{
    		DBGERR("BindIoCompletionCallback failed : {0}") % DBGWINERR(ret);
    		return false;
    	}
     
    	return ChainQuery();
    }

    Once started, the queue can be polled with standard asynchronous IO. In the example, I’m using the Windows thread pool by binding the handle to a call-back using BindIoCompletionCallback.

    NTLM authentication

    HTTP.SYS 1.0 doesn’t support any authentication scheme directly. The user process has to implement it. The NTLM authentication is quite complex:

    The authentication must occur on one HTTP 1.1 session. If the link broken the process must be restarted. Because the SSPI auth layer consumes system resources, the server must track server disconnection.

    On Windows Vista and later

    On Windows Vista and later version, Microsoft have tightened the permission for creating web server. You need to adjust the access using the httpcfg tool.

    AttachmentSize
    HttpServerDemo.zip997.89 KB