none
Microsoft C++ HTTP Server API (httpapi.lib) HttpReceiveClientCertificate function Return ERROR_NOT_FOUND ( 1168 ) RRS feed

  • Question

  • Microsoft C++ HTTP Server API (httpapi.lib) for HTTPS

    I want create https server in c++ by Microsoft http server api

    http://msdn.microsoft.com/en-us/library/windows/desktop/aa364510(v=vs.85).aspx

    i following these steps that are mentioned below

    http://www.codeproject.com/Articles/24027/SSL-with-Self-hosted-WCF-Service?msg=3930582#xx3930582xx

    1. makecert -sv SignRoot.pvk -cy authority -r signroot.cer -a sha1 -n "CN=Dev Certification Authority" -ss my -sr localmachine

    Succeeded

    2. makecert -iv SignRoot.pvk -ic signroot.cer -cy end -pe -n CN="localhost" -eku 1.3.6.1.5.5.7.3.1 -ss my -sr localmachine -sky exchange -sp "Microsoft RSA SChannel Cryptographic Provider" -sy 12

    Succeeded

    3.  config https according

    http://msdn.microsoft.com/en-us/library/ms733791.aspx

    netsh http add sslcert ipport=127.0.0.1:4443 certhash=9eb4919ea794d783a348a0469474c4cf45d65fb3 appid={F8C3E640-D91E-11D2-9944-8F3C3FD5C32F} sslctlstorename=MY clientcertnegotiation=enable

    SSL Certificate successfully added

    Result :

       IP:port                 : 127.0.0.1:4443

        Certificate Hash        : 9eb4919ea794d783a348a0469474c4cf45d65fb3

        Application ID          : {f8c3e640-d91e-11d2-9944-8f3c3fd5c32f}

        Certificate Store Name  : (null)

        Verify Client Certificate Revocation    : Enabled

        Verify Revocation Using Cached Client Certificate Only    : Disabled

        Usage Check    : Enabled

        Revocation Freshness Time : 0

        URL Retrieval Timeout   : 0

        Ctl Identifier          : (null)

        Ctl Store Name          : MY

        DS Mapper Usage    : Disabled

        Negotiate Client Certificate    : Enabled

    This is complete sample code

    #include "stdafx.h"
    #include <stdio.h>
    #include <iostream>
    #include <cstdlib>
    #include <conio.h>
    #include <iostream> 
    #include <tchar.h>
    
    using namespace std;
    
    #ifndef _WIN32_WINNT
    #define _WIN32_WINNT 0x0600
    #endif
    
    #ifndef WIN32_LEAN_AND_MEAN
    #define WIN32_LEAN_AND_MEAN
    #endif
    
    #include <http.h>
    #pragma comment(lib, "httpapi.lib")
    
    //
    // Macros.
    //
    #define INITIALIZE_HTTP_RESPONSE( resp, status, reason )    \
    do                                                      \
    {                                                       \
        RtlZeroMemory( (resp), sizeof(*(resp)) );           \
        (resp)->StatusCode = (status);                      \
        (resp)->pReason = (reason);                         \
        (resp)->ReasonLength = (USHORT) strlen(reason);     \
    } while (FALSE)
    
    #define ADD_KNOWN_HEADER(Response, HeaderId, RawValue)               \
    do                                                               \
    {                                                                \
        (Response).Headers.KnownHeaders[(HeaderId)].pRawValue =      \
                                                          (RawValue);\
        (Response).Headers.KnownHeaders[(HeaderId)].RawValueLength = \
            (USHORT) strlen(RawValue);                               \
    } while(FALSE)
    
    #define ALLOC_MEM(cb) HeapAlloc(GetProcessHeap(), 0, (cb))
    
    #define FREE_MEM(ptr) HeapFree(GetProcessHeap(), 0, (ptr))
    
    //
    // Prototypes.
    //
    DWORD DoReceiveRequests(HANDLE hReqQueue);
    
    DWORD SendHttpResponse(HANDLE hReqQueue, PHTTP_REQUEST pRequest, USHORT StatusCode, PSTR pReason, PSTR pEntity);
    
    DWORD SendHttpPostResponse(HANDLE hReqQueue, PHTTP_REQUEST pRequest);
    
    /*******************************************************************/
    
    int __cdecl wmain(int argc, wchar_t * argv[])
    {	
    	HTTPAPI_VERSION HttpApiVersion = HTTPAPI_VERSION_1;
    
    	ULONG ret = NO_ERROR;
    	HRESULT hr = S_OK;
    	HTTPAPI_VERSION ver = HTTPAPI_VERSION_1;
    
    	ret = HttpInitialize(ver,HTTP_INITIALIZE_SERVER|HTTP_INITIALIZE_CONFIG,NULL);
    	if(ret!=NO_ERROR)
    		return 0;
    
    
    	ULONG           retCode;
    	HANDLE          hReqQueue      = NULL;  //request queue handle
    	int             UrlAdded       = 0;
    
    	retCode = HttpInitialize( 
    				HttpApiVersion,
    				HTTP_INITIALIZE_SERVER ,
    				NULL                     
    				);
    
    	if (retCode == NO_ERROR)
    	{  
    		retCode = HttpCreateHttpHandle(&hReqQueue,// Req Queue
    					0                  // Reserved
    					);   
    		if (retCode == NO_ERROR)
    		{    
    			 retCode = HttpAddUrl(
    							hReqQueue,    // Req Queue
    							L"https://127.0.0.1:4443/",// Fully qualified URL
    							NULL          // Reserved
    							);
    			if (retCode == NO_ERROR)
    			{			 
    			  DoReceiveRequests(hReqQueue);
    			}      
    		}
    	}	       	 
    	return retCode;
    }//main
    
    
    /*******************************************************************++
    
    Routine Description:
    The function to receive a request. This function calls the  
    corresponding function to handle the response.
    
    Arguments:
    hReqQueue - Handle to the request queue
    
    Return Value:
    Success/Failure.
    
    --*******************************************************************/
    DWORD DoReceiveRequests(IN HANDLE hReqQueue)
    {
    ULONG              result;
    HTTP_REQUEST_ID    requestId;
    DWORD              bytesRead;
    PHTTP_REQUEST      pRequest;
    PCHAR              pRequestBuffer;
    ULONG              RequestBufferLength;
    
    //
    // Allocate a 2 KB buffer. This size should work for most 
    // requests. The buffer size can be increased if required. Space
    // is also required for an HTTP_REQUEST structure.
    //
    RequestBufferLength = sizeof(HTTP_REQUEST) + 2048;
    pRequestBuffer      = (PCHAR) ALLOC_MEM( RequestBufferLength );
    
    if (pRequestBuffer == NULL)
    {
        return ERROR_NOT_ENOUGH_MEMORY;
    }
    
    pRequest = (PHTTP_REQUEST)pRequestBuffer;
    
    //
    // Wait for a new request. This is indicated by a NULL 
    // request ID.
    //
    
    HTTP_SET_NULL_ID( &requestId );
    
    for(;;)
    {
        RtlZeroMemory(pRequest, RequestBufferLength);
    
        result = HttpReceiveHttpRequest(
                    hReqQueue,          // Req Queue
                    requestId,          // Req ID
                    0,                  // Flags
                    pRequest,           // HTTP request buffer
                    RequestBufferLength,// req buffer length
                    &bytesRead,         // bytes received
                    NULL                // LPOVERLAPPED
                    );
              if(NO_ERROR == result)
        {
    
            DWORD answer = 0;
            HTTP_SSL_CLIENT_CERT_INFO sslClientCertInfo;
            ULONG bytesReceived;
            answer = HttpReceiveClientCertificate(hReqQueue, pRequest->ConnectionId, 0,
                    &sslClientCertInfo, sizeof( HTTP_SSL_CLIENT_CERT_INFO ), &bytesReceived, NULL );
    
    
            if (answer != NO_ERROR)
            {
              result = SendHttpResponse(hReqQueue, pRequest, 401, "Unauthorized request", "Unauthorized request");
            }
            else
            {
              result = SendHttpResponse(hReqQueue, pRequest, 200, "OK", "OK");
            }
    
            if (result != NO_ERROR)
            {
              break; //if failed to send response, stop listening for further incoming requests
            }
            //
            // Reset the Request ID to handle the next request.
            //
            HTTP_SET_NULL_ID( &requestId );
        }
        else
        {
            break;
        }
    
    }
    if(pRequestBuffer)
    {
        FREE_MEM( pRequestBuffer );
    }
    
    return result;
    }
    
    
    
    /*******************************************************************++
    
    Routine Description:
    The routine sends a HTTP response
    
    Arguments:
    hReqQueue     - Handle to the request queue
    pRequest      - The parsed HTTP request
    StatusCode    - Response Status Code
    pReason       - Response reason phrase
    pEntityString - Response entity body
    
    Return Value:
    Success/Failure.
    --*******************************************************************/
    
    DWORD SendHttpResponse(
    IN HANDLE        hReqQueue,
    IN PHTTP_REQUEST pRequest,
    IN USHORT        StatusCode,
    IN PSTR          pReason,
    IN PSTR          pEntityString
    )
    {
    HTTP_RESPONSE   response;
    HTTP_DATA_CHUNK dataChunk;
    DWORD           result;
    DWORD           bytesSent;
    
    
    INITIALIZE_HTTP_RESPONSE(&response, StatusCode, pReason);
    ADD_KNOWN_HEADER(response, HttpHeaderContentType, "text/html");
    
    
    if(pEntityString)
    {
        // 
        // Add an entity chunk.
        //
        dataChunk.DataChunkType           = HttpDataChunkFromMemory;
        dataChunk.FromMemory.pBuffer      = pEntityString;
        dataChunk.FromMemory.BufferLength = 
                                       (ULONG) strlen(pEntityString);
    
        response.EntityChunkCount         = 1;
        response.pEntityChunks            = &dataChunk;
    }
    
    result = HttpSendHttpResponse(
                    hReqQueue,           // ReqQueueHandle
                    pRequest->RequestId, // Request ID
                    0,                   // Flags
                    &response,           // HTTP response
                    NULL,                // pReserved1
                    &bytesSent,          // bytes sent  (OPTIONAL)
                    NULL,                // pReserved2  (must be NULL)
                    0,                   // Reserved3   (must be 0)
                    NULL,                // LPOVERLAPPED(OPTIONAL)
                    NULL                 // pReserved4  (must be NULL)
                    ); 
    
    if(result != NO_ERROR)
    {
        wprintf(L"HttpSendHttpResponse failed with %lu \n", result);
    }
    
    return result;
    }
    


    My problem is

    HttpReceiveClientCertificate

    Return

    1168

    ERROR_NOT_FOUND

    The function cannot find the client certificate. There is no guarantee that the client certificate will be available even if HTTPCFG is configured with /f 2 [Negotiate Client Cert].

    http://msdn.microsoft.com/en-us/library/windows/desktop/aa364494(v=vs.85).aspx

    my question is why I get error 1168 when I recive request from https://127.0.0.1:4443/

    thanks


    • Edited by s.naderi Monday, February 18, 2013 8:47 AM
    Monday, February 18, 2013 8:42 AM