HttpWinUtils.cpp (3877B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 #include "HttpWinUtils.h" 6 #include "nsIURI.h" 7 #include "nsHttpChannel.h" 8 #include "mozilla/ClearOnShutdown.h" 9 #include <proofofpossessioncookieinfo.h> 10 11 namespace mozilla { 12 namespace net { 13 14 static StaticRefPtr<IProofOfPossessionCookieInfoManager> sPopCookieManager; 15 static bool sPopCookieManagerAvailable = true; 16 17 void AddWindowsSSO(nsHttpChannel* channel) { 18 if (!sPopCookieManagerAvailable) { 19 MOZ_LOG(gHttpLog, mozilla::LogLevel::Debug, 20 ("HttpWinUtils::AddWindowsSSO: sPopCookieManager is not available " 21 "from the beginning")); 22 return; 23 } 24 HRESULT hr; 25 if (!sPopCookieManager) { 26 GUID CLSID_ProofOfPossessionCookieInfoManager; 27 GUID IID_IProofOfPossessionCookieInfoManager; 28 29 CLSIDFromString(L"{A9927F85-A304-4390-8B23-A75F1C668600}", 30 &CLSID_ProofOfPossessionCookieInfoManager); 31 IIDFromString(L"{CDAECE56-4EDF-43DF-B113-88E4556FA1BB}", 32 &IID_IProofOfPossessionCookieInfoManager); 33 34 hr = CoCreateInstance(CLSID_ProofOfPossessionCookieInfoManager, NULL, 35 CLSCTX_INPROC_SERVER, 36 IID_IProofOfPossessionCookieInfoManager, 37 reinterpret_cast<void**>(&sPopCookieManager)); 38 if (FAILED(hr)) { 39 sPopCookieManagerAvailable = false; 40 MOZ_LOG( 41 gHttpLog, mozilla::LogLevel::Debug, 42 ("HttpWinUtils::AddWindowsSSO: sPopCookieManager is not available")); 43 return; 44 } 45 46 RunOnShutdown([&] { 47 if (sPopCookieManager) { 48 sPopCookieManager = nullptr; 49 } 50 }); 51 } 52 53 DWORD cookieCount = 0; 54 ProofOfPossessionCookieInfo* cookieInfo = nullptr; 55 56 nsCOMPtr<nsIURI> uri; 57 channel->GetURI(getter_AddRefs(uri)); 58 59 nsAutoCString urispec; 60 uri->GetSpec(urispec); 61 62 hr = sPopCookieManager->GetCookieInfoForUri( 63 NS_ConvertUTF8toUTF16(urispec).get(), &cookieCount, &cookieInfo); 64 if (FAILED(hr)) { 65 MOZ_LOG(gHttpLog, mozilla::LogLevel::Debug, 66 ("HttpWinUtils::AddWindowsSSO: GetCookieInfoForUri failed")); 67 return; 68 } 69 70 nsAutoCString host; 71 uri->GetHost(host); 72 bool addCookies = false; 73 if (StringEndsWith(host, ".live.com"_ns)) { 74 addCookies = true; 75 } 76 77 nsAutoString allCookies; 78 79 for (DWORD i = 0; i < cookieCount; i++) { 80 nsAutoString cookieData; 81 cookieData.Assign(cookieInfo[i].data); 82 // Strip old Set-Cookie info for WinInet 83 int32_t semicolon = cookieData.FindChar(';'); 84 if (semicolon >= 0) { 85 cookieData.SetLength(semicolon); 86 } 87 if (StringBeginsWith(nsDependentString(cookieInfo[i].name), u"x-ms-"_ns)) { 88 channel->SetRequestHeader(NS_ConvertUTF16toUTF8(cookieInfo[i].name), 89 NS_ConvertUTF16toUTF8(cookieData), 90 true /* merge */); 91 } else if (addCookies) { 92 if (!allCookies.IsEmpty()) { 93 allCookies.AppendLiteral("; "); 94 } 95 allCookies.Append(cookieInfo[i].name); 96 allCookies.AppendLiteral("="); 97 allCookies.Append(cookieData); 98 } 99 } 100 101 // Merging cookie headers doesn't work correctly as it separates the new 102 // cookies using commas instead of semicolons, so we have to replace 103 // the entire header. 104 if (!allCookies.IsEmpty()) { 105 nsAutoCString cookieHeader; 106 channel->GetRequestHeader(nsHttp::Cookie.val(), cookieHeader); 107 if (!cookieHeader.IsEmpty()) { 108 cookieHeader.AppendLiteral("; "); 109 } 110 cookieHeader.Append(NS_ConvertUTF16toUTF8(allCookies)); 111 channel->SetRequestHeader(nsHttp::Cookie.val(), cookieHeader, false); 112 } 113 if (cookieInfo) { 114 FreeProofOfPossessionCookieInfoArray(cookieInfo, cookieCount); 115 } 116 } 117 118 } // namespace net 119 } // namespace mozilla