mirror of
https://github.com/actions/runner.git
synced 2025-12-10 12:36:23 +00:00
265 lines
9.0 KiB
C#
265 lines
9.0 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Globalization;
|
|
using System.Linq;
|
|
using System.Net;
|
|
using System.Net.Http;
|
|
using System.Runtime.InteropServices;
|
|
using System.Text;
|
|
using GitHub.Services.Common;
|
|
|
|
namespace GitHub.Services.Client
|
|
{
|
|
internal static class CookieUtility
|
|
{
|
|
public static readonly String AcsMetadataRetrievalExceptionText = "Unable to retrieve ACS Metadata from '{0}'";
|
|
public static readonly String FedAuthCookieName = "FedAuth";
|
|
public static readonly String WindowsLiveSignOutUrl = "https://login.live.com/uilogout.srf";
|
|
public static readonly Uri WindowsLiveCookieDomain = new Uri("https://login.live.com/");
|
|
|
|
public static CookieCollection GetFederatedCookies(Uri cookieDomainAndPath)
|
|
{
|
|
CookieCollection result = null;
|
|
|
|
Cookie cookie = GetCookieEx(cookieDomainAndPath, FedAuthCookieName).FirstOrDefault();
|
|
|
|
if (cookie != null)
|
|
{
|
|
result = new CookieCollection();
|
|
result.Add(cookie);
|
|
|
|
for (Int32 x = 1; x < 50; x++)
|
|
{
|
|
String cookieName = FedAuthCookieName + x;
|
|
cookie = GetCookieEx(cookieDomainAndPath, cookieName).FirstOrDefault();
|
|
|
|
if (cookie != null)
|
|
{
|
|
result.Add(cookie);
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
public static CookieCollection GetFederatedCookies(String[] token)
|
|
{
|
|
CookieCollection result = null;
|
|
|
|
if (token != null && token.Length > 0 && token[0] != null)
|
|
{
|
|
result = new CookieCollection();
|
|
result.Add(new Cookie(FedAuthCookieName, token[0]));
|
|
|
|
for (Int32 x = 1; x < token.Length; x++)
|
|
{
|
|
String cookieName = FedAuthCookieName + x;
|
|
|
|
if (token[x] != null)
|
|
{
|
|
Cookie cookie = new Cookie(cookieName, token[x]);
|
|
cookie.HttpOnly = true;
|
|
result.Add(cookie);
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
public static CookieCollection GetFederatedCookies(IHttpResponse webResponse)
|
|
{
|
|
CookieCollection result = null;
|
|
IEnumerable<String> cookies = null;
|
|
|
|
if (webResponse.Headers.TryGetValues("Set-Cookie", out cookies))
|
|
{
|
|
foreach (String cookie in cookies)
|
|
{
|
|
if (cookie != null && cookie.StartsWith(CookieUtility.FedAuthCookieName, StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
// Only take the security token field of the cookie, and discard the rest
|
|
String fedAuthToken = cookie.Split(';').FirstOrDefault();
|
|
Int32 index = fedAuthToken.IndexOf('=');
|
|
|
|
if (index > 0 && index < fedAuthToken.Length - 1)
|
|
{
|
|
String name = fedAuthToken.Substring(0, index);
|
|
String value = fedAuthToken.Substring(index + 1);
|
|
|
|
result = result ?? new CookieCollection();
|
|
result.Add(new Cookie(name, value));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
public static CookieCollection GetAllCookies(Uri cookieDomainAndPath)
|
|
{
|
|
CookieCollection result = null;
|
|
List<Cookie> cookies = GetCookieEx(cookieDomainAndPath, null);
|
|
foreach (Cookie cookie in cookies)
|
|
{
|
|
if (result == null)
|
|
{
|
|
result = new CookieCollection();
|
|
}
|
|
|
|
result.Add(cookie);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
public static void DeleteFederatedCookies(Uri cookieDomainAndPath)
|
|
{
|
|
CookieCollection cookies = GetFederatedCookies(cookieDomainAndPath);
|
|
|
|
if (cookies != null)
|
|
{
|
|
foreach (Cookie cookie in cookies)
|
|
{
|
|
DeleteCookieEx(cookieDomainAndPath, cookie.Name);
|
|
}
|
|
}
|
|
}
|
|
|
|
public static void DeleteWindowsLiveCookies()
|
|
{
|
|
DeleteAllCookies(WindowsLiveCookieDomain);
|
|
}
|
|
|
|
public static void DeleteAllCookies(Uri cookieDomainAndPath)
|
|
{
|
|
CookieCollection cookies = GetAllCookies(cookieDomainAndPath);
|
|
|
|
if (cookies != null)
|
|
{
|
|
foreach (Cookie cookie in cookies)
|
|
{
|
|
DeleteCookieEx(cookieDomainAndPath, cookie.Name);
|
|
}
|
|
}
|
|
}
|
|
|
|
public const UInt32 INTERNET_COOKIE_HTTPONLY = 0x00002000;
|
|
|
|
[DllImport("wininet.dll", SetLastError = true, CharSet = CharSet.Unicode)]
|
|
static extern bool InternetGetCookieEx(
|
|
String url, String cookieName, StringBuilder cookieData, ref Int32 size, UInt32 flags, IntPtr reserved);
|
|
|
|
[DllImport("wininet.dll", SetLastError = true, CharSet = CharSet.Unicode)]
|
|
static extern bool InternetSetCookieEx(
|
|
String url, String cookieName, String cookieData, UInt32 flags, IntPtr reserved);
|
|
|
|
public static Boolean DeleteCookieEx(Uri cookiePath, String cookieName)
|
|
{
|
|
UInt32 flags = INTERNET_COOKIE_HTTPONLY;
|
|
|
|
String path = cookiePath.ToString();
|
|
if (!path.EndsWith("/", StringComparison.Ordinal))
|
|
{
|
|
path = path + "/";
|
|
}
|
|
|
|
DateTime expiration = DateTime.UtcNow.AddYears(-1);
|
|
String cookieData = String.Format(CultureInfo.InvariantCulture, "{0}=0;expires={1};path=/;domain={2};httponly", cookieName, expiration.ToString("R"), cookiePath.Host);
|
|
|
|
return InternetSetCookieEx(path, null, cookieData, flags, IntPtr.Zero);
|
|
}
|
|
|
|
public static Boolean SetCookiesEx(
|
|
Uri cookiePath,
|
|
CookieCollection cookies)
|
|
{
|
|
String path = cookiePath.ToString();
|
|
if (!path.EndsWith("/", StringComparison.Ordinal))
|
|
{
|
|
path = path + "/";
|
|
}
|
|
|
|
Boolean successful = true;
|
|
foreach (Cookie cookie in cookies)
|
|
{
|
|
// This means it doesn't expire
|
|
if (cookie.Expires.Year == 1)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
String cookieData = String.Format(CultureInfo.InvariantCulture,
|
|
"{0}; path={1}; domain={2}; expires={3}; httponly",
|
|
cookie.Value,
|
|
cookie.Path,
|
|
cookie.Domain,
|
|
cookie.Expires.ToString("ddd, dd-MMM-yyyy HH:mm:ss 'GMT'"));
|
|
|
|
successful &= InternetSetCookieEx(path, cookie.Name, cookieData, INTERNET_COOKIE_HTTPONLY, IntPtr.Zero);
|
|
}
|
|
return successful;
|
|
}
|
|
|
|
public static List<Cookie> GetCookieEx(Uri cookiePath, String cookieName)
|
|
{
|
|
UInt32 flags = INTERNET_COOKIE_HTTPONLY;
|
|
|
|
List<Cookie> cookies = new List<Cookie>();
|
|
Int32 size = 256;
|
|
StringBuilder cookieData = new StringBuilder(size);
|
|
String path = cookiePath.ToString();
|
|
if (!path.EndsWith("/", StringComparison.Ordinal))
|
|
{
|
|
path = path + "/";
|
|
}
|
|
|
|
if (!InternetGetCookieEx(path, cookieName, cookieData, ref size, flags, IntPtr.Zero))
|
|
{
|
|
if (size < 0)
|
|
{
|
|
return cookies;
|
|
}
|
|
|
|
cookieData = new StringBuilder(size);
|
|
|
|
if (!InternetGetCookieEx(path, cookieName, cookieData, ref size, flags, IntPtr.Zero))
|
|
{
|
|
return cookies;
|
|
}
|
|
}
|
|
|
|
if (cookieData.Length > 0)
|
|
{
|
|
String[] cookieSections = cookieData.ToString().Split(new char[] { ';' });
|
|
|
|
foreach (String cookieSection in cookieSections)
|
|
{
|
|
String[] cookieParts = cookieSection.Split(new char[] { '=' }, 2);
|
|
|
|
if (cookieParts.Length == 2)
|
|
{
|
|
Cookie cookie = new Cookie();
|
|
cookie.Name = cookieParts[0].TrimStart();
|
|
cookie.Value = cookieParts[1];
|
|
cookie.HttpOnly = true;
|
|
cookies.Add(cookie);
|
|
}
|
|
}
|
|
}
|
|
|
|
return cookies;
|
|
}
|
|
}
|
|
}
|