Updates resulting from self-code review.
This commit is contained in:
		| @@ -128,7 +128,7 @@ BOOL APIENTRY DllMain( | ||||
| //=======================================================================-- | ||||
| { | ||||
|    BOOL  retStatus = TRUE; | ||||
|    char  programFilesFolder[MAX_PATH]; | ||||
|    char  programFilesFolder[MAX_PATH] = {0}; | ||||
|  | ||||
|    switch (ul_reason_for_call) | ||||
|    { | ||||
|   | ||||
| @@ -54,12 +54,12 @@ static | ||||
| HANDLE   hNormalizedHostNameCacheMutex; | ||||
|  | ||||
| // Client configuration file folder | ||||
| char  clientConfigFolder[MAX_PATH]; | ||||
| char  clientConfigFolderPartialPath[] = "Novell\\Casa\\Etc\\Auth"; | ||||
| char  clientConfigFolder[MAX_PATH + sizeof(clientConfigFolderPartialPath)]; | ||||
|  | ||||
| // Authentication mechanism configuration file folder | ||||
| char  mechConfigFolder[MAX_PATH]; | ||||
| char  mechConfigFolderPartialPath[] = "Novell\\Casa\\Etc\\Auth\\Mechanisms"; | ||||
| char  mechConfigFolder[MAX_PATH + sizeof(mechConfigFolderPartialPath)]; | ||||
|  | ||||
| // Path separator | ||||
| char  pathCharString[] = "\\"; | ||||
| @@ -81,6 +81,8 @@ CreateUserMutex( | ||||
| // L2 | ||||
| //=======================================================================-- | ||||
| { | ||||
| #define USER_MUTEX_NAME_FMT_STRING "Global\\CASA_Auth_Mutex_%s" | ||||
|  | ||||
|    CasaStatus  retStatus = CASA_STATUS_SUCCESS; | ||||
|    char        *pUsername = NULL; | ||||
|    DWORD       nameLength = 0; | ||||
| @@ -99,32 +101,47 @@ CreateUserMutex( | ||||
|          if (GetUserName(pUsername, &nameLength)) | ||||
|          { | ||||
|             SECURITY_ATTRIBUTES  mutexAttributes; | ||||
|             char                 mutexName[256]; | ||||
|             char                 *pMutexName; | ||||
|  | ||||
|             // Now lets create a global semaphore for the | ||||
|             // user and allow its handle to be inherited. | ||||
|             mutexAttributes.nLength = sizeof(mutexAttributes); | ||||
|             mutexAttributes.lpSecurityDescriptor = NULL; | ||||
|             mutexAttributes.bInheritHandle = TRUE; | ||||
|             if (sprintf(mutexName, "Global\\CASA_Auth_Mutex_%s", pUsername) != -1) | ||||
|             // Allocate a buffer to hold the mutex name | ||||
|             pMutexName = (char*) malloc(sizeof(USER_MUTEX_NAME_FMT_STRING) + nameLength); | ||||
|             if (pMutexName) | ||||
|             { | ||||
|                *phMutex = CreateMutex(&mutexAttributes, | ||||
|                                       FALSE, | ||||
|                                       mutexName); | ||||
|                if (*phMutex == NULL) | ||||
|                // Now lets create a global semaphore for the | ||||
|                // user and allow its handle to be inherited. | ||||
|                mutexAttributes.nLength = sizeof(mutexAttributes); | ||||
|                mutexAttributes.lpSecurityDescriptor = NULL; | ||||
|                mutexAttributes.bInheritHandle = TRUE; | ||||
|                if (sprintf(pMutexName, USER_MUTEX_NAME_FMT_STRING, pUsername) != -1) | ||||
|                { | ||||
|                   DbgTrace(0, "-CreateUserMutex- CreateMutex failed, error = %d\n", GetLastError()); | ||||
|                   *phMutex = CreateMutex(&mutexAttributes, | ||||
|                                          FALSE, | ||||
|                                          pMutexName); | ||||
|                   if (*phMutex == NULL) | ||||
|                   { | ||||
|                      DbgTrace(0, "-CreateUserMutex- CreateMutex failed, error = %d\n", GetLastError()); | ||||
|                      retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, | ||||
|                                                  CASA_FACILITY_AUTHTOKEN, | ||||
|                                                  CASA_STATUS_UNSUCCESSFUL); | ||||
|                   } | ||||
|                } | ||||
|                else | ||||
|                { | ||||
|                   DbgTrace(0, "-CreateUserMutex- sprintf failed, error = %d\n", GetLastError()); | ||||
|                   retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, | ||||
|                                               CASA_FACILITY_AUTHTOKEN, | ||||
|                                               CASA_STATUS_UNSUCCESSFUL); | ||||
|                } | ||||
|  | ||||
|                // Free the buffer used to hold the user mutex name | ||||
|                free(pMutexName); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                DbgTrace(0, "-CreateUserMutex- sprintf failed, error = %d\n", GetLastError()); | ||||
|                DbgTrace(0, "-CreateUserMutex- Buffer allocation failure\n", 0); | ||||
|                retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, | ||||
|                                            CASA_FACILITY_AUTHTOKEN, | ||||
|                                            CASA_STATUS_UNSUCCESSFUL); | ||||
|                                            CASA_STATUS_INSUFFICIENT_RESOURCES); | ||||
|             } | ||||
|          } | ||||
|          else | ||||
| @@ -415,53 +432,65 @@ NormalizeHostName( | ||||
|  | ||||
|             // Now try to resolve the normalized name | ||||
|             pLookupResult = gethostbyname(pHostName); | ||||
|             if (pLookupResult && pLookupResult->h_addrtype == AF_INET) | ||||
|             if (pLookupResult | ||||
|                 && pLookupResult->h_addrtype == AF_INET | ||||
|                 && pLookupResult->h_length > 0 | ||||
|                 && pLookupResult->h_addr_list[0] != NULL) | ||||
|             { | ||||
|                char  dnsHostName[NI_MAXHOST]; | ||||
|  | ||||
|                // Set up a sockaddr structure | ||||
|                sockAddr.sin_family = AF_INET; | ||||
|                sockAddr.sin_addr.S_un.S_addr = *((int*) pLookupResult->h_addr_list[0]); | ||||
|  | ||||
|                // Now try to resolve the name using DNS | ||||
|                if (getnameinfo((const struct sockaddr*) &sockAddr, | ||||
|                                sizeof(sockAddr), | ||||
|                                dnsHostName, | ||||
|                                sizeof(dnsHostName), | ||||
|                                NULL, | ||||
|                                0, | ||||
|                                NI_NAMEREQD) == 0) | ||||
|                char *pDnsHostName = (char*) malloc(NI_MAXHOST + 1); | ||||
|                if (pDnsHostName) | ||||
|                { | ||||
|                   // We resolved the address to a DNS name, use it as the normalized name. | ||||
|                   pEntry->buffLengthRequired = (int) strlen(dnsHostName) + 1; | ||||
|                   pEntry->pNormalizedHostName = (char*) malloc(pEntry->buffLengthRequired); | ||||
|                   if (pEntry->pNormalizedHostName) | ||||
|                   // Set up a sockaddr structure | ||||
|                   sockAddr.sin_family = AF_INET; | ||||
|                   sockAddr.sin_addr.S_un.S_addr = *((int*) pLookupResult->h_addr_list[0]); | ||||
|  | ||||
|                   // Now try to resolve the name using DNS | ||||
|                   if (getnameinfo((const struct sockaddr*) &sockAddr, | ||||
|                                   sizeof(sockAddr), | ||||
|                                   pDnsHostName, | ||||
|                                   NI_MAXHOST, | ||||
|                                   NULL, | ||||
|                                   0, | ||||
|                                   NI_NAMEREQD) == 0) | ||||
|                   { | ||||
|                      // Copy the dns name | ||||
|                      strcpy(pEntry->pNormalizedHostName, dnsHostName); | ||||
|                      // We resolved the address to a DNS name, use it as the normalized name. | ||||
|                      pEntry->buffLengthRequired = (int) strlen(pDnsHostName) + 1; | ||||
|                      pEntry->pNormalizedHostName = (char*) malloc(pEntry->buffLengthRequired); | ||||
|                      if (pEntry->pNormalizedHostName) | ||||
|                      { | ||||
|                         // Copy the dns name | ||||
|                         strcpy(pEntry->pNormalizedHostName, pDnsHostName); | ||||
|                      } | ||||
|                      else | ||||
|                      { | ||||
|                         DbgTrace(0, "-NormalizeHostName- Buffer allocation error\n", 0); | ||||
|                      } | ||||
|                   } | ||||
|                   else | ||||
|                   { | ||||
|                      DbgTrace(0, "-NormalizeHostName- Buffer allocation error\n", 0); | ||||
|                      DbgTrace(0, "-NormalizeHostName- getnameInfo failed, error %d\n", WSAGetLastError()); | ||||
|  | ||||
|                      // Not able to resolve the name in DNS, just use the host name as | ||||
|                      // the normalized name. | ||||
|                      pEntry->buffLengthRequired = (int) strlen(pHostName) + 1; | ||||
|                      pEntry->pNormalizedHostName = (char*) malloc(pEntry->buffLengthRequired); | ||||
|                      if (pEntry->pNormalizedHostName) | ||||
|                      { | ||||
|                         // Copy the host name | ||||
|                         strcpy(pEntry->pNormalizedHostName, pHostName); | ||||
|                      } | ||||
|                      else | ||||
|                      { | ||||
|                         DbgTrace(0, "-NormalizeHostName- Buffer allocation error\n", 0); | ||||
|                      } | ||||
|                   } | ||||
|  | ||||
|                   // Free the buffer allocated to hold the DNS name | ||||
|                   free(pDnsHostName); | ||||
|                } | ||||
|                else | ||||
|                { | ||||
|                   DbgTrace(0, "-NormalizeHostName- getnameInfo failed, error %d\n", WSAGetLastError()); | ||||
|  | ||||
|                   // Not able to resolve the name in DNS, just use the host name as | ||||
|                   // the normalized name. | ||||
|                   pEntry->buffLengthRequired = (int) strlen(pHostName) + 1; | ||||
|                   pEntry->pNormalizedHostName = (char*) malloc(pEntry->buffLengthRequired); | ||||
|                   if (pEntry->pNormalizedHostName) | ||||
|                   { | ||||
|                      // Copy the host name | ||||
|                      strcpy(pEntry->pNormalizedHostName, pHostName); | ||||
|                   } | ||||
|                   else | ||||
|                   { | ||||
|                      DbgTrace(0, "-NormalizeHostName- Buffer allocation error\n", 0); | ||||
|                   } | ||||
|                   DbgTrace(0, "-NormalizeHostName- Buffer allocation failure\n", 0); | ||||
|                } | ||||
|             } | ||||
|             else | ||||
|   | ||||
| @@ -356,10 +356,14 @@ InternalRpc( | ||||
| // L2 | ||||
| //=======================================================================-- | ||||
| { | ||||
| #define RPC_TARGET_FMT_STRING "CasaAuthTokenSvc/Rpc?method=%s" | ||||
|  | ||||
| #ifndef CASA_STATUS_INVALID_SERVER_CERTIFICATE | ||||
| #define CASA_STATUS_INVALID_SERVER_CERTIFICATE CASA_STATUS_UNSUCCESSFUL // temporary until casa_status.h is updated | ||||
| #endif | ||||
|  | ||||
|    CasaStatus  retStatus = CASA_STATUS_SUCCESS; | ||||
|    char        rpcTarget[256]; | ||||
|    char        *pRpcTarget; | ||||
|    LPWSTR      pWideRpcTarget; | ||||
|    int         wideRpcTargetLen; | ||||
|    WCHAR       sendHeaders[] = L"Content-Type: text/html"; | ||||
| @@ -373,173 +377,184 @@ InternalRpc( | ||||
|    *ppResponseData = NULL; | ||||
|  | ||||
|    // Create rpc target string and convert it to a wide string | ||||
|    sprintf(rpcTarget, "CasaAuthTokenSvc/Rpc?method=%s", pMethod); | ||||
|    retStatus = CopyMultiToWideAlloc(rpcTarget, | ||||
|                                     (int) strlen(rpcTarget), | ||||
|                                     &pWideRpcTarget, | ||||
|                                     &wideRpcTargetLen); | ||||
|    if (CASA_SUCCESS(retStatus)) | ||||
|    pRpcTarget = (char*) malloc(sizeof(RPC_TARGET_FMT_STRING) + strlen(pMethod)); | ||||
|    if (pRpcTarget) | ||||
|    { | ||||
|       HINTERNET   hRequest; | ||||
|  | ||||
|       do | ||||
|       sprintf(pRpcTarget, RPC_TARGET_FMT_STRING, pMethod); | ||||
|       retStatus = CopyMultiToWideAlloc(pRpcTarget, | ||||
|                                        (int) strlen(pRpcTarget), | ||||
|                                        &pWideRpcTarget, | ||||
|                                        &wideRpcTargetLen); | ||||
|       if (CASA_SUCCESS(retStatus)) | ||||
|       { | ||||
|          // Forget about having been told to retry | ||||
|          attemptRetry = false; | ||||
|          HINTERNET   hRequest; | ||||
|  | ||||
|          // Open a request handle | ||||
|          hRequest = WinHttpOpenRequest(pSession->hConnection, | ||||
|                                        L"POST", | ||||
|                                        pWideRpcTarget, | ||||
|                                        NULL, | ||||
|                                        WINHTTP_NO_REFERER, | ||||
|                                        WINHTTP_DEFAULT_ACCEPT_TYPES, | ||||
|                                        flags & SECURE_RPC_FLAG? 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; | ||||
|  | ||||
|             // 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))) | ||||
|                { | ||||
|                   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) | ||||
|                   { | ||||
|                      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()); | ||||
|                   } | ||||
|                } | ||||
|             } | ||||
|  | ||||
|             // 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, | ||||
|             // 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); | ||||
| @@ -547,7 +562,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); | ||||
| @@ -555,160 +570,163 @@ InternalRpc( | ||||
|                } | ||||
|                else | ||||
|                { | ||||
|                   DbgTrace(0, "-InternalRpc- Unable to receive response, error = %d\n", GetLastError()); | ||||
|                   retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, | ||||
|                                               CASA_FACILITY_AUTHTOKEN, | ||||
|                                               CASA_STATUS_UNSUCCESSFUL); | ||||
|                } | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                int   error = GetLastError(); | ||||
|                   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) | ||||
|                   if (error == ERROR_WINHTTP_CANNOT_CONNECT) | ||||
|                   { | ||||
|                      WINHTTP_CERTIFICATE_INFO certInfo; | ||||
|                      DWORD certInfoLen = sizeof(certInfo); | ||||
|                      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); | ||||
|  | ||||
|                      // 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) | ||||
|                      // 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) | ||||
|                      { | ||||
|                         char  *pSubjectInfo; | ||||
|                         int   subjectInfoLen; | ||||
|                         WINHTTP_CERTIFICATE_INFO certInfo; | ||||
|                         DWORD certInfoLen = sizeof(certInfo); | ||||
|  | ||||
|                         // Convert the subjectInfo to multi-byte | ||||
|                         retStatus = CopyWideToMultiAlloc(certInfo.lpszSubjectInfo, | ||||
|                                                          (int) wcslen(certInfo.lpszSubjectInfo), | ||||
|                                                          &pSubjectInfo, | ||||
|                                                          &subjectInfoLen); | ||||
|                         if (CASA_SUCCESS(retStatus)) | ||||
|                         // 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  *pIssuerInfo; | ||||
|                            int   issuerInfoLen; | ||||
|                            char  *pSubjectInfo; | ||||
|                            int   subjectInfoLen; | ||||
|  | ||||
|                            // Convert the issuerInfo to multi-byte | ||||
|                            retStatus = CopyWideToMultiAlloc(certInfo.lpszIssuerInfo, | ||||
|                                                             (int) wcslen(certInfo.lpszIssuerInfo), | ||||
|                                                             &pIssuerInfo, | ||||
|                                                             &issuerInfoLen); | ||||
|                            // Convert the subjectInfo to multi-byte | ||||
|                            retStatus = CopyWideToMultiAlloc(certInfo.lpszSubjectInfo, | ||||
|                                                             (int) wcslen(certInfo.lpszSubjectInfo), | ||||
|                                                             &pSubjectInfo, | ||||
|                                                             &subjectInfoLen); | ||||
|                            if (CASA_SUCCESS(retStatus)) | ||||
|                            { | ||||
|                               long  invalidCertFlags = 0; | ||||
|                               char  *pIssuerInfo; | ||||
|                               int   issuerInfoLen; | ||||
|  | ||||
|                               // 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)) | ||||
|                               // Convert the issuerInfo to multi-byte | ||||
|                               retStatus = CopyWideToMultiAlloc(certInfo.lpszIssuerInfo, | ||||
|                                                                (int) wcslen(certInfo.lpszIssuerInfo), | ||||
|                                                                &pIssuerInfo, | ||||
|                                                                &issuerInfoLen); | ||||
|                               if (CASA_SUCCESS(retStatus)) | ||||
|                               { | ||||
|                                  DbgTrace(1, "-InternalRpc- User approved invalid certificate from %s\n", pSession->pHostName); | ||||
|                                  long  invalidCertFlags = 0; | ||||
|  | ||||
|                                  // tbd - Investigate if there is a way to set the accepted certificate in a store so that | ||||
|                                  // it can be utilized by the SSL stack directly. This would be a better method for dealing with | ||||
|                                  // this issue. | ||||
|                                  // Setup the invalid cert flags | ||||
|                                  if (securityFailureStatusFlags & WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CA) | ||||
|                                     invalidCertFlags |= INVALID_CERT_CA_FLAG; | ||||
|  | ||||
|                                  AllowInvalidCertsFromHost(pSession->pHostName); | ||||
|                                  if (securityFailureStatusFlags & WINHTTP_CALLBACK_STATUS_FLAG_CERT_CN_INVALID) | ||||
|                                     invalidCertFlags |= INVALID_CERT_CN_FLAG; | ||||
|  | ||||
|                                  // Try to retry the request | ||||
|                                  attemptRetry = true; | ||||
|                               } | ||||
|                               else | ||||
|                               { | ||||
|                                  DbgTrace(1, "-InternalRpc- User did not approve invalid certificate from %s\n", pSession->pHostName); | ||||
|                                  if (securityFailureStatusFlags & WINHTTP_CALLBACK_STATUS_FLAG_CERT_DATE_INVALID) | ||||
|                                     invalidCertFlags |= INVALID_CERT_DATE_FLAG; | ||||
|  | ||||
|                                  retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, | ||||
|                                                              CASA_FACILITY_AUTHTOKEN, | ||||
|                                                              CASA_STATUS_INVALID_SERVER_CERTIFICATE); | ||||
|                                  // 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); | ||||
|  | ||||
|                                     // tbd - Investigate if there is a way to set the accepted certificate in a store so that | ||||
|                                     // it can be utilized by the SSL stack directly. This would be a better method for dealing with | ||||
|                                     // this issue. | ||||
|  | ||||
|                                     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 issuerInfo | ||||
|                               free(pIssuerInfo); | ||||
|                               // Free the buffer containing the subjectInfo | ||||
|                               free(pSubjectInfo); | ||||
|                            } | ||||
|  | ||||
|                            // 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()); | ||||
|                         } | ||||
|  | ||||
|                         // 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()); | ||||
|                         // 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 | ||||
|                   { | ||||
|                      // Decided to no give the user a choice to accept invalid server certificate | ||||
|                      DbgTrace(0, "-InternalRpc- Unsuccessful send http request, error = %d\n", error); | ||||
|                      retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, | ||||
|                                                  CASA_FACILITY_AUTHTOKEN, | ||||
|                                                  CASA_STATUS_INVALID_SERVER_CERTIFICATE); | ||||
|                                                  CASA_STATUS_UNSUCCESSFUL); | ||||
|                   } | ||||
|                } | ||||
|                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 | ||||
|             { | ||||
|                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--); | ||||
|  | ||||
|             // 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); | ||||
|       } | ||||
|       else | ||||
|       { | ||||
|          DbgTrace(0, "-InternalRpc- Error converting method name to wide string\n", 0); | ||||
|       } | ||||
|  | ||||
|       // Free the rpc target wide string buffer | ||||
|       free(pWideRpcTarget); | ||||
|       // Free buffer used to hold the rpc target string | ||||
|       free(pRpcTarget); | ||||
|    } | ||||
|    else | ||||
|    { | ||||
|       DbgTrace(0, "-InternalRpc- Error converting method name to wide string\n", 0); | ||||
|       DbgTrace(0, "-InternalRpc- Buffer allocation failure\n", 0); | ||||
|       retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, | ||||
|                                   CASA_FACILITY_AUTHTOKEN, | ||||
|                                   CASA_STATUS_INSUFFICIENT_RESOURCES); | ||||
|    } | ||||
|  | ||||
|    DbgTrace(1, "-InternalRpc- End, retStatus = %d\n", retStatus); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user