Updates resulting from self-code review.
This commit is contained in:
		| @@ -194,6 +194,9 @@ ObtainSessionToken( | |||||||
|             if (pRespMsg) |             if (pRespMsg) | ||||||
|                free(pRespMsg); |                free(pRespMsg); | ||||||
|  |  | ||||||
|  |             // Clear and free the memory associated with the request message since | ||||||
|  |             // it may contain sensitive information. | ||||||
|  |             memset(pReqMsg, 0, strlen(pReqMsg)); | ||||||
|             free(pReqMsg); |             free(pReqMsg); | ||||||
|          } |          } | ||||||
|          else |          else | ||||||
| @@ -223,6 +226,8 @@ ObtainSessionToken( | |||||||
|          } |          } | ||||||
|  |  | ||||||
|          // Free up the buffer associated with the authentication mechanism token |          // Free up the buffer associated with the authentication mechanism token | ||||||
|  |          // after clearing it since it may contain sensitive information. | ||||||
|  |          memset(pAuthMechToken, 0, strlen(pAuthMechToken)); | ||||||
|          free(pAuthMechToken); |          free(pAuthMechToken); | ||||||
|       } |       } | ||||||
|       else |       else | ||||||
|   | |||||||
| @@ -101,7 +101,6 @@ AuthTokenIf_GetAuthToken( | |||||||
|    TimeStamp         expiry; |    TimeStamp         expiry; | ||||||
|    CredHandle        hCredentials = {0}; |    CredHandle        hCredentials = {0}; | ||||||
|  |  | ||||||
|  |  | ||||||
|    DbgTrace(1, "-AuthTokenIf_GetAuthToken- Start\n", 0); |    DbgTrace(1, "-AuthTokenIf_GetAuthToken- Start\n", 0); | ||||||
|  |  | ||||||
|    // Validate input parameters |    // Validate input parameters | ||||||
| @@ -211,7 +210,9 @@ AuthTokenIf_GetAuthToken( | |||||||
|             // Return the actual size or the size required |             // Return the actual size or the size required | ||||||
|             *pTokenBufLen = encodedTokenLen; |             *pTokenBufLen = encodedTokenLen; | ||||||
|  |  | ||||||
|             // Free the buffer containing the encoded token |             // Free the buffer containing the encoded token after clearing | ||||||
|  |             // its memory to avoid leaking sensitive information. | ||||||
|  |             memset(pEncodedToken, 0, strlen(pEncodedToken)); | ||||||
|             free(pEncodedToken); |             free(pEncodedToken); | ||||||
|          } |          } | ||||||
|  |  | ||||||
| @@ -229,7 +230,10 @@ AuthTokenIf_GetAuthToken( | |||||||
|  |  | ||||||
|       // Free any buffer associated with the sendToken |       // Free any buffer associated with the sendToken | ||||||
|       if (sendTok.pvBuffer) |       if (sendTok.pvBuffer) | ||||||
|  |       { | ||||||
|  |          memset(sendTok.pvBuffer, 0, sendTok.cbBuffer); | ||||||
|          FreeContextBuffer(sendTok.pvBuffer); |          FreeContextBuffer(sendTok.pvBuffer); | ||||||
|  |       } | ||||||
|  |  | ||||||
|       // Free the credential handle obtained |       // Free the credential handle obtained | ||||||
|       FreeCredentialsHandle(&hCredentials); |       FreeCredentialsHandle(&hCredentials); | ||||||
|   | |||||||
| @@ -181,6 +181,10 @@ GetUserCredentials( | |||||||
|       DbgTrace(0, "-GetUserCredentials- Failed to obtain credentials for pw authentication\n", 0); |       DbgTrace(0, "-GetUserCredentials- Failed to obtain credentials for pw authentication\n", 0); | ||||||
|    } |    } | ||||||
|  |  | ||||||
|  |    // Clear out the credential structure to make sure that we are not leaving sensitive | ||||||
|  |    // information on the stack. | ||||||
|  |    memset(&credential, 0, sizeof(credential)); | ||||||
|  |  | ||||||
|    // Return the buffers to the caller if successful |    // Return the buffers to the caller if successful | ||||||
|    if (CASA_SUCCESS(retStatus)) |    if (CASA_SUCCESS(retStatus)) | ||||||
|    { |    { | ||||||
| @@ -324,11 +328,15 @@ AuthTokenIf_GetAuthToken( | |||||||
|             // Return the actual size or the size required |             // Return the actual size or the size required | ||||||
|             *pTokenBufLen = encodedTokenLen; |             *pTokenBufLen = encodedTokenLen; | ||||||
|  |  | ||||||
|             // Free the buffer containing the encoded token |             // Free the buffer containing the encoded token after clearing | ||||||
|  |             // it to avoid leaking sensitive information. | ||||||
|  |             memset(pEncodedToken, 0, strlen(pEncodedToken)); | ||||||
|             free(pEncodedToken); |             free(pEncodedToken); | ||||||
|          } |          } | ||||||
|  |  | ||||||
|          // Free the buffer allocated for the token |          // Free the buffer allocated for the token after clearing it | ||||||
|  |          // to avoid leaving sensitive information behind. | ||||||
|  |          memset(pToken, 0, strlen(pToken)); | ||||||
|          free(pToken); |          free(pToken); | ||||||
|       } |       } | ||||||
|       else |       else | ||||||
| @@ -339,8 +347,9 @@ AuthTokenIf_GetAuthToken( | |||||||
|                                      CASA_STATUS_INSUFFICIENT_RESOURCES); |                                      CASA_STATUS_INSUFFICIENT_RESOURCES); | ||||||
|       } |       } | ||||||
|  |  | ||||||
|       // Free allocated buffers |       // Free allocated buffers after clearing memory holding the password | ||||||
|       free(pUsername); |       free(pUsername); | ||||||
|  |       memset(pPassword, 0, strlen(pPassword)); | ||||||
|       free(pPassword); |       free(pPassword); | ||||||
|    } |    } | ||||||
|    else |    else | ||||||
|   | |||||||
| @@ -28,5 +28,5 @@ LibraryName		\Program Files\novell\casa\lib\pwmech.dll | |||||||
| #              tools such as DbgView. Under Linux, debug statements are logged | #              tools such as DbgView. Under Linux, debug statements are logged | ||||||
| #              to /var/log/messages. | #              to /var/log/messages. | ||||||
| # | # | ||||||
| #DebugLevel	0 | #DebugLevel 0 | ||||||
|  |  | ||||||
|   | |||||||
| @@ -128,7 +128,7 @@ BOOL APIENTRY DllMain( | |||||||
| //=======================================================================-- | //=======================================================================-- | ||||||
| { | { | ||||||
|    BOOL  retStatus = TRUE; |    BOOL  retStatus = TRUE; | ||||||
|    char  programFilesFolder[MAX_PATH]; |    char  programFilesFolder[MAX_PATH] = {0}; | ||||||
|  |  | ||||||
|    switch (ul_reason_for_call) |    switch (ul_reason_for_call) | ||||||
|    { |    { | ||||||
|   | |||||||
| @@ -54,12 +54,12 @@ static | |||||||
| HANDLE   hNormalizedHostNameCacheMutex; | HANDLE   hNormalizedHostNameCacheMutex; | ||||||
|  |  | ||||||
| // Client configuration file folder | // Client configuration file folder | ||||||
| char  clientConfigFolder[MAX_PATH]; |  | ||||||
| char  clientConfigFolderPartialPath[] = "Novell\\Casa\\Etc\\Auth"; | char  clientConfigFolderPartialPath[] = "Novell\\Casa\\Etc\\Auth"; | ||||||
|  | char  clientConfigFolder[MAX_PATH + sizeof(clientConfigFolderPartialPath)]; | ||||||
|  |  | ||||||
| // Authentication mechanism configuration file folder | // Authentication mechanism configuration file folder | ||||||
| char  mechConfigFolder[MAX_PATH]; |  | ||||||
| char  mechConfigFolderPartialPath[] = "Novell\\Casa\\Etc\\Auth\\Mechanisms"; | char  mechConfigFolderPartialPath[] = "Novell\\Casa\\Etc\\Auth\\Mechanisms"; | ||||||
|  | char  mechConfigFolder[MAX_PATH + sizeof(mechConfigFolderPartialPath)]; | ||||||
|  |  | ||||||
| // Path separator | // Path separator | ||||||
| char  pathCharString[] = "\\"; | char  pathCharString[] = "\\"; | ||||||
| @@ -81,6 +81,8 @@ CreateUserMutex( | |||||||
| // L2 | // L2 | ||||||
| //=======================================================================-- | //=======================================================================-- | ||||||
| { | { | ||||||
|  | #define USER_MUTEX_NAME_FMT_STRING "Global\\CASA_Auth_Mutex_%s" | ||||||
|  |  | ||||||
|    CasaStatus  retStatus = CASA_STATUS_SUCCESS; |    CasaStatus  retStatus = CASA_STATUS_SUCCESS; | ||||||
|    char        *pUsername = NULL; |    char        *pUsername = NULL; | ||||||
|    DWORD       nameLength = 0; |    DWORD       nameLength = 0; | ||||||
| @@ -99,32 +101,47 @@ CreateUserMutex( | |||||||
|          if (GetUserName(pUsername, &nameLength)) |          if (GetUserName(pUsername, &nameLength)) | ||||||
|          { |          { | ||||||
|             SECURITY_ATTRIBUTES  mutexAttributes; |             SECURITY_ATTRIBUTES  mutexAttributes; | ||||||
|             char                 mutexName[256]; |             char                 *pMutexName; | ||||||
|  |  | ||||||
|             // Now lets create a global semaphore for the |             // Allocate a buffer to hold the mutex name | ||||||
|             // user and allow its handle to be inherited. |             pMutexName = (char*) malloc(sizeof(USER_MUTEX_NAME_FMT_STRING) + nameLength); | ||||||
|             mutexAttributes.nLength = sizeof(mutexAttributes); |             if (pMutexName) | ||||||
|             mutexAttributes.lpSecurityDescriptor = NULL; |  | ||||||
|             mutexAttributes.bInheritHandle = TRUE; |  | ||||||
|             if (sprintf(mutexName, "Global\\CASA_Auth_Mutex_%s", pUsername) != -1) |  | ||||||
|             { |             { | ||||||
|                *phMutex = CreateMutex(&mutexAttributes, |                // Now lets create a global semaphore for the | ||||||
|                                       FALSE, |                // user and allow its handle to be inherited. | ||||||
|                                       mutexName); |                mutexAttributes.nLength = sizeof(mutexAttributes); | ||||||
|                if (*phMutex == NULL) |                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, |                   retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, | ||||||
|                                               CASA_FACILITY_AUTHTOKEN, |                                               CASA_FACILITY_AUTHTOKEN, | ||||||
|                                               CASA_STATUS_UNSUCCESSFUL); |                                               CASA_STATUS_UNSUCCESSFUL); | ||||||
|                } |                } | ||||||
|  |  | ||||||
|  |                // Free the buffer used to hold the user mutex name | ||||||
|  |                free(pMutexName); | ||||||
|             } |             } | ||||||
|             else |             else | ||||||
|             { |             { | ||||||
|                DbgTrace(0, "-CreateUserMutex- sprintf failed, error = %d\n", GetLastError()); |                DbgTrace(0, "-CreateUserMutex- Buffer allocation failure\n", 0); | ||||||
|                retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, |                retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, | ||||||
|                                            CASA_FACILITY_AUTHTOKEN, |                                            CASA_FACILITY_AUTHTOKEN, | ||||||
|                                            CASA_STATUS_UNSUCCESSFUL); |                                            CASA_STATUS_INSUFFICIENT_RESOURCES); | ||||||
|             } |             } | ||||||
|          } |          } | ||||||
|          else |          else | ||||||
| @@ -415,53 +432,65 @@ NormalizeHostName( | |||||||
|  |  | ||||||
|             // Now try to resolve the normalized name |             // Now try to resolve the normalized name | ||||||
|             pLookupResult = gethostbyname(pHostName); |             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]; |                char *pDnsHostName = (char*) malloc(NI_MAXHOST + 1); | ||||||
|  |                if (pDnsHostName) | ||||||
|                // 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) |  | ||||||
|                { |                { | ||||||
|                   // We resolved the address to a DNS name, use it as the normalized name. |                   // Set up a sockaddr structure | ||||||
|                   pEntry->buffLengthRequired = (int) strlen(dnsHostName) + 1; |                   sockAddr.sin_family = AF_INET; | ||||||
|                   pEntry->pNormalizedHostName = (char*) malloc(pEntry->buffLengthRequired); |                   sockAddr.sin_addr.S_un.S_addr = *((int*) pLookupResult->h_addr_list[0]); | ||||||
|                   if (pEntry->pNormalizedHostName) |  | ||||||
|  |                   // 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 |                      // We resolved the address to a DNS name, use it as the normalized name. | ||||||
|                      strcpy(pEntry->pNormalizedHostName, dnsHostName); |                      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 |                   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 |                else | ||||||
|                { |                { | ||||||
|                   DbgTrace(0, "-NormalizeHostName- getnameInfo failed, error %d\n", WSAGetLastError()); |                   DbgTrace(0, "-NormalizeHostName- Buffer allocation failure\n", 0); | ||||||
|  |  | ||||||
|                   // 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); |  | ||||||
|                   } |  | ||||||
|                } |                } | ||||||
|             } |             } | ||||||
|             else |             else | ||||||
|   | |||||||
| @@ -356,10 +356,14 @@ InternalRpc( | |||||||
| // L2 | // 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 | #define CASA_STATUS_INVALID_SERVER_CERTIFICATE CASA_STATUS_UNSUCCESSFUL // temporary until casa_status.h is updated | ||||||
|  | #endif | ||||||
|  |  | ||||||
|    CasaStatus  retStatus = CASA_STATUS_SUCCESS; |    CasaStatus  retStatus = CASA_STATUS_SUCCESS; | ||||||
|    char        rpcTarget[256]; |    char        *pRpcTarget; | ||||||
|    LPWSTR      pWideRpcTarget; |    LPWSTR      pWideRpcTarget; | ||||||
|    int         wideRpcTargetLen; |    int         wideRpcTargetLen; | ||||||
|    WCHAR       sendHeaders[] = L"Content-Type: text/html"; |    WCHAR       sendHeaders[] = L"Content-Type: text/html"; | ||||||
| @@ -373,173 +377,184 @@ InternalRpc( | |||||||
|    *ppResponseData = NULL; |    *ppResponseData = NULL; | ||||||
|  |  | ||||||
|    // Create rpc target string and convert it to a wide string |    // Create rpc target string and convert it to a wide string | ||||||
|    sprintf(rpcTarget, "CasaAuthTokenSvc/Rpc?method=%s", pMethod); |    pRpcTarget = (char*) malloc(sizeof(RPC_TARGET_FMT_STRING) + strlen(pMethod)); | ||||||
|    retStatus = CopyMultiToWideAlloc(rpcTarget, |    if (pRpcTarget) | ||||||
|                                     (int) strlen(rpcTarget), |  | ||||||
|                                     &pWideRpcTarget, |  | ||||||
|                                     &wideRpcTargetLen); |  | ||||||
|    if (CASA_SUCCESS(retStatus)) |  | ||||||
|    { |    { | ||||||
|       HINTERNET   hRequest; |       sprintf(pRpcTarget, RPC_TARGET_FMT_STRING, pMethod); | ||||||
|  |       retStatus = CopyMultiToWideAlloc(pRpcTarget, | ||||||
|       do |                                        (int) strlen(pRpcTarget), | ||||||
|  |                                        &pWideRpcTarget, | ||||||
|  |                                        &wideRpcTargetLen); | ||||||
|  |       if (CASA_SUCCESS(retStatus)) | ||||||
|       { |       { | ||||||
|          // Forget about having been told to retry |          HINTERNET   hRequest; | ||||||
|          attemptRetry = false; |  | ||||||
|  |  | ||||||
|          // Open a request handle |          do | ||||||
|          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) |  | ||||||
|          { |          { | ||||||
|             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 |             // Open a request handle | ||||||
|             if (flags & SECURE_RPC_FLAG) |             hRequest = WinHttpOpenRequest(pSession->hConnection, | ||||||
|             { |                                           L"POST", | ||||||
|                // We are using secure connections, now proceed based on whether or not |                                           pWideRpcTarget, | ||||||
|                // 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, |  | ||||||
|                                           NULL, |                                           NULL, | ||||||
|                                           &httpCompStatus, |                                           WINHTTP_NO_REFERER, | ||||||
|                                           &httpCompStatusLen, |                                           WINHTTP_DEFAULT_ACCEPT_TYPES, | ||||||
|                                           WINHTTP_NO_HEADER_INDEX)) |                                           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 |                      DWORD secFlags = SECURITY_FLAG_IGNORE_CERT_CN_INVALID | SECURITY_FLAG_IGNORE_UNKNOWN_CA; | ||||||
|                      if (memcmp(httpCompStatus, L"200", sizeof(httpCompStatus)) == 0) |  | ||||||
|  |                      // We are configured to allow invalid certificates, inform the HTTP stack. | ||||||
|  |                      if (WinHttpSetOption(hRequest, | ||||||
|  |                                           WINHTTP_OPTION_SECURITY_FLAGS, | ||||||
|  |                                           &secFlags, | ||||||
|  |                                           sizeof(secFlags)) == FALSE) | ||||||
|                      { |                      { | ||||||
|                         char  *pResponseData; |                         DbgTrace(0, "-InternalRpc- Failed setting options to ignore invalid certs, error = %d\n", GetLastError()); | ||||||
|                         int   responseDataBufSize = INITIAL_RESPONSE_DATA_BUF_SIZE;       |                      } | ||||||
|                         int   responseDataRead = 0; |                   } | ||||||
|  |                   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. |                // Send the request | ||||||
|                         pResponseData = (char*) malloc(INITIAL_RESPONSE_DATA_BUF_SIZE); |                securityFailureStatusFlags = 0; | ||||||
|                         if (pResponseData) |                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; |                            char  *pResponseData; | ||||||
|                            DWORD    bytesRead; |                            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; |                               char     *pCurrLocation = pResponseData; | ||||||
|                               if (WinHttpReadData(hRequest, |                               DWORD    bytesRead; | ||||||
|                                                   (LPVOID) pCurrLocation, |  | ||||||
|                                                   responseDataBufSize - responseDataRead, |                               do | ||||||
|                                                   &bytesRead)) |  | ||||||
|                               { |                               { | ||||||
|                                  pCurrLocation += bytesRead; |                                  bytesRead = 0; | ||||||
|                                  responseDataRead += bytesRead; |                                  if (WinHttpReadData(hRequest, | ||||||
|  |                                                      (LPVOID) pCurrLocation, | ||||||
|                                  // Check if we need to allocate a larger buffer |                                                      responseDataBufSize - responseDataRead, | ||||||
|                                  if (responseDataRead == responseDataBufSize) |                                                      &bytesRead)) | ||||||
|                                  { |                                  { | ||||||
|                                     char  *pTmpBuf; |                                     pCurrLocation += bytesRead; | ||||||
|  |                                     responseDataRead += bytesRead; | ||||||
|  |  | ||||||
|                                     // We need to upgrade the receive buffer |                                     // Check if we need to allocate a larger buffer | ||||||
|                                     pTmpBuf = (char*) malloc(responseDataBufSize + INCREMENT_RESPONSE_DATA_BUF_SIZE); |                                     if (responseDataRead == responseDataBufSize) | ||||||
|                                     if (pTmpBuf) |  | ||||||
|                                     { |                                     { | ||||||
|                                        memcpy(pTmpBuf, pResponseData, responseDataBufSize); |                                        char  *pTmpBuf; | ||||||
|                                        free(pResponseData); |  | ||||||
|                                        pResponseData = pTmpBuf; |                                        // We need to upgrade the receive buffer | ||||||
|                                        pCurrLocation = pResponseData + responseDataBufSize; |                                        pTmpBuf = (char*) malloc(responseDataBufSize + INCREMENT_RESPONSE_DATA_BUF_SIZE); | ||||||
|                                        responseDataBufSize += INCREMENT_RESPONSE_DATA_BUF_SIZE; |                                        if (pTmpBuf) | ||||||
|                                     } |                                        { | ||||||
|                                     else |                                           memcpy(pTmpBuf, pResponseData, responseDataBufSize); | ||||||
|                                     { |                                           free(pResponseData); | ||||||
|                                        DbgTrace(0, "-InternalRpc- Buffer allocation failure\n", 0); |                                           pResponseData = pTmpBuf; | ||||||
|                                        retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, |                                           pCurrLocation = pResponseData + responseDataBufSize; | ||||||
|                                                                    CASA_FACILITY_AUTHTOKEN, |                                           responseDataBufSize += INCREMENT_RESPONSE_DATA_BUF_SIZE; | ||||||
|                                                                    CASA_STATUS_INSUFFICIENT_RESOURCES); |                                        } | ||||||
|  |                                        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 |                               else | ||||||
|                               { |                               { | ||||||
|                                  DbgTrace(0, "-InternalRpc- Failed reading response data, error = %d\n", GetLastError()); |                                  // Failed to receive the response data, free the allocated buffer. | ||||||
|                                  retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, |                                  free(pResponseData); | ||||||
|                                                              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 |                            else | ||||||
|                            { |                            { | ||||||
|                               // Failed to receive the response data, free the allocated buffer. |                               DbgTrace(0, "-InternalRpc- Buffer allocation failure\n", 0); | ||||||
|                               free(pResponseData); |                               retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, | ||||||
|  |                                                           CASA_FACILITY_AUTHTOKEN, | ||||||
|  |                                                           CASA_STATUS_INSUFFICIENT_RESOURCES); | ||||||
|                            } |                            } | ||||||
|                         } |                         } | ||||||
|                         else |                         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, |                            retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, | ||||||
|                                                        CASA_FACILITY_AUTHTOKEN, |                                                        CASA_FACILITY_AUTHTOKEN, | ||||||
|                                                        CASA_STATUS_INSUFFICIENT_RESOURCES); |                                                        CASA_STATUS_UNSUCCESSFUL); | ||||||
|                         } |                         } | ||||||
|                      } |                      } | ||||||
|                      else |                      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, |                         retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, | ||||||
|                                                     CASA_FACILITY_AUTHTOKEN, |                                                     CASA_FACILITY_AUTHTOKEN, | ||||||
|                                                     CASA_STATUS_UNSUCCESSFUL); |                                                     CASA_STATUS_UNSUCCESSFUL); | ||||||
| @@ -547,7 +562,7 @@ InternalRpc( | |||||||
|                   } |                   } | ||||||
|                   else |                   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, |                      retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, | ||||||
|                                                  CASA_FACILITY_AUTHTOKEN, |                                                  CASA_FACILITY_AUTHTOKEN, | ||||||
|                                                  CASA_STATUS_UNSUCCESSFUL); |                                                  CASA_STATUS_UNSUCCESSFUL); | ||||||
| @@ -555,160 +570,163 @@ InternalRpc( | |||||||
|                } |                } | ||||||
|                else |                else | ||||||
|                { |                { | ||||||
|                   DbgTrace(0, "-InternalRpc- Unable to receive response, error = %d\n", GetLastError()); |                   int   error = GetLastError(); | ||||||
|                   retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, |  | ||||||
|                                               CASA_FACILITY_AUTHTOKEN, |  | ||||||
|                                               CASA_STATUS_UNSUCCESSFUL); |  | ||||||
|                } |  | ||||||
|             } |  | ||||||
|             else |  | ||||||
|             { |  | ||||||
|                int   error = GetLastError(); |  | ||||||
|  |  | ||||||
|                if (error == ERROR_WINHTTP_CANNOT_CONNECT) |                   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; |                      DbgTrace(0, "-InternalRpc- Unable to connect to server\n", 0); | ||||||
|                      DWORD certInfoLen = sizeof(certInfo); |                      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. |                      // Try to deal with the issue | ||||||
|                      // |                      if ((securityFailureStatusFlags & ~(WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CA | ||||||
|                      // Obtain information about the server certificate to give user |                                                          | WINHTTP_CALLBACK_STATUS_FLAG_CERT_CN_INVALID | ||||||
|                      // the choice of accepting it. |                                                          | WINHTTP_CALLBACK_STATUS_FLAG_CERT_DATE_INVALID)) == 0 | ||||||
|                      if (WinHttpQueryOption(hRequest, |                          && flags & ALLOW_INVALID_CERTS_USER_APPROVAL_RPC_FLAG) | ||||||
|                                             WINHTTP_OPTION_SECURITY_CERTIFICATE_STRUCT, |  | ||||||
|                                             &certInfo, |  | ||||||
|                                             &certInfoLen) |  | ||||||
|                          && certInfo.lpszSubjectInfo != NULL |  | ||||||
|                          && certInfo.lpszIssuerInfo != NULL) |  | ||||||
|                      { |                      { | ||||||
|                         char  *pSubjectInfo; |                         WINHTTP_CERTIFICATE_INFO certInfo; | ||||||
|                         int   subjectInfoLen; |                         DWORD certInfoLen = sizeof(certInfo); | ||||||
|  |  | ||||||
|                         // Convert the subjectInfo to multi-byte |                         // The failure was due to an invalid CN, CA, or both. | ||||||
|                         retStatus = CopyWideToMultiAlloc(certInfo.lpszSubjectInfo, |                         // | ||||||
|                                                          (int) wcslen(certInfo.lpszSubjectInfo), |                         // Obtain information about the server certificate to give user | ||||||
|                                                          &pSubjectInfo, |                         // the choice of accepting it. | ||||||
|                                                          &subjectInfoLen); |                         if (WinHttpQueryOption(hRequest, | ||||||
|                         if (CASA_SUCCESS(retStatus)) |                                                WINHTTP_OPTION_SECURITY_CERTIFICATE_STRUCT, | ||||||
|  |                                                &certInfo, | ||||||
|  |                                                &certInfoLen) | ||||||
|  |                             && certInfo.lpszSubjectInfo != NULL | ||||||
|  |                             && certInfo.lpszIssuerInfo != NULL) | ||||||
|                         { |                         { | ||||||
|                            char  *pIssuerInfo; |                            char  *pSubjectInfo; | ||||||
|                            int   issuerInfoLen; |                            int   subjectInfoLen; | ||||||
|  |  | ||||||
|                            // Convert the issuerInfo to multi-byte |                            // Convert the subjectInfo to multi-byte | ||||||
|                            retStatus = CopyWideToMultiAlloc(certInfo.lpszIssuerInfo, |                            retStatus = CopyWideToMultiAlloc(certInfo.lpszSubjectInfo, | ||||||
|                                                             (int) wcslen(certInfo.lpszIssuerInfo), |                                                             (int) wcslen(certInfo.lpszSubjectInfo), | ||||||
|                                                             &pIssuerInfo, |                                                             &pSubjectInfo, | ||||||
|                                                             &issuerInfoLen); |                                                             &subjectInfoLen); | ||||||
|                            if (CASA_SUCCESS(retStatus)) |                            if (CASA_SUCCESS(retStatus)) | ||||||
|                            { |                            { | ||||||
|                               long  invalidCertFlags = 0; |                               char  *pIssuerInfo; | ||||||
|  |                               int   issuerInfoLen; | ||||||
|  |  | ||||||
|                               // Setup the invalid cert flags |                               // Convert the issuerInfo to multi-byte | ||||||
|                               if (securityFailureStatusFlags & WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CA) |                               retStatus = CopyWideToMultiAlloc(certInfo.lpszIssuerInfo, | ||||||
|                                  invalidCertFlags |= INVALID_CERT_CA_FLAG; |                                                                (int) wcslen(certInfo.lpszIssuerInfo), | ||||||
|  |                                                                &pIssuerInfo, | ||||||
|                               if (securityFailureStatusFlags & WINHTTP_CALLBACK_STATUS_FLAG_CERT_CN_INVALID) |                                                                &issuerInfoLen); | ||||||
|                                  invalidCertFlags |= INVALID_CERT_CN_FLAG; |                               if (CASA_SUCCESS(retStatus)) | ||||||
|  |  | ||||||
|                               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); |                                  long  invalidCertFlags = 0; | ||||||
|  |  | ||||||
|                                  // tbd - Investigate if there is a way to set the accepted certificate in a store so that |                                  // Setup the invalid cert flags | ||||||
|                                  // it can be utilized by the SSL stack directly. This would be a better method for dealing with |                                  if (securityFailureStatusFlags & WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CA) | ||||||
|                                  // this issue. |                                     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 |                                  if (securityFailureStatusFlags & WINHTTP_CALLBACK_STATUS_FLAG_CERT_DATE_INVALID) | ||||||
|                                  attemptRetry = true; |                                     invalidCertFlags |= INVALID_CERT_DATE_FLAG; | ||||||
|                               } |  | ||||||
|                               else |  | ||||||
|                               { |  | ||||||
|                                  DbgTrace(1, "-InternalRpc- User did not approve invalid certificate from %s\n", pSession->pHostName); |  | ||||||
|  |  | ||||||
|                                  retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, |                                  // Give user the choice to accept the certificate | ||||||
|                                                              CASA_FACILITY_AUTHTOKEN, |                                  if (UserApprovedCert(pSession->pHostName, | ||||||
|                                                              CASA_STATUS_INVALID_SERVER_CERTIFICATE); |                                                       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 the buffer containing the subjectInfo | ||||||
|                               free(pIssuerInfo); |                               free(pSubjectInfo); | ||||||
|                            } |                            } | ||||||
|  |  | ||||||
|                            // Free the buffer containing the subjectInfo |                            // Free necessary certificate information | ||||||
|                            free(pSubjectInfo); |                            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 |                      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 |                   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, |                      retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, | ||||||
|                                                  CASA_FACILITY_AUTHTOKEN, |                                                  CASA_FACILITY_AUTHTOKEN, | ||||||
|                                                  CASA_STATUS_INVALID_SERVER_CERTIFICATE); |                                                  CASA_STATUS_UNSUCCESSFUL); | ||||||
|                   } |                   } | ||||||
|                } |                } | ||||||
|                else |  | ||||||
|                { |                // Close the request handle | ||||||
|                   DbgTrace(0, "-InternalRpc- Unsuccessful send http request, error = %d\n", error); |                WinHttpCloseHandle(hRequest); | ||||||
|                   retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, |  | ||||||
|                                               CASA_FACILITY_AUTHTOKEN, |  | ||||||
|                                               CASA_STATUS_UNSUCCESSFUL); |  | ||||||
|                } |  | ||||||
|             } |             } | ||||||
|  |             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 |          // Free the rpc target wide string buffer | ||||||
|             WinHttpCloseHandle(hRequest); |          free(pWideRpcTarget); | ||||||
|          } |       } | ||||||
|          else |       else | ||||||
|          { |       { | ||||||
|             DbgTrace(0, "-InternalRpc- Unable to open http request, error = %d\n", GetLastError()); |          DbgTrace(0, "-InternalRpc- Error converting method name to wide string\n", 0); | ||||||
|             retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, |       } | ||||||
|                                         CASA_FACILITY_AUTHTOKEN, |  | ||||||
|                                         CASA_STATUS_UNSUCCESSFUL); |  | ||||||
|          } |  | ||||||
|       } while (attemptRetry && retriesAllowed--); |  | ||||||
|  |  | ||||||
|       // Free the rpc target wide string buffer |       // Free buffer used to hold the rpc target string | ||||||
|       free(pWideRpcTarget); |       free(pRpcTarget); | ||||||
|    } |    } | ||||||
|    else |    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); |    DbgTrace(1, "-InternalRpc- End, retStatus = %d\n", retStatus); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user