Made modifications to switch the client to communicate with ATSs over SSL. Still need to make changes to the linux rpc.c to have all of the necessary changes completed.
Also made a fix to allow credential store scoping all the way into the authentication mechanisms.
This commit is contained in:
		| @@ -7,4 +7,5 @@ EXPORTS | ||||
| ;                DllUnregisterServer PRIVATE | ||||
| ;                DllGetClassObject   PRIVATE | ||||
|                 ObtainAuthToken     PRIVATE         | ||||
|                 ObtainAuthTokenEx   PRIVATE         | ||||
| ;               DllCanUnloadNow     PRIVATE   | ||||
| @@ -21,7 +21,7 @@ | ||||
| 				Name="VCCLCompilerTool" | ||||
| 				AdditionalOptions="/D "XML_STATIC"" | ||||
| 				Optimization="0" | ||||
| 				AdditionalIncludeDirectories=".;..\;..\..\include;"C:\Dev\casa\CASA-auth-token\non-java\include\windows";"\Program Files\novell\casa\include";"C:\Dev\Expat-2.0.0\Source\lib"" | ||||
| 				AdditionalIncludeDirectories=".;..\;..\..\include;..\..\include\windows;"\Program Files\novell\casa\include";"C:\Dev\Expat-2.0.0\Source\lib"" | ||||
| 				PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE" | ||||
| 				MinimalRebuild="TRUE" | ||||
| 				BasicRuntimeChecks="3" | ||||
| @@ -35,7 +35,7 @@ | ||||
| 			<Tool | ||||
| 				Name="VCLinkerTool" | ||||
| 				IgnoreImportLibrary="FALSE" | ||||
| 				AdditionalOptions="/EXPORT:ObtainAuthToken" | ||||
| 				AdditionalOptions="/EXPORT:ObtainAuthToken /EXPORT:ObtainAuthTokenEx" | ||||
| 				AdditionalDependencies="ws2_32.lib winhttp.lib libexpatml.lib micasa.lib shlwapi.lib" | ||||
| 				OutputFile="$(OutDir)/authtoken.dll" | ||||
| 				LinkIncremental="1" | ||||
| @@ -53,7 +53,7 @@ | ||||
| mkdir \"Program Files"\novell\casa | ||||
| mkdir \"Program Files"\novell\casa\lib\ | ||||
| copy $(OutDir)\authtoken.dll \"Program Files"\novell\casa\lib\authtoken.dll | ||||
| copy $(SolutionDir)client\windows\authtoken.lib \"Program Files"\novell\casa\lib\authtoken.lib | ||||
| copy $(SolutionDir)\client\windows\authtoken.lib \"Program Files"\novell\casa\lib\authtoken.lib | ||||
| "/> | ||||
| 			<Tool | ||||
| 				Name="VCPreBuildEventTool"/> | ||||
| @@ -81,7 +81,7 @@ copy $(SolutionDir)client\windows\authtoken.lib \"Program Files"\novel | ||||
| 			<Tool | ||||
| 				Name="VCCLCompilerTool" | ||||
| 				AdditionalOptions="/D "XML_STATIC"" | ||||
| 				AdditionalIncludeDirectories=".;..\;..\..\include;"C:\Dev\casa\CASA-auth-token\non-java\include\windows";"\Program Files\novell\casa\include";"C:\Dev\Expat-2.0.0\Source\lib"" | ||||
| 				AdditionalIncludeDirectories=".;..\;..\..\include;..\..\include\windows;"\Program Files\novell\casa\include";"C:\Dev\Expat-2.0.0\Source\lib"" | ||||
| 				PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE" | ||||
| 				RuntimeLibrary="4" | ||||
| 				UsePrecompiledHeader="0" | ||||
| @@ -92,7 +92,7 @@ copy $(SolutionDir)client\windows\authtoken.lib \"Program Files"\novel | ||||
| 				Name="VCCustomBuildTool"/> | ||||
| 			<Tool | ||||
| 				Name="VCLinkerTool" | ||||
| 				AdditionalOptions="/EXPORT:ObtainAuthToken" | ||||
| 				AdditionalOptions="/EXPORT:ObtainAuthToken /EXPORT:ObtainAuthTokenEx" | ||||
| 				AdditionalDependencies="ws2_32.lib winhttp.lib libexpatml.lib micasa.lib shlwapi.lib" | ||||
| 				OutputFile="$(OutDir)/authtoken.dll" | ||||
| 				LinkIncremental="1" | ||||
| @@ -111,7 +111,7 @@ copy $(SolutionDir)client\windows\authtoken.lib \"Program Files"\novel | ||||
| mkdir \"Program Files"\novell\casa | ||||
| mkdir \"Program Files"\novell\casa\lib\ | ||||
| copy $(OutDir)\authtoken.dll \"Program Files"\novell\casa\lib\authtoken.dll | ||||
| copy $(SolutionDir)client\windows\authtoken.lib \"Program Files"\novell\casa\lib\authtoken.lib | ||||
| copy $(SolutionDir)\client\windows\authtoken.lib \"Program Files"\novell\casa\lib\authtoken.lib | ||||
| "/> | ||||
| 			<Tool | ||||
| 				Name="VCPreBuildEventTool"/> | ||||
| @@ -148,7 +148,7 @@ copy $(SolutionDir)client\windows\authtoken.lib \"Program Files"\novel | ||||
| 				RelativePath="..\authpolicy.c"> | ||||
| 			</File> | ||||
| 			<File | ||||
| 				RelativePath=".\win32\authtoken.def"> | ||||
| 				RelativePath=".\authtoken.def"> | ||||
| 			</File> | ||||
| 			<File | ||||
| 				RelativePath="..\cache.c"> | ||||
| @@ -171,6 +171,9 @@ copy $(SolutionDir)client\windows\authtoken.lib \"Program Files"\novel | ||||
| 			<File | ||||
| 				RelativePath="..\gettokenmsg.c"> | ||||
| 			</File> | ||||
| 			<File | ||||
| 				RelativePath="..\invalidcert.c"> | ||||
| 			</File> | ||||
| 			<File | ||||
| 				RelativePath=".\platform.c"> | ||||
| 			</File> | ||||
|   | ||||
| @@ -71,6 +71,7 @@ typedef struct _RpcSession | ||||
| { | ||||
|    HINTERNET   hSession; | ||||
|    HINTERNET   hConnection; | ||||
|    char        *pHostName; | ||||
|  | ||||
| } RpcSession, *PRpcSession; | ||||
|  | ||||
|   | ||||
| @@ -94,6 +94,62 @@ CopyMultiToWideAlloc( | ||||
| } | ||||
|  | ||||
|  | ||||
| //++======================================================================= | ||||
| static | ||||
| CasaStatus | ||||
| CopyWideToMultiAlloc( | ||||
|    IN    LPWSTR pWide, | ||||
|    IN    int wideSize, | ||||
|    INOUT char **ppMulti, | ||||
|    INOUT int *pMultiSize) | ||||
| // | ||||
| //  Arguments:  | ||||
| // | ||||
| //  Returns:    | ||||
| // | ||||
| //  Abstract:   | ||||
| // | ||||
| //  Notes: | ||||
| // | ||||
| // L2 | ||||
| //=======================================================================-- | ||||
| { | ||||
|    int      retStatus; | ||||
|    int      size, i; | ||||
|  | ||||
|    DbgTrace(2, "-CopyWideToMultiAlloc- Start\n", 0); | ||||
|  | ||||
|    size = wideSize + 1; | ||||
|  | ||||
|    if ((*ppMulti = malloc(size)) != NULL) | ||||
|    { | ||||
|       for (i = 0; i < wideSize; i++) | ||||
|       { | ||||
|          *(*ppMulti + i) = (char) *(pWide + i); | ||||
|       } | ||||
|  | ||||
|       *(*ppMulti + i) = '\0'; | ||||
|  | ||||
|       if (pMultiSize) | ||||
|       { | ||||
|          *pMultiSize = size - 1; | ||||
|       } | ||||
|  | ||||
|       retStatus = CASA_STATUS_SUCCESS; | ||||
|    } | ||||
|    else | ||||
|    { | ||||
|       retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, | ||||
|                                   CASA_FACILITY_AUTHTOKEN, | ||||
|                                   CASA_STATUS_INSUFFICIENT_RESOURCES); | ||||
|    } | ||||
|  | ||||
|    DbgTrace(2, "-CopyWideToMultiAlloc- End, retStatus = %08X\n", retStatus); | ||||
|  | ||||
|    return retStatus; | ||||
| } | ||||
|  | ||||
|  | ||||
| //++======================================================================= | ||||
| RpcSession* | ||||
| OpenRpcSession( | ||||
| @@ -112,6 +168,7 @@ OpenRpcSession( | ||||
| //=======================================================================-- | ||||
| { | ||||
|    RpcSession  *pSession; | ||||
|    bool        success = false; | ||||
|  | ||||
|    DbgTrace(1, "-OpenRpcSession- Start\n", 0); | ||||
|  | ||||
| @@ -122,55 +179,60 @@ OpenRpcSession( | ||||
|       // Zero the session structure | ||||
|       memset(pSession, 0, sizeof(*pSession)); | ||||
|  | ||||
|       // Open a Winhttp session | ||||
|       pSession->hSession = WinHttpOpen(L"CASA Client/1.0", | ||||
|                                        WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, | ||||
|                                        WINHTTP_NO_PROXY_NAME, | ||||
|                                        WINHTTP_NO_PROXY_BYPASS, | ||||
|                                        0); | ||||
|       if (pSession->hSession) | ||||
|       // Save copy of the hostname | ||||
|       pSession->pHostName = malloc(strlen(pHostName) + 1); | ||||
|       if (pSession->pHostName) | ||||
|       { | ||||
|          LPWSTR   pWideHostName; | ||||
|          int      wideHostLen; | ||||
|          strcpy(pSession->pHostName, pHostName); | ||||
|  | ||||
|          // Session opened, now convert the host name to Unicode so that | ||||
|          // we can open a connection. | ||||
|          if (CopyMultiToWideAlloc(pHostName, | ||||
|                                   (int) strlen(pHostName), | ||||
|                                   &pWideHostName, | ||||
|                                   &wideHostLen) == CASA_STATUS_SUCCESS) | ||||
|          // Open a Winhttp session | ||||
|          pSession->hSession = WinHttpOpen(L"CASA Client/1.0", | ||||
|                                           WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, | ||||
|                                           WINHTTP_NO_PROXY_NAME, | ||||
|                                           WINHTTP_NO_PROXY_BYPASS, | ||||
|                                           0); | ||||
|          if (pSession->hSession) | ||||
|          { | ||||
|             // Now open connection | ||||
|             pSession->hConnection = WinHttpConnect(pSession->hSession, | ||||
|                                                    pWideHostName, | ||||
|                                                    hostPort, | ||||
|                                                    0); | ||||
|             if (pSession->hConnection == NULL) | ||||
|             LPWSTR   pWideHostName; | ||||
|             int      wideHostLen; | ||||
|  | ||||
|             // Session opened, now convert the host name to Unicode so that | ||||
|             // we can open a connection. | ||||
|             if (CopyMultiToWideAlloc(pHostName, | ||||
|                                      (int) strlen(pHostName), | ||||
|                                      &pWideHostName, | ||||
|                                      &wideHostLen) == CASA_STATUS_SUCCESS) | ||||
|             { | ||||
|                DbgTrace(0, "-OpenRpcSession- Failed to open connection, error = %d\n", GetLastError()); | ||||
|                // Now open connection | ||||
|                pSession->hConnection = WinHttpConnect(pSession->hSession, | ||||
|                                                       pWideHostName, | ||||
|                                                       hostPort, | ||||
|                                                       0); | ||||
|                if (pSession->hConnection == NULL) | ||||
|                { | ||||
|                   DbgTrace(0, "-OpenRpcSession- Failed to open connection, error = %d\n", GetLastError()); | ||||
|                } | ||||
|                else | ||||
|                { | ||||
|                   success = true; | ||||
|                } | ||||
|  | ||||
|                // Free allocated resources | ||||
|                WinHttpCloseHandle(pSession->hSession); | ||||
|                free(pSession); | ||||
|                pSession = NULL; | ||||
|                // Free the host name wide string buffer | ||||
|                free(pWideHostName); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                DbgTrace(0, "-OpenRpcSession- Error converting host name to wide string\n", 0); | ||||
|             } | ||||
|  | ||||
|             // Free the host name wide string buffer | ||||
|             free(pWideHostName); | ||||
|          } | ||||
|          else | ||||
|          { | ||||
|             DbgTrace(0, "-OpenRpcSession- Error converting host name to wide string\n", 0); | ||||
|  | ||||
|             // Free allocated resources | ||||
|             WinHttpCloseHandle(pSession->hSession); | ||||
|             free(pSession); | ||||
|             pSession = NULL; | ||||
|             DbgTrace(0, "-OpenRpcSession- Failed to open session, error = %d\n", GetLastError()); | ||||
|          } | ||||
|       } | ||||
|       else | ||||
|       { | ||||
|          DbgTrace(0, "-OpenRpcSession- Failed to open session, error = %d\n", GetLastError()); | ||||
|          DbgTrace(0, "-OpenRpcSession- Failed to allocate buffer for host name\n", 0); | ||||
|       } | ||||
|    } | ||||
|    else | ||||
| @@ -178,6 +240,25 @@ OpenRpcSession( | ||||
|       DbgTrace(0, "-OpenRpcSession- Failed to allocate buffer for rpc session\n", 0); | ||||
|    } | ||||
|  | ||||
|    // Clean up if we did not succeed | ||||
|    if (!success) | ||||
|    { | ||||
|       if (pSession) | ||||
|       { | ||||
|          if (pSession->hConnection) | ||||
|             WinHttpCloseHandle(pSession->hConnection); | ||||
|  | ||||
|          if (pSession->hSession) | ||||
|             WinHttpCloseHandle(pSession->hSession); | ||||
|  | ||||
|          if (pSession->pHostName) | ||||
|             free(pSession->pHostName); | ||||
|  | ||||
|          free(pSession); | ||||
|          pSession = NULL; | ||||
|       } | ||||
|    } | ||||
|  | ||||
|    DbgTrace(2, "-OpenRpcSession- End, pSession = %08X\n", pSession); | ||||
|  | ||||
|    return pSession; | ||||
| @@ -208,6 +289,10 @@ CloseRpcSession( | ||||
|    // Close the session handle | ||||
|    WinHttpCloseHandle(pSession->hSession); | ||||
|  | ||||
|    // Free hostname buffer if necessary | ||||
|    if (pSession->pHostName) | ||||
|       free(pSession->pHostName); | ||||
|  | ||||
|    // Free the space allocated for the session | ||||
|    free(pSession); | ||||
|  | ||||
| @@ -215,13 +300,47 @@ CloseRpcSession( | ||||
| } | ||||
|  | ||||
|  | ||||
| //++======================================================================= | ||||
| static | ||||
| void CALLBACK | ||||
| SecureFailureStatusCallback( | ||||
|    IN    HINTERNET hRequest, | ||||
|    IN    DWORD *pContext, | ||||
|    IN    DWORD internetStatus, | ||||
|    IN    LPVOID pStatusInformation, | ||||
|    IN    DWORD statusInformationLength) | ||||
| // | ||||
| //  Arguments:  | ||||
| // | ||||
| //  Returns:    | ||||
| // | ||||
| //  Abstract:   | ||||
| // | ||||
| //  Notes: | ||||
| // | ||||
| // L0 | ||||
| //=======================================================================-- | ||||
| { | ||||
|    DbgTrace(1, "-SecureFailureStatusCallback- Start\n", 0); | ||||
|  | ||||
|    // Only deal with failures related to certificates | ||||
|    if (internetStatus == WINHTTP_CALLBACK_STATUS_SECURE_FAILURE) | ||||
|    { | ||||
|       // Save the specific failure status | ||||
|       *pContext = *(DWORD*) pStatusInformation; | ||||
|    } | ||||
|  | ||||
|    DbgTrace(1, "-SecureFailureStatusCallback- End\n", 0); | ||||
| } | ||||
|  | ||||
|  | ||||
| //++======================================================================= | ||||
| static | ||||
| CasaStatus | ||||
| InternalRpc( | ||||
|    IN    RpcSession *pSession, | ||||
|    IN    char *pMethod, | ||||
|    IN    bool secure, | ||||
|    IN    long flags, | ||||
|    IN    char *pRequestData, | ||||
|    INOUT char **ppResponseData, | ||||
|    INOUT int *pResponseDataLen) | ||||
| @@ -237,11 +356,16 @@ InternalRpc( | ||||
| // L2 | ||||
| //=======================================================================-- | ||||
| { | ||||
| #define CASA_STATUS_INVALID_SERVER_CERTIFICATE CASA_STATUS_UNSUCCESSFUL // temporary until casa_status.h is updated | ||||
|  | ||||
|    CasaStatus  retStatus = CASA_STATUS_SUCCESS; | ||||
|    char        rpcTarget[256]; | ||||
|    LPWSTR      pWideRpcTarget; | ||||
|    int         wideRpcTargetLen; | ||||
|    WCHAR       sendHeaders[] = L"Content-Type: text/html"; | ||||
|    DWORD       securityFailureStatusFlags; | ||||
|    int         retriesAllowed = 1; | ||||
|    bool        attemptRetry; | ||||
|  | ||||
|    DbgTrace(1, "-InternalRpc- Start\n", 0); | ||||
|  | ||||
| @@ -258,124 +382,172 @@ InternalRpc( | ||||
|    { | ||||
|       HINTERNET   hRequest; | ||||
|  | ||||
|       // Open a request handle | ||||
|       hRequest = WinHttpOpenRequest(pSession->hConnection, | ||||
|                                     L"POST", | ||||
|                                     pWideRpcTarget, | ||||
|                                     NULL, | ||||
|                                     WINHTTP_NO_REFERER, | ||||
|                                     WINHTTP_DEFAULT_ACCEPT_TYPES, | ||||
|                                     secure? WINHTTP_FLAG_REFRESH | WINHTTP_FLAG_SECURE : WINHTTP_FLAG_REFRESH); | ||||
|       if (hRequest) | ||||
|       do | ||||
|       { | ||||
|          int   reqDataLen = (int) strlen(pRequestData); | ||||
|          // Forget about having been told to retry | ||||
|          attemptRetry = false; | ||||
|  | ||||
|          // Send the request | ||||
|          if (WinHttpSendRequest(hRequest, | ||||
|                                 sendHeaders, | ||||
|                                 -1, | ||||
|                                 pRequestData, | ||||
|                                 reqDataLen, | ||||
|                                 reqDataLen, | ||||
|                                 0)) | ||||
|          { | ||||
|             // Request sent, now await for the response. | ||||
|             if (WinHttpReceiveResponse(hRequest, NULL)) | ||||
|             { | ||||
|                WCHAR httpCompStatus[4] = {0}; | ||||
|                DWORD httpCompStatusLen = sizeof(httpCompStatus); | ||||
|  | ||||
|                // Response received, make sure that it completed successfully. | ||||
|                if (WinHttpQueryHeaders(hRequest, | ||||
|                                        WINHTTP_QUERY_STATUS_CODE, | ||||
|          // Open a request handle | ||||
|          hRequest = WinHttpOpenRequest(pSession->hConnection, | ||||
|                                        L"POST", | ||||
|                                        pWideRpcTarget, | ||||
|                                        NULL, | ||||
|                                        &httpCompStatus, | ||||
|                                        &httpCompStatusLen, | ||||
|                                        WINHTTP_NO_HEADER_INDEX)) | ||||
|                                        WINHTTP_NO_REFERER, | ||||
|                                        WINHTTP_DEFAULT_ACCEPT_TYPES, | ||||
|                                        flags & SECURE_RPC_FLAG? WINHTTP_FLAG_REFRESH | WINHTTP_FLAG_SECURE : WINHTTP_FLAG_REFRESH); | ||||
|          if (hRequest) | ||||
|          { | ||||
|             int   reqDataLen = (int) strlen(pRequestData); | ||||
|  | ||||
|             // Check if we need to set options to deal with secure connections | ||||
|             if (flags & SECURE_RPC_FLAG) | ||||
|             { | ||||
|                // We are using secure connections, now proceed based on whether or not | ||||
|                // we are configured to allow invalid certificates. | ||||
|                if (flags & ALLOW_INVALID_CERTS_RPC_FLAG | ||||
|                    || (flags & ALLOW_INVALID_CERTS_USER_APPROVAL_RPC_FLAG | ||||
|                        && InvalidCertsFromHostAllowed(pSession->pHostName))) | ||||
|                { | ||||
|                   // Check that the request completed successfully | ||||
|                   if (memcmp(httpCompStatus, L"200", sizeof(httpCompStatus)) == 0) | ||||
|                   DWORD secFlags = SECURITY_FLAG_IGNORE_CERT_CN_INVALID | SECURITY_FLAG_IGNORE_UNKNOWN_CA; | ||||
|  | ||||
|                   // We are configured to allow invalid certificates, inform the HTTP stack. | ||||
|                   if (WinHttpSetOption(hRequest, | ||||
|                                        WINHTTP_OPTION_SECURITY_FLAGS, | ||||
|                                        &secFlags, | ||||
|                                        sizeof(secFlags)) == FALSE) | ||||
|                   { | ||||
|                      char  *pResponseData; | ||||
|                      int   responseDataBufSize = INITIAL_RESPONSE_DATA_BUF_SIZE;       | ||||
|                      int   responseDataRead = 0; | ||||
|                      DbgTrace(0, "-InternalRpc- Failed setting options to ignore invalid certs, error = %d\n", GetLastError()); | ||||
|                   } | ||||
|                } | ||||
|                else | ||||
|                { | ||||
|                   // We are not configured to allow invalid certificates, set a callback handler | ||||
|                   // to detect invalid certificate conditions. | ||||
|                   if (WinHttpSetStatusCallback(hRequest, | ||||
|                                                SecureFailureStatusCallback, | ||||
|                                                WINHTTP_CALLBACK_FLAG_SECURE_FAILURE, | ||||
|                                                (DWORD_PTR) NULL) == WINHTTP_INVALID_STATUS_CALLBACK) | ||||
|                   { | ||||
|                      DbgTrace(0, "-InternalRpc- Failed setting status callback, error = %d\n", GetLastError()); | ||||
|                   } | ||||
|                } | ||||
|             } | ||||
|  | ||||
|                      // Now read the response data, to do so we need to allocate a buffer. | ||||
|                      pResponseData = (char*) malloc(INITIAL_RESPONSE_DATA_BUF_SIZE); | ||||
|                      if (pResponseData) | ||||
|             // Send the request | ||||
|             securityFailureStatusFlags = 0; | ||||
|             if (WinHttpSendRequest(hRequest, | ||||
|                                    sendHeaders, | ||||
|                                    -1, | ||||
|                                    pRequestData, | ||||
|                                    reqDataLen, | ||||
|                                    reqDataLen, | ||||
|                                    (DWORD_PTR) &securityFailureStatusFlags)) | ||||
|             { | ||||
|                // Request sent, now await for the response. | ||||
|                if (WinHttpReceiveResponse(hRequest, NULL)) | ||||
|                { | ||||
|                   WCHAR httpCompStatus[4] = {0}; | ||||
|                   DWORD httpCompStatusLen = sizeof(httpCompStatus); | ||||
|  | ||||
|                   // Response received, make sure that it completed successfully. | ||||
|                   if (WinHttpQueryHeaders(hRequest, | ||||
|                                           WINHTTP_QUERY_STATUS_CODE, | ||||
|                                           NULL, | ||||
|                                           &httpCompStatus, | ||||
|                                           &httpCompStatusLen, | ||||
|                                           WINHTTP_NO_HEADER_INDEX)) | ||||
|                   { | ||||
|                      // Check that the request completed successfully | ||||
|                      if (memcmp(httpCompStatus, L"200", sizeof(httpCompStatus)) == 0) | ||||
|                      { | ||||
|                         char     *pCurrLocation = pResponseData; | ||||
|                         DWORD    bytesRead; | ||||
|                         char  *pResponseData; | ||||
|                         int   responseDataBufSize = INITIAL_RESPONSE_DATA_BUF_SIZE;       | ||||
|                         int   responseDataRead = 0; | ||||
|  | ||||
|                         do | ||||
|                         // Now read the response data, to do so we need to allocate a buffer. | ||||
|                         pResponseData = (char*) malloc(INITIAL_RESPONSE_DATA_BUF_SIZE); | ||||
|                         if (pResponseData) | ||||
|                         { | ||||
|                            bytesRead = 0; | ||||
|                            if (WinHttpReadData(hRequest, | ||||
|                                                (LPVOID) pCurrLocation, | ||||
|                                                responseDataBufSize - responseDataRead, | ||||
|                                                &bytesRead)) | ||||
|                            char     *pCurrLocation = pResponseData; | ||||
|                            DWORD    bytesRead; | ||||
|  | ||||
|                            do | ||||
|                            { | ||||
|                               pCurrLocation += bytesRead; | ||||
|                               responseDataRead += bytesRead; | ||||
|  | ||||
|                               // Check if we need to allocate a larger buffer | ||||
|                               if (responseDataRead == responseDataBufSize) | ||||
|                               bytesRead = 0; | ||||
|                               if (WinHttpReadData(hRequest, | ||||
|                                                   (LPVOID) pCurrLocation, | ||||
|                                                   responseDataBufSize - responseDataRead, | ||||
|                                                   &bytesRead)) | ||||
|                               { | ||||
|                                  char  *pTmpBuf; | ||||
|                                  pCurrLocation += bytesRead; | ||||
|                                  responseDataRead += bytesRead; | ||||
|  | ||||
|                                  // We need to upgrade the receive buffer | ||||
|                                  pTmpBuf = (char*) malloc(responseDataBufSize + INCREMENT_RESPONSE_DATA_BUF_SIZE); | ||||
|                                  if (pTmpBuf) | ||||
|                                  // Check if we need to allocate a larger buffer | ||||
|                                  if (responseDataRead == responseDataBufSize) | ||||
|                                  { | ||||
|                                     memcpy(pTmpBuf, pResponseData, responseDataBufSize); | ||||
|                                     free(pResponseData); | ||||
|                                     pResponseData = pTmpBuf; | ||||
|                                     pCurrLocation = pResponseData + responseDataBufSize; | ||||
|                                     responseDataBufSize += INCREMENT_RESPONSE_DATA_BUF_SIZE; | ||||
|                                  } | ||||
|                                  else | ||||
|                                  { | ||||
|                                     DbgTrace(0, "-InternalRpc- Buffer allocation failure\n", 0); | ||||
|                                     retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, | ||||
|                                                                 CASA_FACILITY_AUTHTOKEN, | ||||
|                                                                 CASA_STATUS_INSUFFICIENT_RESOURCES); | ||||
|                                     char  *pTmpBuf; | ||||
|  | ||||
|                                     // We need to upgrade the receive buffer | ||||
|                                     pTmpBuf = (char*) malloc(responseDataBufSize + INCREMENT_RESPONSE_DATA_BUF_SIZE); | ||||
|                                     if (pTmpBuf) | ||||
|                                     { | ||||
|                                        memcpy(pTmpBuf, pResponseData, responseDataBufSize); | ||||
|                                        free(pResponseData); | ||||
|                                        pResponseData = pTmpBuf; | ||||
|                                        pCurrLocation = pResponseData + responseDataBufSize; | ||||
|                                        responseDataBufSize += INCREMENT_RESPONSE_DATA_BUF_SIZE; | ||||
|                                     } | ||||
|                                     else | ||||
|                                     { | ||||
|                                        DbgTrace(0, "-InternalRpc- Buffer allocation failure\n", 0); | ||||
|                                        retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, | ||||
|                                                                    CASA_FACILITY_AUTHTOKEN, | ||||
|                                                                    CASA_STATUS_INSUFFICIENT_RESOURCES); | ||||
|                                     } | ||||
|                                  } | ||||
|                               } | ||||
|                               else | ||||
|                               { | ||||
|                                  DbgTrace(0, "-InternalRpc- Failed reading response data, error = %d\n", GetLastError()); | ||||
|                                  retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, | ||||
|                                                              CASA_FACILITY_AUTHTOKEN, | ||||
|                                                              CASA_STATUS_UNSUCCESSFUL); | ||||
|                               } | ||||
|                            } while (CASA_SUCCESS(retStatus) | ||||
|                                     && bytesRead != 0); | ||||
|  | ||||
|                            // Check if the response data was successfully received | ||||
|                            if (CASA_SUCCESS(retStatus)) | ||||
|                            { | ||||
|                               // The response data was received, return it to the caller. | ||||
|                               *ppResponseData = pResponseData; | ||||
|                               *pResponseDataLen = responseDataRead;  | ||||
|                            } | ||||
|                            else | ||||
|                            { | ||||
|                               DbgTrace(0, "-InternalRpc- Failed reading response data, error = %d\n", GetLastError()); | ||||
|                               retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, | ||||
|                                                           CASA_FACILITY_AUTHTOKEN, | ||||
|                                                           CASA_STATUS_UNSUCCESSFUL); | ||||
|                               // Failed to receive the response data, free the allocated buffer. | ||||
|                               free(pResponseData); | ||||
|                            } | ||||
|                         } while (CASA_SUCCESS(retStatus) | ||||
|                                  && bytesRead != 0); | ||||
|  | ||||
|                         // Check if the response data was successfully received | ||||
|                         if (CASA_SUCCESS(retStatus)) | ||||
|                         { | ||||
|                            // The response data was received, return it to the caller. | ||||
|                            *ppResponseData = pResponseData; | ||||
|                            *pResponseDataLen = responseDataRead;  | ||||
|                         } | ||||
|                         else | ||||
|                         { | ||||
|                            // Failed to receive the response data, free the allocated buffer. | ||||
|                            free(pResponseData); | ||||
|                            DbgTrace(0, "-InternalRpc- Buffer allocation failure\n", 0); | ||||
|                            retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, | ||||
|                                                        CASA_FACILITY_AUTHTOKEN, | ||||
|                                                        CASA_STATUS_INSUFFICIENT_RESOURCES); | ||||
|                         } | ||||
|                      } | ||||
|                      else | ||||
|                      { | ||||
|                         DbgTrace(0, "-InternalRpc- Buffer allocation failure\n", 0); | ||||
|                         DbgTrace(0, "-InternalRpc- HTTP request did not complete successfully, status = %S\n", httpCompStatus); | ||||
|                         retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, | ||||
|                                                     CASA_FACILITY_AUTHTOKEN, | ||||
|                                                     CASA_STATUS_INSUFFICIENT_RESOURCES); | ||||
|                                                     CASA_STATUS_UNSUCCESSFUL); | ||||
|                      } | ||||
|                   } | ||||
|                   else | ||||
|                   { | ||||
|                      DbgTrace(0, "-InternalRpc- HTTP request did not complete successfully, status = %S\n", httpCompStatus); | ||||
|                      DbgTrace(0, "-InternalRpc- Unable to obtain http request completion status, error = %d\n", GetLastError()); | ||||
|                      retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, | ||||
|                                                  CASA_FACILITY_AUTHTOKEN, | ||||
|                                                  CASA_STATUS_UNSUCCESSFUL); | ||||
| @@ -383,7 +555,7 @@ InternalRpc( | ||||
|                } | ||||
|                else | ||||
|                { | ||||
|                   DbgTrace(0, "-InternalRpc- Unable to obtain http request completion status, error = %d\n", GetLastError()); | ||||
|                   DbgTrace(0, "-InternalRpc- Unable to receive response, error = %d\n", GetLastError()); | ||||
|                   retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, | ||||
|                                               CASA_FACILITY_AUTHTOKEN, | ||||
|                                               CASA_STATUS_UNSUCCESSFUL); | ||||
| @@ -391,41 +563,141 @@ InternalRpc( | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                DbgTrace(0, "-InternalRpc- Unable to receive response, error = %d\n", GetLastError()); | ||||
|                retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, | ||||
|                                            CASA_FACILITY_AUTHTOKEN, | ||||
|                                            CASA_STATUS_UNSUCCESSFUL); | ||||
|                int   error = GetLastError(); | ||||
|  | ||||
|                if (error == ERROR_WINHTTP_CANNOT_CONNECT) | ||||
|                { | ||||
|                   DbgTrace(0, "-InternalRpc- Unable to connect to server\n", 0); | ||||
|                   retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, | ||||
|                                               CASA_FACILITY_AUTHTOKEN, | ||||
|                                               CASA_STATUS_AUTH_SERVER_UNAVAILABLE); | ||||
|                } | ||||
|                else if (error == ERROR_WINHTTP_SECURE_FAILURE) | ||||
|                { | ||||
|                   DbgTrace(1, "-InternalRpc- Secure connection failure, flags = %0x\n", securityFailureStatusFlags); | ||||
|  | ||||
|                   // Try to deal with the issue | ||||
|                   if ((securityFailureStatusFlags & ~(WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CA | ||||
|                                                       | WINHTTP_CALLBACK_STATUS_FLAG_CERT_CN_INVALID | ||||
|                                                       | WINHTTP_CALLBACK_STATUS_FLAG_CERT_DATE_INVALID)) == 0 | ||||
|                       && flags & ALLOW_INVALID_CERTS_USER_APPROVAL_RPC_FLAG) | ||||
|                   { | ||||
|                      WINHTTP_CERTIFICATE_INFO certInfo; | ||||
|                      DWORD certInfoLen = sizeof(certInfo); | ||||
|  | ||||
|                      // The failure was due to an invalid CN, CA, or both. | ||||
|                      // | ||||
|                      // Obtain information about the server certificate to give user | ||||
|                      // the choice of accepting it. | ||||
|                      if (WinHttpQueryOption(hRequest, | ||||
|                                             WINHTTP_OPTION_SECURITY_CERTIFICATE_STRUCT, | ||||
|                                             &certInfo, | ||||
|                                             &certInfoLen) | ||||
|                          && certInfo.lpszSubjectInfo != NULL | ||||
|                          && certInfo.lpszIssuerInfo != NULL) | ||||
|                      { | ||||
|                         char  *pSubjectInfo; | ||||
|                         int   subjectInfoLen; | ||||
|  | ||||
|                         // Convert the subjectInfo to multi-byte | ||||
|                         retStatus = CopyWideToMultiAlloc(certInfo.lpszSubjectInfo, | ||||
|                                                          (int) wcslen(certInfo.lpszSubjectInfo), | ||||
|                                                          &pSubjectInfo, | ||||
|                                                          &subjectInfoLen); | ||||
|                         if (CASA_SUCCESS(retStatus)) | ||||
|                         { | ||||
|                            char  *pIssuerInfo; | ||||
|                            int   issuerInfoLen; | ||||
|  | ||||
|                            // Convert the issuerInfo to multi-byte | ||||
|                            retStatus = CopyWideToMultiAlloc(certInfo.lpszIssuerInfo, | ||||
|                                                             (int) wcslen(certInfo.lpszIssuerInfo), | ||||
|                                                             &pIssuerInfo, | ||||
|                                                             &issuerInfoLen); | ||||
|                            if (CASA_SUCCESS(retStatus)) | ||||
|                            { | ||||
|                               long  invalidCertFlags = 0; | ||||
|  | ||||
|                               // Setup the invalid cert flags | ||||
|                               if (securityFailureStatusFlags & WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CA) | ||||
|                                  invalidCertFlags |= INVALID_CERT_CA_FLAG; | ||||
|  | ||||
|                               if (securityFailureStatusFlags & WINHTTP_CALLBACK_STATUS_FLAG_CERT_CN_INVALID) | ||||
|                                  invalidCertFlags |= INVALID_CERT_CN_FLAG; | ||||
|  | ||||
|                               if (securityFailureStatusFlags & WINHTTP_CALLBACK_STATUS_FLAG_CERT_DATE_INVALID) | ||||
|                                  invalidCertFlags |= INVALID_CERT_DATE_FLAG; | ||||
|  | ||||
|                               // Give user the choice to accept the certificate | ||||
|                               if (UserApprovedCert(pSession->pHostName, | ||||
|                                                    pSubjectInfo, | ||||
|                                                    pIssuerInfo, | ||||
|                                                    invalidCertFlags)) | ||||
|                               { | ||||
|                                  DbgTrace(1, "-InternalRpc- User approved invalid certificate from %s\n", pSession->pHostName); | ||||
|  | ||||
|                                  AllowInvalidCertsFromHost(pSession->pHostName); | ||||
|  | ||||
|                                  // Try to retry the request | ||||
|                                  attemptRetry = true; | ||||
|                               } | ||||
|                               else | ||||
|                               { | ||||
|                                  DbgTrace(1, "-InternalRpc- User did not approve invalid certificate from %s\n", pSession->pHostName); | ||||
|  | ||||
|                                  retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, | ||||
|                                                              CASA_FACILITY_AUTHTOKEN, | ||||
|                                                              CASA_STATUS_INVALID_SERVER_CERTIFICATE); | ||||
|                               } | ||||
|  | ||||
|                               // Free the buffer containing the issuerInfo | ||||
|                               free(pIssuerInfo); | ||||
|                            } | ||||
|  | ||||
|                            // Free the buffer containing the subjectInfo | ||||
|                            free(pSubjectInfo); | ||||
|                         } | ||||
|  | ||||
|                         // Free necessary certificate information | ||||
|                         if (certInfo.lpszSubjectInfo) LocalFree(certInfo.lpszSubjectInfo); | ||||
|                         if (certInfo.lpszIssuerInfo) LocalFree(certInfo.lpszIssuerInfo); | ||||
|                         if (certInfo.lpszProtocolName) LocalFree(certInfo.lpszProtocolName); | ||||
|                         if (certInfo.lpszSignatureAlgName) LocalFree(certInfo.lpszSignatureAlgName); | ||||
|                         if (certInfo.lpszEncryptionAlgName) LocalFree(certInfo.lpszEncryptionAlgName); | ||||
|                      } | ||||
|                      else | ||||
|                      { | ||||
|                         DbgTrace(0, "-InternalRpc- Unable to obtain server certificate struct, error = %0x\n", GetLastError()); | ||||
|                      } | ||||
|                   } | ||||
|                   else | ||||
|                   { | ||||
|                      // Decided to no give the user a choice to accept invalid server certificate | ||||
|                      retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, | ||||
|                                                  CASA_FACILITY_AUTHTOKEN, | ||||
|                                                  CASA_STATUS_INVALID_SERVER_CERTIFICATE); | ||||
|                   } | ||||
|                } | ||||
|                else | ||||
|                { | ||||
|                   DbgTrace(0, "-InternalRpc- Unsuccessful send http request, error = %d\n", error); | ||||
|                   retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, | ||||
|                                               CASA_FACILITY_AUTHTOKEN, | ||||
|                                               CASA_STATUS_UNSUCCESSFUL); | ||||
|                } | ||||
|             } | ||||
|  | ||||
|             // Close the request handle | ||||
|             WinHttpCloseHandle(hRequest); | ||||
|          } | ||||
|          else | ||||
|          { | ||||
|             int   error = GetLastError(); | ||||
|  | ||||
|             DbgTrace(0, "-InternalRpc- Unsuccessful send http request, error = %d\n", error); | ||||
|             if (error == ERROR_WINHTTP_CANNOT_CONNECT) | ||||
|             { | ||||
|                retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, | ||||
|                                            CASA_FACILITY_AUTHTOKEN, | ||||
|                                            CASA_STATUS_AUTH_SERVER_UNAVAILABLE); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, | ||||
|                                            CASA_FACILITY_AUTHTOKEN, | ||||
|                                            CASA_STATUS_UNSUCCESSFUL); | ||||
|             } | ||||
|             DbgTrace(0, "-InternalRpc- Unable to open http request, error = %d\n", GetLastError()); | ||||
|             retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, | ||||
|                                         CASA_FACILITY_AUTHTOKEN, | ||||
|                                         CASA_STATUS_UNSUCCESSFUL); | ||||
|          } | ||||
|  | ||||
|          // Close the request handle | ||||
|          WinHttpCloseHandle(hRequest); | ||||
|       } | ||||
|       else | ||||
|       { | ||||
|          DbgTrace(0, "-InternalRpc- Unable to open http request, error = %d\n", GetLastError()); | ||||
|          retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, | ||||
|                                      CASA_FACILITY_AUTHTOKEN, | ||||
|                                      CASA_STATUS_UNSUCCESSFUL); | ||||
|       } | ||||
|       } while (attemptRetry && retriesAllowed--); | ||||
|  | ||||
|       // Free the rpc target wide string buffer | ||||
|       free(pWideRpcTarget); | ||||
| @@ -446,7 +718,7 @@ CasaStatus | ||||
| Rpc( | ||||
|    IN    RpcSession *pSession, | ||||
|    IN    char *pMethod, | ||||
|    IN    bool secure, | ||||
|    IN    long flags, | ||||
|    IN    char *pRequestData, | ||||
|    INOUT char **ppResponseData, | ||||
|    INOUT int *pResponseDataLen) | ||||
| @@ -473,7 +745,7 @@ Rpc( | ||||
|       // Issue the RPC | ||||
|       retStatus = InternalRpc(pSession, | ||||
|                               pMethod, | ||||
|                               secure, | ||||
|                               flags, | ||||
|                               pRequestData, | ||||
|                               ppResponseData, | ||||
|                               pResponseDataLen); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user