Unverified Commit bb3b57c6 authored by honfika's avatar honfika Committed by GitHub

Merge pull request #803 from justcoding121/master

beta
parents 06cb6ee8 cc28b9fc
<!DOCTYPE html>
<!--[if IE]><![endif]-->
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Enum AlternativeNameType
| Titanium Web Proxy </title>
<meta name="viewport" content="width=device-width">
<meta name="title" content="Enum AlternativeNameType
| Titanium Web Proxy ">
<meta name="generator" content="docfx 2.55.0.0">
<link rel="shortcut icon" href="../favicon.ico">
<link rel="stylesheet" href="../styles/docfx.vendor.css">
<link rel="stylesheet" href="../styles/docfx.css">
<link rel="stylesheet" href="../styles/main.css">
<meta property="docfx:navrel" content="">
<meta property="docfx:tocrel" content="toc.html">
<meta property="docfx:rel" content="../">
</head>
<body data-spy="scroll" data-target="#affix" data-offset="120">
<div id="wrapper">
<header>
<nav id="autocollapse" class="navbar navbar-inverse ng-scope" role="navigation">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="../index.html">
<img id="logo" class="svg" src="../logo.svg" alt="">
</a>
</div>
<div class="collapse navbar-collapse" id="navbar">
<form class="navbar-form navbar-right" role="search" id="search">
<div class="form-group">
<input type="text" class="form-control" id="search-query" placeholder="Search" autocomplete="off">
</div>
</form>
</div>
</div>
</nav>
<div class="subnav navbar navbar-default">
<div class="container hide-when-search" id="breadcrumb">
<ul class="breadcrumb">
<li></li>
</ul>
</div>
</div>
</header>
<div class="container body-content">
<div id="search-results">
<div class="search-list"></div>
<div class="sr-items">
<p><i class="glyphicon glyphicon-refresh index-loading"></i></p>
</div>
<ul id="pagination"></ul>
</div>
</div>
<div role="main" class="container body-content hide-when-search">
<div class="sidenav hide-when-search">
<a class="btn toc-toggle collapse" data-toggle="collapse" href="#sidetoggle" aria-expanded="false" aria-controls="sidetoggle">Show / Hide Table of Contents</a>
<div class="sidetoggle collapse" id="sidetoggle">
<div id="sidetoc"></div>
</div>
</div>
<div class="article row grid-right">
<div class="col-md-10">
<article class="content wrap" id="_content" data-uid="Titanium.Web.Proxy.Network.Certificate.AlternativeNameType">
<h1 id="Titanium_Web_Proxy_Network_Certificate_AlternativeNameType" data-uid="Titanium.Web.Proxy.Network.Certificate.AlternativeNameType" class="text-break">Enum AlternativeNameType
</h1>
<div class="markdown level0 summary"></div>
<div class="markdown level0 conceptual"></div>
<h6><strong>Namespace</strong>: <a class="xref" href="Titanium.Web.Proxy.Network.Certificate.html">Titanium.Web.Proxy.Network.Certificate</a></h6>
<h6><strong>Assembly</strong>: Titanium.Web.Proxy.dll</h6>
<h5 id="Titanium_Web_Proxy_Network_Certificate_AlternativeNameType_syntax">Syntax</h5>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public enum AlternativeNameType</code></pre>
</div>
<h3 id="fields">Fields
</h3>
<table class="table table-bordered table-striped table-condensed">
<thead>
<tr>
<th>Name</th>
<th>Description</th>
</tr>
<thead>
<tbody>
<tr>
<td id="Titanium_Web_Proxy_Network_Certificate_AlternativeNameType_XCN_CERT_ALT_NAME_DIRECTORY_NAME">XCN_CERT_ALT_NAME_DIRECTORY_NAME</td>
<td></td>
</tr>
<tr>
<td id="Titanium_Web_Proxy_Network_Certificate_AlternativeNameType_XCN_CERT_ALT_NAME_DNS_NAME">XCN_CERT_ALT_NAME_DNS_NAME</td>
<td></td>
</tr>
<tr>
<td id="Titanium_Web_Proxy_Network_Certificate_AlternativeNameType_XCN_CERT_ALT_NAME_GUID">XCN_CERT_ALT_NAME_GUID</td>
<td></td>
</tr>
<tr>
<td id="Titanium_Web_Proxy_Network_Certificate_AlternativeNameType_XCN_CERT_ALT_NAME_IP_ADDRESS">XCN_CERT_ALT_NAME_IP_ADDRESS</td>
<td></td>
</tr>
<tr>
<td id="Titanium_Web_Proxy_Network_Certificate_AlternativeNameType_XCN_CERT_ALT_NAME_OTHER_NAME">XCN_CERT_ALT_NAME_OTHER_NAME</td>
<td></td>
</tr>
<tr>
<td id="Titanium_Web_Proxy_Network_Certificate_AlternativeNameType_XCN_CERT_ALT_NAME_REGISTERED_ID">XCN_CERT_ALT_NAME_REGISTERED_ID</td>
<td></td>
</tr>
<tr>
<td id="Titanium_Web_Proxy_Network_Certificate_AlternativeNameType_XCN_CERT_ALT_NAME_RFC822_NAME">XCN_CERT_ALT_NAME_RFC822_NAME</td>
<td></td>
</tr>
<tr>
<td id="Titanium_Web_Proxy_Network_Certificate_AlternativeNameType_XCN_CERT_ALT_NAME_UNKNOWN">XCN_CERT_ALT_NAME_UNKNOWN</td>
<td></td>
</tr>
<tr>
<td id="Titanium_Web_Proxy_Network_Certificate_AlternativeNameType_XCN_CERT_ALT_NAME_URL">XCN_CERT_ALT_NAME_URL</td>
<td></td>
</tr>
<tr>
<td id="Titanium_Web_Proxy_Network_Certificate_AlternativeNameType_XCN_CERT_ALT_NAME_USER_PRINCIPLE_NAME">XCN_CERT_ALT_NAME_USER_PRINCIPLE_NAME</td>
<td></td>
</tr>
</tbody>
</thead></thead></table>
</article>
</div>
<div class="hidden-sm col-md-2" role="complementary">
<div class="sideaffix">
<div class="contribution">
<ul class="nav">
<li>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_Network_Certificate_AlternativeNameType.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.Network.Certificate.AlternativeNameType%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A" class="contribution-link">Improve this Doc</a>
</li>
<li>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/Certificates/WinCertificateMaker.cs/#L339" class="contribution-link">View Source</a>
</li>
</ul>
</div>
<nav class="bs-docs-sidebar hidden-print hidden-xs hidden-sm affix" id="affix">
<!-- <p><a class="back-to-top" href="#top">Back to top</a><p> -->
</nav>
</div>
</div>
</div>
</div>
<footer>
<div class="grad-bottom"></div>
<div class="footer">
<div class="container">
<span class="pull-right">
<a href="#top">Back to top</a>
</span>
<span>Generated by <strong>DocFX</strong></span>
</div>
</div>
</footer>
</div>
<script type="text/javascript" src="../styles/docfx.vendor.js"></script>
<script type="text/javascript" src="../styles/docfx.js"></script>
<script type="text/javascript" src="../styles/main.js"></script>
</body>
</html>
<!DOCTYPE html>
<!--[if IE]><![endif]-->
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Enum EncodingType
| Titanium Web Proxy </title>
<meta name="viewport" content="width=device-width">
<meta name="title" content="Enum EncodingType
| Titanium Web Proxy ">
<meta name="generator" content="docfx 2.55.0.0">
<link rel="shortcut icon" href="../favicon.ico">
<link rel="stylesheet" href="../styles/docfx.vendor.css">
<link rel="stylesheet" href="../styles/docfx.css">
<link rel="stylesheet" href="../styles/main.css">
<meta property="docfx:navrel" content="">
<meta property="docfx:tocrel" content="toc.html">
<meta property="docfx:rel" content="../">
</head>
<body data-spy="scroll" data-target="#affix" data-offset="120">
<div id="wrapper">
<header>
<nav id="autocollapse" class="navbar navbar-inverse ng-scope" role="navigation">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="../index.html">
<img id="logo" class="svg" src="../logo.svg" alt="">
</a>
</div>
<div class="collapse navbar-collapse" id="navbar">
<form class="navbar-form navbar-right" role="search" id="search">
<div class="form-group">
<input type="text" class="form-control" id="search-query" placeholder="Search" autocomplete="off">
</div>
</form>
</div>
</div>
</nav>
<div class="subnav navbar navbar-default">
<div class="container hide-when-search" id="breadcrumb">
<ul class="breadcrumb">
<li></li>
</ul>
</div>
</div>
</header>
<div class="container body-content">
<div id="search-results">
<div class="search-list"></div>
<div class="sr-items">
<p><i class="glyphicon glyphicon-refresh index-loading"></i></p>
</div>
<ul id="pagination"></ul>
</div>
</div>
<div role="main" class="container body-content hide-when-search">
<div class="sidenav hide-when-search">
<a class="btn toc-toggle collapse" data-toggle="collapse" href="#sidetoggle" aria-expanded="false" aria-controls="sidetoggle">Show / Hide Table of Contents</a>
<div class="sidetoggle collapse" id="sidetoggle">
<div id="sidetoc"></div>
</div>
</div>
<div class="article row grid-right">
<div class="col-md-10">
<article class="content wrap" id="_content" data-uid="Titanium.Web.Proxy.Network.Certificate.EncodingType">
<h1 id="Titanium_Web_Proxy_Network_Certificate_EncodingType" data-uid="Titanium.Web.Proxy.Network.Certificate.EncodingType" class="text-break">Enum EncodingType
</h1>
<div class="markdown level0 summary"></div>
<div class="markdown level0 conceptual"></div>
<h6><strong>Namespace</strong>: <a class="xref" href="Titanium.Web.Proxy.Network.Certificate.html">Titanium.Web.Proxy.Network.Certificate</a></h6>
<h6><strong>Assembly</strong>: Titanium.Web.Proxy.dll</h6>
<h5 id="Titanium_Web_Proxy_Network_Certificate_EncodingType_syntax">Syntax</h5>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public enum EncodingType</code></pre>
</div>
<h3 id="fields">Fields
</h3>
<table class="table table-bordered table-striped table-condensed">
<thead>
<tr>
<th>Name</th>
<th>Description</th>
</tr>
<thead>
<tbody>
<tr>
<td id="Titanium_Web_Proxy_Network_Certificate_EncodingType_XCN_CRYPT_STRING_ANY">XCN_CRYPT_STRING_ANY</td>
<td></td>
</tr>
<tr>
<td id="Titanium_Web_Proxy_Network_Certificate_EncodingType_XCN_CRYPT_STRING_BASE64">XCN_CRYPT_STRING_BASE64</td>
<td></td>
</tr>
<tr>
<td id="Titanium_Web_Proxy_Network_Certificate_EncodingType_XCN_CRYPT_STRING_BASE64_ANY">XCN_CRYPT_STRING_BASE64_ANY</td>
<td></td>
</tr>
<tr>
<td id="Titanium_Web_Proxy_Network_Certificate_EncodingType_XCN_CRYPT_STRING_BASE64HEADER">XCN_CRYPT_STRING_BASE64HEADER</td>
<td></td>
</tr>
<tr>
<td id="Titanium_Web_Proxy_Network_Certificate_EncodingType_XCN_CRYPT_STRING_BASE64REQUESTHEADER">XCN_CRYPT_STRING_BASE64REQUESTHEADER</td>
<td></td>
</tr>
<tr>
<td id="Titanium_Web_Proxy_Network_Certificate_EncodingType_XCN_CRYPT_STRING_BASE64URI">XCN_CRYPT_STRING_BASE64URI</td>
<td></td>
</tr>
<tr>
<td id="Titanium_Web_Proxy_Network_Certificate_EncodingType_XCN_CRYPT_STRING_BASE64X509CRLHEADER">XCN_CRYPT_STRING_BASE64X509CRLHEADER</td>
<td></td>
</tr>
<tr>
<td id="Titanium_Web_Proxy_Network_Certificate_EncodingType_XCN_CRYPT_STRING_BINARY">XCN_CRYPT_STRING_BINARY</td>
<td></td>
</tr>
<tr>
<td id="Titanium_Web_Proxy_Network_Certificate_EncodingType_XCN_CRYPT_STRING_CHAIN">XCN_CRYPT_STRING_CHAIN</td>
<td></td>
</tr>
<tr>
<td id="Titanium_Web_Proxy_Network_Certificate_EncodingType_XCN_CRYPT_STRING_ENCODEMASK">XCN_CRYPT_STRING_ENCODEMASK</td>
<td></td>
</tr>
<tr>
<td id="Titanium_Web_Proxy_Network_Certificate_EncodingType_XCN_CRYPT_STRING_HASHDATA">XCN_CRYPT_STRING_HASHDATA</td>
<td></td>
</tr>
<tr>
<td id="Titanium_Web_Proxy_Network_Certificate_EncodingType_XCN_CRYPT_STRING_HEX">XCN_CRYPT_STRING_HEX</td>
<td></td>
</tr>
<tr>
<td id="Titanium_Web_Proxy_Network_Certificate_EncodingType_XCN_CRYPT_STRING_HEX_ANY">XCN_CRYPT_STRING_HEX_ANY</td>
<td></td>
</tr>
<tr>
<td id="Titanium_Web_Proxy_Network_Certificate_EncodingType_XCN_CRYPT_STRING_HEXADDR">XCN_CRYPT_STRING_HEXADDR</td>
<td></td>
</tr>
<tr>
<td id="Titanium_Web_Proxy_Network_Certificate_EncodingType_XCN_CRYPT_STRING_HEXASCII">XCN_CRYPT_STRING_HEXASCII</td>
<td></td>
</tr>
<tr>
<td id="Titanium_Web_Proxy_Network_Certificate_EncodingType_XCN_CRYPT_STRING_HEXASCIIADDR">XCN_CRYPT_STRING_HEXASCIIADDR</td>
<td></td>
</tr>
<tr>
<td id="Titanium_Web_Proxy_Network_Certificate_EncodingType_XCN_CRYPT_STRING_HEXRAW">XCN_CRYPT_STRING_HEXRAW</td>
<td></td>
</tr>
<tr>
<td id="Titanium_Web_Proxy_Network_Certificate_EncodingType_XCN_CRYPT_STRING_NOCR">XCN_CRYPT_STRING_NOCR</td>
<td></td>
</tr>
<tr>
<td id="Titanium_Web_Proxy_Network_Certificate_EncodingType_XCN_CRYPT_STRING_NOCRLF">XCN_CRYPT_STRING_NOCRLF</td>
<td></td>
</tr>
<tr>
<td id="Titanium_Web_Proxy_Network_Certificate_EncodingType_XCN_CRYPT_STRING_PERCENTESCAPE">XCN_CRYPT_STRING_PERCENTESCAPE</td>
<td></td>
</tr>
<tr>
<td id="Titanium_Web_Proxy_Network_Certificate_EncodingType_XCN_CRYPT_STRING_STRICT">XCN_CRYPT_STRING_STRICT</td>
<td></td>
</tr>
<tr>
<td id="Titanium_Web_Proxy_Network_Certificate_EncodingType_XCN_CRYPT_STRING_TEXT">XCN_CRYPT_STRING_TEXT</td>
<td></td>
</tr>
</tbody>
</thead></thead></table>
</article>
</div>
<div class="hidden-sm col-md-2" role="complementary">
<div class="sideaffix">
<div class="contribution">
<ul class="nav">
<li>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_Network_Certificate_EncodingType.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.Network.Certificate.EncodingType%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A" class="contribution-link">Improve this Doc</a>
</li>
<li>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/Certificates/WinCertificateMaker.cs/#L313" class="contribution-link">View Source</a>
</li>
</ul>
</div>
<nav class="bs-docs-sidebar hidden-print hidden-xs hidden-sm affix" id="affix">
<!-- <p><a class="back-to-top" href="#top">Back to top</a><p> -->
</nav>
</div>
</div>
</div>
</div>
<footer>
<div class="grad-bottom"></div>
<div class="footer">
<div class="container">
<span class="pull-right">
<a href="#top">Back to top</a>
</span>
<span>Generated by <strong>DocFX</strong></span>
</div>
</div>
</footer>
</div>
<script type="text/javascript" src="../styles/docfx.vendor.js"></script>
<script type="text/javascript" src="../styles/docfx.js"></script>
<script type="text/javascript" src="../styles/main.js"></script>
</body>
</html>
<!DOCTYPE html>
<!--[if IE]><![endif]-->
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Namespace Titanium.Web.Proxy.Network.Certificate
| Titanium Web Proxy </title>
<meta name="viewport" content="width=device-width">
<meta name="title" content="Namespace Titanium.Web.Proxy.Network.Certificate
| Titanium Web Proxy ">
<meta name="generator" content="docfx 2.55.0.0">
<link rel="shortcut icon" href="../favicon.ico">
<link rel="stylesheet" href="../styles/docfx.vendor.css">
<link rel="stylesheet" href="../styles/docfx.css">
<link rel="stylesheet" href="../styles/main.css">
<meta property="docfx:navrel" content="">
<meta property="docfx:tocrel" content="toc.html">
<meta property="docfx:rel" content="../">
</head>
<body data-spy="scroll" data-target="#affix" data-offset="120">
<div id="wrapper">
<header>
<nav id="autocollapse" class="navbar navbar-inverse ng-scope" role="navigation">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="../index.html">
<img id="logo" class="svg" src="../logo.svg" alt="">
</a>
</div>
<div class="collapse navbar-collapse" id="navbar">
<form class="navbar-form navbar-right" role="search" id="search">
<div class="form-group">
<input type="text" class="form-control" id="search-query" placeholder="Search" autocomplete="off">
</div>
</form>
</div>
</div>
</nav>
<div class="subnav navbar navbar-default">
<div class="container hide-when-search" id="breadcrumb">
<ul class="breadcrumb">
<li></li>
</ul>
</div>
</div>
</header>
<div class="container body-content">
<div id="search-results">
<div class="search-list"></div>
<div class="sr-items">
<p><i class="glyphicon glyphicon-refresh index-loading"></i></p>
</div>
<ul id="pagination"></ul>
</div>
</div>
<div role="main" class="container body-content hide-when-search">
<div class="sidenav hide-when-search">
<a class="btn toc-toggle collapse" data-toggle="collapse" href="#sidetoggle" aria-expanded="false" aria-controls="sidetoggle">Show / Hide Table of Contents</a>
<div class="sidetoggle collapse" id="sidetoggle">
<div id="sidetoc"></div>
</div>
</div>
<div class="article row grid-right">
<div class="col-md-10">
<article class="content wrap" id="_content" data-uid="Titanium.Web.Proxy.Network.Certificate">
<h1 id="Titanium_Web_Proxy_Network_Certificate" data-uid="Titanium.Web.Proxy.Network.Certificate" class="text-break">Namespace Titanium.Web.Proxy.Network.Certificate
</h1>
<div class="markdown level0 summary"></div>
<div class="markdown level0 conceptual"></div>
<div class="markdown level0 remarks"></div>
<h3 id="enums">Enums
</h3>
<h4><a class="xref" href="Titanium.Web.Proxy.Network.Certificate.AlternativeNameType.html">AlternativeNameType</a></h4>
<section></section>
<h4><a class="xref" href="Titanium.Web.Proxy.Network.Certificate.EncodingType.html">EncodingType</a></h4>
<section></section>
</article>
</div>
<div class="hidden-sm col-md-2" role="complementary">
<div class="sideaffix">
<div class="contribution">
<ul class="nav">
</ul>
</div>
<nav class="bs-docs-sidebar hidden-print hidden-xs hidden-sm affix" id="affix">
<!-- <p><a class="back-to-top" href="#top">Back to top</a><p> -->
</nav>
</div>
</div>
</div>
</div>
<footer>
<div class="grad-bottom"></div>
<div class="footer">
<div class="container">
<span class="pull-right">
<a href="#top">Back to top</a>
</span>
<span>Generated by <strong>DocFX</strong></span>
</div>
</div>
</footer>
</div>
<script type="text/javascript" src="../styles/docfx.vendor.js"></script>
<script type="text/javascript" src="../styles/docfx.js"></script>
<script type="text/javascript" src="../styles/main.js"></script>
</body>
</html>
...@@ -240,6 +240,19 @@ ...@@ -240,6 +240,19 @@
</li> </li>
</ul> </ul>
</li> </li>
<li>
<span class="expand-stub"></span>
<a href="Titanium.Web.Proxy.Network.Certificate.html" name="" title="Titanium.Web.Proxy.Network.Certificate">Titanium.Web.Proxy.Network.Certificate</a>
<ul class="nav level2">
<li>
<a href="Titanium.Web.Proxy.Network.Certificate.AlternativeNameType.html" name="" title="AlternativeNameType">AlternativeNameType</a>
</li>
<li>
<a href="Titanium.Web.Proxy.Network.Certificate.EncodingType.html" name="" title="EncodingType">EncodingType</a>
</li>
</ul>
</li>
<li> <li>
<span class="expand-stub"></span> <span class="expand-stub"></span>
<a href="Titanium.Web.Proxy.StreamExtended.html" name="" title="Titanium.Web.Proxy.StreamExtended">Titanium.Web.Proxy.StreamExtended</a> <a href="Titanium.Web.Proxy.StreamExtended.html" name="" title="Titanium.Web.Proxy.StreamExtended">Titanium.Web.Proxy.StreamExtended</a>
......
...@@ -274,6 +274,21 @@ ...@@ -274,6 +274,21 @@
"title": "Class TransparentProxyEndPoint | Titanium Web Proxy", "title": "Class TransparentProxyEndPoint | Titanium Web Proxy",
"keywords": "Class TransparentProxyEndPoint A proxy end point client is not aware of. Useful when requests are redirected to this proxy end point through port forwarding via router. Inheritance Object ProxyEndPoint TransparentBaseProxyEndPoint TransparentProxyEndPoint Inherited Members ProxyEndPoint.IpAddress ProxyEndPoint.Port ProxyEndPoint.DecryptSsl ProxyEndPoint.GenericCertificate Object.ToString() Object.Equals(Object) Object.Equals(Object, Object) Object.ReferenceEquals(Object, Object) Object.GetHashCode() Object.GetType() Object.MemberwiseClone() Namespace : Titanium.Web.Proxy.Models Assembly : Titanium.Web.Proxy.dll Syntax public class TransparentProxyEndPoint : TransparentBaseProxyEndPoint Constructors | Improve this Doc View Source TransparentProxyEndPoint(IPAddress, Int32, Boolean) Initialize a new instance. Declaration public TransparentProxyEndPoint(IPAddress ipAddress, int port, bool decryptSsl = true) Parameters Type Name Description IPAddress ipAddress Listening Ip address. Int32 port Listening port. Boolean decryptSsl Should we decrypt ssl? Properties | Improve this Doc View Source GenericCertificateName Name of the Certificate need to be sent (same as the hostname we want to proxy). This is valid only when UseServerNameIndication is set to false. Declaration public override string GenericCertificateName { get; set; } Property Value Type Description String Overrides TransparentBaseProxyEndPoint.GenericCertificateName Events | Improve this Doc View Source BeforeSslAuthenticate Before Ssl authentication this event is fired. Declaration public event AsyncEventHandler<BeforeSslAuthenticateEventArgs> BeforeSslAuthenticate Event Type Type Description AsyncEventHandler < BeforeSslAuthenticateEventArgs >" "keywords": "Class TransparentProxyEndPoint A proxy end point client is not aware of. Useful when requests are redirected to this proxy end point through port forwarding via router. Inheritance Object ProxyEndPoint TransparentBaseProxyEndPoint TransparentProxyEndPoint Inherited Members ProxyEndPoint.IpAddress ProxyEndPoint.Port ProxyEndPoint.DecryptSsl ProxyEndPoint.GenericCertificate Object.ToString() Object.Equals(Object) Object.Equals(Object, Object) Object.ReferenceEquals(Object, Object) Object.GetHashCode() Object.GetType() Object.MemberwiseClone() Namespace : Titanium.Web.Proxy.Models Assembly : Titanium.Web.Proxy.dll Syntax public class TransparentProxyEndPoint : TransparentBaseProxyEndPoint Constructors | Improve this Doc View Source TransparentProxyEndPoint(IPAddress, Int32, Boolean) Initialize a new instance. Declaration public TransparentProxyEndPoint(IPAddress ipAddress, int port, bool decryptSsl = true) Parameters Type Name Description IPAddress ipAddress Listening Ip address. Int32 port Listening port. Boolean decryptSsl Should we decrypt ssl? Properties | Improve this Doc View Source GenericCertificateName Name of the Certificate need to be sent (same as the hostname we want to proxy). This is valid only when UseServerNameIndication is set to false. Declaration public override string GenericCertificateName { get; set; } Property Value Type Description String Overrides TransparentBaseProxyEndPoint.GenericCertificateName Events | Improve this Doc View Source BeforeSslAuthenticate Before Ssl authentication this event is fired. Declaration public event AsyncEventHandler<BeforeSslAuthenticateEventArgs> BeforeSslAuthenticate Event Type Type Description AsyncEventHandler < BeforeSslAuthenticateEventArgs >"
}, },
"api/Titanium.Web.Proxy.Network.Certificate.AlternativeNameType.html": {
"href": "api/Titanium.Web.Proxy.Network.Certificate.AlternativeNameType.html",
"title": "Enum AlternativeNameType | Titanium Web Proxy",
"keywords": "Enum AlternativeNameType Namespace : Titanium.Web.Proxy.Network.Certificate Assembly : Titanium.Web.Proxy.dll Syntax public enum AlternativeNameType Fields Name Description XCN_CERT_ALT_NAME_DIRECTORY_NAME XCN_CERT_ALT_NAME_DNS_NAME XCN_CERT_ALT_NAME_GUID XCN_CERT_ALT_NAME_IP_ADDRESS XCN_CERT_ALT_NAME_OTHER_NAME XCN_CERT_ALT_NAME_REGISTERED_ID XCN_CERT_ALT_NAME_RFC822_NAME XCN_CERT_ALT_NAME_UNKNOWN XCN_CERT_ALT_NAME_URL XCN_CERT_ALT_NAME_USER_PRINCIPLE_NAME"
},
"api/Titanium.Web.Proxy.Network.Certificate.EncodingType.html": {
"href": "api/Titanium.Web.Proxy.Network.Certificate.EncodingType.html",
"title": "Enum EncodingType | Titanium Web Proxy",
"keywords": "Enum EncodingType Namespace : Titanium.Web.Proxy.Network.Certificate Assembly : Titanium.Web.Proxy.dll Syntax public enum EncodingType Fields Name Description XCN_CRYPT_STRING_ANY XCN_CRYPT_STRING_BASE64 XCN_CRYPT_STRING_BASE64_ANY XCN_CRYPT_STRING_BASE64HEADER XCN_CRYPT_STRING_BASE64REQUESTHEADER XCN_CRYPT_STRING_BASE64URI XCN_CRYPT_STRING_BASE64X509CRLHEADER XCN_CRYPT_STRING_BINARY XCN_CRYPT_STRING_CHAIN XCN_CRYPT_STRING_ENCODEMASK XCN_CRYPT_STRING_HASHDATA XCN_CRYPT_STRING_HEX XCN_CRYPT_STRING_HEX_ANY XCN_CRYPT_STRING_HEXADDR XCN_CRYPT_STRING_HEXASCII XCN_CRYPT_STRING_HEXASCIIADDR XCN_CRYPT_STRING_HEXRAW XCN_CRYPT_STRING_NOCR XCN_CRYPT_STRING_NOCRLF XCN_CRYPT_STRING_PERCENTESCAPE XCN_CRYPT_STRING_STRICT XCN_CRYPT_STRING_TEXT"
},
"api/Titanium.Web.Proxy.Network.Certificate.html": {
"href": "api/Titanium.Web.Proxy.Network.Certificate.html",
"title": "Namespace Titanium.Web.Proxy.Network.Certificate | Titanium Web Proxy",
"keywords": "Namespace Titanium.Web.Proxy.Network.Certificate Enums AlternativeNameType EncodingType"
},
"api/Titanium.Web.Proxy.Network.CertificateEngine.html": { "api/Titanium.Web.Proxy.Network.CertificateEngine.html": {
"href": "api/Titanium.Web.Proxy.Network.CertificateEngine.html", "href": "api/Titanium.Web.Proxy.Network.CertificateEngine.html",
"title": "Enum CertificateEngine | Titanium Web Proxy", "title": "Enum CertificateEngine | Titanium Web Proxy",
......
...@@ -3268,6 +3268,216 @@ references: ...@@ -3268,6 +3268,216 @@ references:
commentId: N:Titanium.Web.Proxy.Network commentId: N:Titanium.Web.Proxy.Network
fullName: Titanium.Web.Proxy.Network fullName: Titanium.Web.Proxy.Network
nameWithType: Titanium.Web.Proxy.Network nameWithType: Titanium.Web.Proxy.Network
- uid: Titanium.Web.Proxy.Network.Certificate
name: Titanium.Web.Proxy.Network.Certificate
href: api/Titanium.Web.Proxy.Network.Certificate.html
commentId: N:Titanium.Web.Proxy.Network.Certificate
fullName: Titanium.Web.Proxy.Network.Certificate
nameWithType: Titanium.Web.Proxy.Network.Certificate
- uid: Titanium.Web.Proxy.Network.Certificate.AlternativeNameType
name: AlternativeNameType
href: api/Titanium.Web.Proxy.Network.Certificate.AlternativeNameType.html
commentId: T:Titanium.Web.Proxy.Network.Certificate.AlternativeNameType
fullName: Titanium.Web.Proxy.Network.Certificate.AlternativeNameType
nameWithType: AlternativeNameType
- uid: Titanium.Web.Proxy.Network.Certificate.AlternativeNameType.XCN_CERT_ALT_NAME_DIRECTORY_NAME
name: XCN_CERT_ALT_NAME_DIRECTORY_NAME
href: api/Titanium.Web.Proxy.Network.Certificate.AlternativeNameType.html#Titanium_Web_Proxy_Network_Certificate_AlternativeNameType_XCN_CERT_ALT_NAME_DIRECTORY_NAME
commentId: F:Titanium.Web.Proxy.Network.Certificate.AlternativeNameType.XCN_CERT_ALT_NAME_DIRECTORY_NAME
fullName: Titanium.Web.Proxy.Network.Certificate.AlternativeNameType.XCN_CERT_ALT_NAME_DIRECTORY_NAME
nameWithType: AlternativeNameType.XCN_CERT_ALT_NAME_DIRECTORY_NAME
- uid: Titanium.Web.Proxy.Network.Certificate.AlternativeNameType.XCN_CERT_ALT_NAME_DNS_NAME
name: XCN_CERT_ALT_NAME_DNS_NAME
href: api/Titanium.Web.Proxy.Network.Certificate.AlternativeNameType.html#Titanium_Web_Proxy_Network_Certificate_AlternativeNameType_XCN_CERT_ALT_NAME_DNS_NAME
commentId: F:Titanium.Web.Proxy.Network.Certificate.AlternativeNameType.XCN_CERT_ALT_NAME_DNS_NAME
fullName: Titanium.Web.Proxy.Network.Certificate.AlternativeNameType.XCN_CERT_ALT_NAME_DNS_NAME
nameWithType: AlternativeNameType.XCN_CERT_ALT_NAME_DNS_NAME
- uid: Titanium.Web.Proxy.Network.Certificate.AlternativeNameType.XCN_CERT_ALT_NAME_GUID
name: XCN_CERT_ALT_NAME_GUID
href: api/Titanium.Web.Proxy.Network.Certificate.AlternativeNameType.html#Titanium_Web_Proxy_Network_Certificate_AlternativeNameType_XCN_CERT_ALT_NAME_GUID
commentId: F:Titanium.Web.Proxy.Network.Certificate.AlternativeNameType.XCN_CERT_ALT_NAME_GUID
fullName: Titanium.Web.Proxy.Network.Certificate.AlternativeNameType.XCN_CERT_ALT_NAME_GUID
nameWithType: AlternativeNameType.XCN_CERT_ALT_NAME_GUID
- uid: Titanium.Web.Proxy.Network.Certificate.AlternativeNameType.XCN_CERT_ALT_NAME_IP_ADDRESS
name: XCN_CERT_ALT_NAME_IP_ADDRESS
href: api/Titanium.Web.Proxy.Network.Certificate.AlternativeNameType.html#Titanium_Web_Proxy_Network_Certificate_AlternativeNameType_XCN_CERT_ALT_NAME_IP_ADDRESS
commentId: F:Titanium.Web.Proxy.Network.Certificate.AlternativeNameType.XCN_CERT_ALT_NAME_IP_ADDRESS
fullName: Titanium.Web.Proxy.Network.Certificate.AlternativeNameType.XCN_CERT_ALT_NAME_IP_ADDRESS
nameWithType: AlternativeNameType.XCN_CERT_ALT_NAME_IP_ADDRESS
- uid: Titanium.Web.Proxy.Network.Certificate.AlternativeNameType.XCN_CERT_ALT_NAME_OTHER_NAME
name: XCN_CERT_ALT_NAME_OTHER_NAME
href: api/Titanium.Web.Proxy.Network.Certificate.AlternativeNameType.html#Titanium_Web_Proxy_Network_Certificate_AlternativeNameType_XCN_CERT_ALT_NAME_OTHER_NAME
commentId: F:Titanium.Web.Proxy.Network.Certificate.AlternativeNameType.XCN_CERT_ALT_NAME_OTHER_NAME
fullName: Titanium.Web.Proxy.Network.Certificate.AlternativeNameType.XCN_CERT_ALT_NAME_OTHER_NAME
nameWithType: AlternativeNameType.XCN_CERT_ALT_NAME_OTHER_NAME
- uid: Titanium.Web.Proxy.Network.Certificate.AlternativeNameType.XCN_CERT_ALT_NAME_REGISTERED_ID
name: XCN_CERT_ALT_NAME_REGISTERED_ID
href: api/Titanium.Web.Proxy.Network.Certificate.AlternativeNameType.html#Titanium_Web_Proxy_Network_Certificate_AlternativeNameType_XCN_CERT_ALT_NAME_REGISTERED_ID
commentId: F:Titanium.Web.Proxy.Network.Certificate.AlternativeNameType.XCN_CERT_ALT_NAME_REGISTERED_ID
fullName: Titanium.Web.Proxy.Network.Certificate.AlternativeNameType.XCN_CERT_ALT_NAME_REGISTERED_ID
nameWithType: AlternativeNameType.XCN_CERT_ALT_NAME_REGISTERED_ID
- uid: Titanium.Web.Proxy.Network.Certificate.AlternativeNameType.XCN_CERT_ALT_NAME_RFC822_NAME
name: XCN_CERT_ALT_NAME_RFC822_NAME
href: api/Titanium.Web.Proxy.Network.Certificate.AlternativeNameType.html#Titanium_Web_Proxy_Network_Certificate_AlternativeNameType_XCN_CERT_ALT_NAME_RFC822_NAME
commentId: F:Titanium.Web.Proxy.Network.Certificate.AlternativeNameType.XCN_CERT_ALT_NAME_RFC822_NAME
fullName: Titanium.Web.Proxy.Network.Certificate.AlternativeNameType.XCN_CERT_ALT_NAME_RFC822_NAME
nameWithType: AlternativeNameType.XCN_CERT_ALT_NAME_RFC822_NAME
- uid: Titanium.Web.Proxy.Network.Certificate.AlternativeNameType.XCN_CERT_ALT_NAME_UNKNOWN
name: XCN_CERT_ALT_NAME_UNKNOWN
href: api/Titanium.Web.Proxy.Network.Certificate.AlternativeNameType.html#Titanium_Web_Proxy_Network_Certificate_AlternativeNameType_XCN_CERT_ALT_NAME_UNKNOWN
commentId: F:Titanium.Web.Proxy.Network.Certificate.AlternativeNameType.XCN_CERT_ALT_NAME_UNKNOWN
fullName: Titanium.Web.Proxy.Network.Certificate.AlternativeNameType.XCN_CERT_ALT_NAME_UNKNOWN
nameWithType: AlternativeNameType.XCN_CERT_ALT_NAME_UNKNOWN
- uid: Titanium.Web.Proxy.Network.Certificate.AlternativeNameType.XCN_CERT_ALT_NAME_URL
name: XCN_CERT_ALT_NAME_URL
href: api/Titanium.Web.Proxy.Network.Certificate.AlternativeNameType.html#Titanium_Web_Proxy_Network_Certificate_AlternativeNameType_XCN_CERT_ALT_NAME_URL
commentId: F:Titanium.Web.Proxy.Network.Certificate.AlternativeNameType.XCN_CERT_ALT_NAME_URL
fullName: Titanium.Web.Proxy.Network.Certificate.AlternativeNameType.XCN_CERT_ALT_NAME_URL
nameWithType: AlternativeNameType.XCN_CERT_ALT_NAME_URL
- uid: Titanium.Web.Proxy.Network.Certificate.AlternativeNameType.XCN_CERT_ALT_NAME_USER_PRINCIPLE_NAME
name: XCN_CERT_ALT_NAME_USER_PRINCIPLE_NAME
href: api/Titanium.Web.Proxy.Network.Certificate.AlternativeNameType.html#Titanium_Web_Proxy_Network_Certificate_AlternativeNameType_XCN_CERT_ALT_NAME_USER_PRINCIPLE_NAME
commentId: F:Titanium.Web.Proxy.Network.Certificate.AlternativeNameType.XCN_CERT_ALT_NAME_USER_PRINCIPLE_NAME
fullName: Titanium.Web.Proxy.Network.Certificate.AlternativeNameType.XCN_CERT_ALT_NAME_USER_PRINCIPLE_NAME
nameWithType: AlternativeNameType.XCN_CERT_ALT_NAME_USER_PRINCIPLE_NAME
- uid: Titanium.Web.Proxy.Network.Certificate.EncodingType
name: EncodingType
href: api/Titanium.Web.Proxy.Network.Certificate.EncodingType.html
commentId: T:Titanium.Web.Proxy.Network.Certificate.EncodingType
fullName: Titanium.Web.Proxy.Network.Certificate.EncodingType
nameWithType: EncodingType
- uid: Titanium.Web.Proxy.Network.Certificate.EncodingType.XCN_CRYPT_STRING_ANY
name: XCN_CRYPT_STRING_ANY
href: api/Titanium.Web.Proxy.Network.Certificate.EncodingType.html#Titanium_Web_Proxy_Network_Certificate_EncodingType_XCN_CRYPT_STRING_ANY
commentId: F:Titanium.Web.Proxy.Network.Certificate.EncodingType.XCN_CRYPT_STRING_ANY
fullName: Titanium.Web.Proxy.Network.Certificate.EncodingType.XCN_CRYPT_STRING_ANY
nameWithType: EncodingType.XCN_CRYPT_STRING_ANY
- uid: Titanium.Web.Proxy.Network.Certificate.EncodingType.XCN_CRYPT_STRING_BASE64
name: XCN_CRYPT_STRING_BASE64
href: api/Titanium.Web.Proxy.Network.Certificate.EncodingType.html#Titanium_Web_Proxy_Network_Certificate_EncodingType_XCN_CRYPT_STRING_BASE64
commentId: F:Titanium.Web.Proxy.Network.Certificate.EncodingType.XCN_CRYPT_STRING_BASE64
fullName: Titanium.Web.Proxy.Network.Certificate.EncodingType.XCN_CRYPT_STRING_BASE64
nameWithType: EncodingType.XCN_CRYPT_STRING_BASE64
- uid: Titanium.Web.Proxy.Network.Certificate.EncodingType.XCN_CRYPT_STRING_BASE64_ANY
name: XCN_CRYPT_STRING_BASE64_ANY
href: api/Titanium.Web.Proxy.Network.Certificate.EncodingType.html#Titanium_Web_Proxy_Network_Certificate_EncodingType_XCN_CRYPT_STRING_BASE64_ANY
commentId: F:Titanium.Web.Proxy.Network.Certificate.EncodingType.XCN_CRYPT_STRING_BASE64_ANY
fullName: Titanium.Web.Proxy.Network.Certificate.EncodingType.XCN_CRYPT_STRING_BASE64_ANY
nameWithType: EncodingType.XCN_CRYPT_STRING_BASE64_ANY
- uid: Titanium.Web.Proxy.Network.Certificate.EncodingType.XCN_CRYPT_STRING_BASE64HEADER
name: XCN_CRYPT_STRING_BASE64HEADER
href: api/Titanium.Web.Proxy.Network.Certificate.EncodingType.html#Titanium_Web_Proxy_Network_Certificate_EncodingType_XCN_CRYPT_STRING_BASE64HEADER
commentId: F:Titanium.Web.Proxy.Network.Certificate.EncodingType.XCN_CRYPT_STRING_BASE64HEADER
fullName: Titanium.Web.Proxy.Network.Certificate.EncodingType.XCN_CRYPT_STRING_BASE64HEADER
nameWithType: EncodingType.XCN_CRYPT_STRING_BASE64HEADER
- uid: Titanium.Web.Proxy.Network.Certificate.EncodingType.XCN_CRYPT_STRING_BASE64REQUESTHEADER
name: XCN_CRYPT_STRING_BASE64REQUESTHEADER
href: api/Titanium.Web.Proxy.Network.Certificate.EncodingType.html#Titanium_Web_Proxy_Network_Certificate_EncodingType_XCN_CRYPT_STRING_BASE64REQUESTHEADER
commentId: F:Titanium.Web.Proxy.Network.Certificate.EncodingType.XCN_CRYPT_STRING_BASE64REQUESTHEADER
fullName: Titanium.Web.Proxy.Network.Certificate.EncodingType.XCN_CRYPT_STRING_BASE64REQUESTHEADER
nameWithType: EncodingType.XCN_CRYPT_STRING_BASE64REQUESTHEADER
- uid: Titanium.Web.Proxy.Network.Certificate.EncodingType.XCN_CRYPT_STRING_BASE64URI
name: XCN_CRYPT_STRING_BASE64URI
href: api/Titanium.Web.Proxy.Network.Certificate.EncodingType.html#Titanium_Web_Proxy_Network_Certificate_EncodingType_XCN_CRYPT_STRING_BASE64URI
commentId: F:Titanium.Web.Proxy.Network.Certificate.EncodingType.XCN_CRYPT_STRING_BASE64URI
fullName: Titanium.Web.Proxy.Network.Certificate.EncodingType.XCN_CRYPT_STRING_BASE64URI
nameWithType: EncodingType.XCN_CRYPT_STRING_BASE64URI
- uid: Titanium.Web.Proxy.Network.Certificate.EncodingType.XCN_CRYPT_STRING_BASE64X509CRLHEADER
name: XCN_CRYPT_STRING_BASE64X509CRLHEADER
href: api/Titanium.Web.Proxy.Network.Certificate.EncodingType.html#Titanium_Web_Proxy_Network_Certificate_EncodingType_XCN_CRYPT_STRING_BASE64X509CRLHEADER
commentId: F:Titanium.Web.Proxy.Network.Certificate.EncodingType.XCN_CRYPT_STRING_BASE64X509CRLHEADER
fullName: Titanium.Web.Proxy.Network.Certificate.EncodingType.XCN_CRYPT_STRING_BASE64X509CRLHEADER
nameWithType: EncodingType.XCN_CRYPT_STRING_BASE64X509CRLHEADER
- uid: Titanium.Web.Proxy.Network.Certificate.EncodingType.XCN_CRYPT_STRING_BINARY
name: XCN_CRYPT_STRING_BINARY
href: api/Titanium.Web.Proxy.Network.Certificate.EncodingType.html#Titanium_Web_Proxy_Network_Certificate_EncodingType_XCN_CRYPT_STRING_BINARY
commentId: F:Titanium.Web.Proxy.Network.Certificate.EncodingType.XCN_CRYPT_STRING_BINARY
fullName: Titanium.Web.Proxy.Network.Certificate.EncodingType.XCN_CRYPT_STRING_BINARY
nameWithType: EncodingType.XCN_CRYPT_STRING_BINARY
- uid: Titanium.Web.Proxy.Network.Certificate.EncodingType.XCN_CRYPT_STRING_CHAIN
name: XCN_CRYPT_STRING_CHAIN
href: api/Titanium.Web.Proxy.Network.Certificate.EncodingType.html#Titanium_Web_Proxy_Network_Certificate_EncodingType_XCN_CRYPT_STRING_CHAIN
commentId: F:Titanium.Web.Proxy.Network.Certificate.EncodingType.XCN_CRYPT_STRING_CHAIN
fullName: Titanium.Web.Proxy.Network.Certificate.EncodingType.XCN_CRYPT_STRING_CHAIN
nameWithType: EncodingType.XCN_CRYPT_STRING_CHAIN
- uid: Titanium.Web.Proxy.Network.Certificate.EncodingType.XCN_CRYPT_STRING_ENCODEMASK
name: XCN_CRYPT_STRING_ENCODEMASK
href: api/Titanium.Web.Proxy.Network.Certificate.EncodingType.html#Titanium_Web_Proxy_Network_Certificate_EncodingType_XCN_CRYPT_STRING_ENCODEMASK
commentId: F:Titanium.Web.Proxy.Network.Certificate.EncodingType.XCN_CRYPT_STRING_ENCODEMASK
fullName: Titanium.Web.Proxy.Network.Certificate.EncodingType.XCN_CRYPT_STRING_ENCODEMASK
nameWithType: EncodingType.XCN_CRYPT_STRING_ENCODEMASK
- uid: Titanium.Web.Proxy.Network.Certificate.EncodingType.XCN_CRYPT_STRING_HASHDATA
name: XCN_CRYPT_STRING_HASHDATA
href: api/Titanium.Web.Proxy.Network.Certificate.EncodingType.html#Titanium_Web_Proxy_Network_Certificate_EncodingType_XCN_CRYPT_STRING_HASHDATA
commentId: F:Titanium.Web.Proxy.Network.Certificate.EncodingType.XCN_CRYPT_STRING_HASHDATA
fullName: Titanium.Web.Proxy.Network.Certificate.EncodingType.XCN_CRYPT_STRING_HASHDATA
nameWithType: EncodingType.XCN_CRYPT_STRING_HASHDATA
- uid: Titanium.Web.Proxy.Network.Certificate.EncodingType.XCN_CRYPT_STRING_HEX
name: XCN_CRYPT_STRING_HEX
href: api/Titanium.Web.Proxy.Network.Certificate.EncodingType.html#Titanium_Web_Proxy_Network_Certificate_EncodingType_XCN_CRYPT_STRING_HEX
commentId: F:Titanium.Web.Proxy.Network.Certificate.EncodingType.XCN_CRYPT_STRING_HEX
fullName: Titanium.Web.Proxy.Network.Certificate.EncodingType.XCN_CRYPT_STRING_HEX
nameWithType: EncodingType.XCN_CRYPT_STRING_HEX
- uid: Titanium.Web.Proxy.Network.Certificate.EncodingType.XCN_CRYPT_STRING_HEX_ANY
name: XCN_CRYPT_STRING_HEX_ANY
href: api/Titanium.Web.Proxy.Network.Certificate.EncodingType.html#Titanium_Web_Proxy_Network_Certificate_EncodingType_XCN_CRYPT_STRING_HEX_ANY
commentId: F:Titanium.Web.Proxy.Network.Certificate.EncodingType.XCN_CRYPT_STRING_HEX_ANY
fullName: Titanium.Web.Proxy.Network.Certificate.EncodingType.XCN_CRYPT_STRING_HEX_ANY
nameWithType: EncodingType.XCN_CRYPT_STRING_HEX_ANY
- uid: Titanium.Web.Proxy.Network.Certificate.EncodingType.XCN_CRYPT_STRING_HEXADDR
name: XCN_CRYPT_STRING_HEXADDR
href: api/Titanium.Web.Proxy.Network.Certificate.EncodingType.html#Titanium_Web_Proxy_Network_Certificate_EncodingType_XCN_CRYPT_STRING_HEXADDR
commentId: F:Titanium.Web.Proxy.Network.Certificate.EncodingType.XCN_CRYPT_STRING_HEXADDR
fullName: Titanium.Web.Proxy.Network.Certificate.EncodingType.XCN_CRYPT_STRING_HEXADDR
nameWithType: EncodingType.XCN_CRYPT_STRING_HEXADDR
- uid: Titanium.Web.Proxy.Network.Certificate.EncodingType.XCN_CRYPT_STRING_HEXASCII
name: XCN_CRYPT_STRING_HEXASCII
href: api/Titanium.Web.Proxy.Network.Certificate.EncodingType.html#Titanium_Web_Proxy_Network_Certificate_EncodingType_XCN_CRYPT_STRING_HEXASCII
commentId: F:Titanium.Web.Proxy.Network.Certificate.EncodingType.XCN_CRYPT_STRING_HEXASCII
fullName: Titanium.Web.Proxy.Network.Certificate.EncodingType.XCN_CRYPT_STRING_HEXASCII
nameWithType: EncodingType.XCN_CRYPT_STRING_HEXASCII
- uid: Titanium.Web.Proxy.Network.Certificate.EncodingType.XCN_CRYPT_STRING_HEXASCIIADDR
name: XCN_CRYPT_STRING_HEXASCIIADDR
href: api/Titanium.Web.Proxy.Network.Certificate.EncodingType.html#Titanium_Web_Proxy_Network_Certificate_EncodingType_XCN_CRYPT_STRING_HEXASCIIADDR
commentId: F:Titanium.Web.Proxy.Network.Certificate.EncodingType.XCN_CRYPT_STRING_HEXASCIIADDR
fullName: Titanium.Web.Proxy.Network.Certificate.EncodingType.XCN_CRYPT_STRING_HEXASCIIADDR
nameWithType: EncodingType.XCN_CRYPT_STRING_HEXASCIIADDR
- uid: Titanium.Web.Proxy.Network.Certificate.EncodingType.XCN_CRYPT_STRING_HEXRAW
name: XCN_CRYPT_STRING_HEXRAW
href: api/Titanium.Web.Proxy.Network.Certificate.EncodingType.html#Titanium_Web_Proxy_Network_Certificate_EncodingType_XCN_CRYPT_STRING_HEXRAW
commentId: F:Titanium.Web.Proxy.Network.Certificate.EncodingType.XCN_CRYPT_STRING_HEXRAW
fullName: Titanium.Web.Proxy.Network.Certificate.EncodingType.XCN_CRYPT_STRING_HEXRAW
nameWithType: EncodingType.XCN_CRYPT_STRING_HEXRAW
- uid: Titanium.Web.Proxy.Network.Certificate.EncodingType.XCN_CRYPT_STRING_NOCR
name: XCN_CRYPT_STRING_NOCR
href: api/Titanium.Web.Proxy.Network.Certificate.EncodingType.html#Titanium_Web_Proxy_Network_Certificate_EncodingType_XCN_CRYPT_STRING_NOCR
commentId: F:Titanium.Web.Proxy.Network.Certificate.EncodingType.XCN_CRYPT_STRING_NOCR
fullName: Titanium.Web.Proxy.Network.Certificate.EncodingType.XCN_CRYPT_STRING_NOCR
nameWithType: EncodingType.XCN_CRYPT_STRING_NOCR
- uid: Titanium.Web.Proxy.Network.Certificate.EncodingType.XCN_CRYPT_STRING_NOCRLF
name: XCN_CRYPT_STRING_NOCRLF
href: api/Titanium.Web.Proxy.Network.Certificate.EncodingType.html#Titanium_Web_Proxy_Network_Certificate_EncodingType_XCN_CRYPT_STRING_NOCRLF
commentId: F:Titanium.Web.Proxy.Network.Certificate.EncodingType.XCN_CRYPT_STRING_NOCRLF
fullName: Titanium.Web.Proxy.Network.Certificate.EncodingType.XCN_CRYPT_STRING_NOCRLF
nameWithType: EncodingType.XCN_CRYPT_STRING_NOCRLF
- uid: Titanium.Web.Proxy.Network.Certificate.EncodingType.XCN_CRYPT_STRING_PERCENTESCAPE
name: XCN_CRYPT_STRING_PERCENTESCAPE
href: api/Titanium.Web.Proxy.Network.Certificate.EncodingType.html#Titanium_Web_Proxy_Network_Certificate_EncodingType_XCN_CRYPT_STRING_PERCENTESCAPE
commentId: F:Titanium.Web.Proxy.Network.Certificate.EncodingType.XCN_CRYPT_STRING_PERCENTESCAPE
fullName: Titanium.Web.Proxy.Network.Certificate.EncodingType.XCN_CRYPT_STRING_PERCENTESCAPE
nameWithType: EncodingType.XCN_CRYPT_STRING_PERCENTESCAPE
- uid: Titanium.Web.Proxy.Network.Certificate.EncodingType.XCN_CRYPT_STRING_STRICT
name: XCN_CRYPT_STRING_STRICT
href: api/Titanium.Web.Proxy.Network.Certificate.EncodingType.html#Titanium_Web_Proxy_Network_Certificate_EncodingType_XCN_CRYPT_STRING_STRICT
commentId: F:Titanium.Web.Proxy.Network.Certificate.EncodingType.XCN_CRYPT_STRING_STRICT
fullName: Titanium.Web.Proxy.Network.Certificate.EncodingType.XCN_CRYPT_STRING_STRICT
nameWithType: EncodingType.XCN_CRYPT_STRING_STRICT
- uid: Titanium.Web.Proxy.Network.Certificate.EncodingType.XCN_CRYPT_STRING_TEXT
name: XCN_CRYPT_STRING_TEXT
href: api/Titanium.Web.Proxy.Network.Certificate.EncodingType.html#Titanium_Web_Proxy_Network_Certificate_EncodingType_XCN_CRYPT_STRING_TEXT
commentId: F:Titanium.Web.Proxy.Network.Certificate.EncodingType.XCN_CRYPT_STRING_TEXT
fullName: Titanium.Web.Proxy.Network.Certificate.EncodingType.XCN_CRYPT_STRING_TEXT
nameWithType: EncodingType.XCN_CRYPT_STRING_TEXT
- uid: Titanium.Web.Proxy.Network.CertificateEngine - uid: Titanium.Web.Proxy.Network.CertificateEngine
name: CertificateEngine name: CertificateEngine
href: api/Titanium.Web.Proxy.Network.CertificateEngine.html href: api/Titanium.Web.Proxy.Network.CertificateEngine.html
......
using System; using System;
using System.IO; using System.IO;
using System.Security.Cryptography.X509Certificates; using System.Net;
using Org.BouncyCastle.Asn1; using System.Security.Cryptography.X509Certificates;
using Org.BouncyCastle.Asn1.Pkcs; using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.X509; using Org.BouncyCastle.Asn1.Pkcs;
using Org.BouncyCastle.Crypto; using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Crypto.Generators; using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Operators; using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Crypto.Operators;
using Org.BouncyCastle.Crypto.Prng; using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Math; using Org.BouncyCastle.Crypto.Prng;
using Org.BouncyCastle.OpenSsl; using Org.BouncyCastle.Math;
using Org.BouncyCastle.Pkcs; using Org.BouncyCastle.OpenSsl;
using Org.BouncyCastle.Security; using Org.BouncyCastle.Pkcs;
using Org.BouncyCastle.Utilities; using Org.BouncyCastle.Security;
using Org.BouncyCastle.X509; using Org.BouncyCastle.Utilities;
using Titanium.Web.Proxy.Helpers; using Org.BouncyCastle.X509;
using Titanium.Web.Proxy.Shared; using Titanium.Web.Proxy.Helpers;
using X509Certificate = Org.BouncyCastle.X509.X509Certificate; using Titanium.Web.Proxy.Shared;
using X509Certificate = Org.BouncyCastle.X509.X509Certificate;
namespace Titanium.Web.Proxy.Network.Certificate
{ namespace Titanium.Web.Proxy.Network.Certificate
/// <summary> {
/// Implements certificate generation operations. /// <summary>
/// </summary> /// Implements certificate generation operations.
internal class BCCertificateMaker : ICertificateMaker /// </summary>
{ internal class BCCertificateMaker : ICertificateMaker
private readonly int certificateValidDays; {
private const int certificateGraceDays = 366; private readonly int certificateValidDays;
private const int certificateGraceDays = 366;
// The FriendlyName value cannot be set on Unix.
// Set this flag to true when exception detected to avoid further exceptions // The FriendlyName value cannot be set on Unix.
private static bool doNotSetFriendlyName; // Set this flag to true when exception detected to avoid further exceptions
private static bool doNotSetFriendlyName;
private readonly ExceptionHandler exceptionFunc;
private readonly ExceptionHandler exceptionFunc;
internal BCCertificateMaker(ExceptionHandler exceptionFunc, int certificateValidDays)
{ internal BCCertificateMaker(ExceptionHandler exceptionFunc, int certificateValidDays)
this.certificateValidDays = certificateValidDays; {
this.exceptionFunc = exceptionFunc; this.certificateValidDays = certificateValidDays;
} this.exceptionFunc = exceptionFunc;
}
/// <summary>
/// Makes the certificate. /// <summary>
/// </summary> /// Makes the certificate.
/// <param name="sSubjectCn">The s subject cn.</param> /// </summary>
/// <param name="signingCert">The signing cert.</param> /// <param name="sSubjectCn">The s subject cn.</param>
/// <returns>X509Certificate2 instance.</returns> /// <param name="signingCert">The signing cert.</param>
public X509Certificate2 MakeCertificate(string sSubjectCn, X509Certificate2? signingCert = null) /// <returns>X509Certificate2 instance.</returns>
{ public X509Certificate2 MakeCertificate(string sSubjectCn, X509Certificate2? signingCert = null)
return makeCertificateInternal(sSubjectCn, true, signingCert); {
} return makeCertificateInternal(sSubjectCn, true, signingCert);
}
/// <summary>
/// Generates the certificate. /// <summary>
/// </summary> /// Generates the certificate.
/// <param name="subjectName">Name of the subject.</param> /// </summary>
/// <param name="issuerName">Name of the issuer.</param> /// <param name="subjectName">Name of the subject.</param>
/// <param name="validFrom">The valid from.</param> /// <param name="issuerName">Name of the issuer.</param>
/// <param name="validTo">The valid to.</param> /// <param name="validFrom">The valid from.</param>
/// <param name="keyStrength">The key strength.</param> /// <param name="validTo">The valid to.</param>
/// <param name="signatureAlgorithm">The signature algorithm.</param> /// <param name="keyStrength">The key strength.</param>
/// <param name="issuerPrivateKey">The issuer private key.</param> /// <param name="signatureAlgorithm">The signature algorithm.</param>
/// <param name="hostName">The host name</param> /// <param name="issuerPrivateKey">The issuer private key.</param>
/// <returns>X509Certificate2 instance.</returns> /// <param name="hostName">The host name</param>
/// <exception cref="PemException">Malformed sequence in RSA private key</exception> /// <returns>X509Certificate2 instance.</returns>
private static X509Certificate2 generateCertificate(string? hostName, /// <exception cref="PemException">Malformed sequence in RSA private key</exception>
string subjectName, private static X509Certificate2 generateCertificate(string? hostName,
string issuerName, DateTime validFrom, string subjectName,
DateTime validTo, int keyStrength = 2048, string issuerName, DateTime validFrom,
string signatureAlgorithm = "SHA256WithRSA", DateTime validTo, int keyStrength = 2048,
AsymmetricKeyParameter? issuerPrivateKey = null) string signatureAlgorithm = "SHA256WithRSA",
{ AsymmetricKeyParameter? issuerPrivateKey = null)
// Generating Random Numbers {
var randomGenerator = new CryptoApiRandomGenerator(); // Generating Random Numbers
var secureRandom = new SecureRandom(randomGenerator); var randomGenerator = new CryptoApiRandomGenerator();
var secureRandom = new SecureRandom(randomGenerator);
// The Certificate Generator
var certificateGenerator = new X509V3CertificateGenerator(); // The Certificate Generator
var certificateGenerator = new X509V3CertificateGenerator();
// Serial Number
var serialNumber = // Serial Number
BigIntegers.CreateRandomInRange(BigInteger.One, BigInteger.ValueOf(long.MaxValue), secureRandom); var serialNumber =
certificateGenerator.SetSerialNumber(serialNumber); BigIntegers.CreateRandomInRange(BigInteger.One, BigInteger.ValueOf(long.MaxValue), secureRandom);
certificateGenerator.SetSerialNumber(serialNumber);
// Issuer and Subject Name
var subjectDn = new X509Name(subjectName); // Issuer and Subject Name
var issuerDn = new X509Name(issuerName); var subjectDn = new X509Name(subjectName);
certificateGenerator.SetIssuerDN(issuerDn); var issuerDn = new X509Name(issuerName);
certificateGenerator.SetSubjectDN(subjectDn); certificateGenerator.SetIssuerDN(issuerDn);
certificateGenerator.SetSubjectDN(subjectDn);
certificateGenerator.SetNotBefore(validFrom);
certificateGenerator.SetNotAfter(validTo); certificateGenerator.SetNotBefore(validFrom);
certificateGenerator.SetNotAfter(validTo);
if (hostName != null)
{ if (hostName != null)
// add subject alternative names {
var subjectAlternativeNames = new Asn1Encodable[] { new GeneralName(GeneralName.DnsName, hostName) }; // add subject alternative names
var nameType = GeneralName.DnsName;
var subjectAlternativeNamesExtension = new DerSequence(subjectAlternativeNames); if (IPAddress.TryParse(hostName, out _))
certificateGenerator.AddExtension(X509Extensions.SubjectAlternativeName.Id, false, {
subjectAlternativeNamesExtension); nameType = GeneralName.IPAddress;
} }
// Subject Public Key var subjectAlternativeNames = new Asn1Encodable[] { new GeneralName(nameType, hostName) };
var keyGenerationParameters = new KeyGenerationParameters(secureRandom, keyStrength);
var keyPairGenerator = new RsaKeyPairGenerator(); var subjectAlternativeNamesExtension = new DerSequence(subjectAlternativeNames);
keyPairGenerator.Init(keyGenerationParameters); certificateGenerator.AddExtension(X509Extensions.SubjectAlternativeName.Id, false,
var subjectKeyPair = keyPairGenerator.GenerateKeyPair(); subjectAlternativeNamesExtension);
}
certificateGenerator.SetPublicKey(subjectKeyPair.Public);
// Subject Public Key
// Set certificate intended purposes to only Server Authentication var keyGenerationParameters = new KeyGenerationParameters(secureRandom, keyStrength);
certificateGenerator.AddExtension(X509Extensions.ExtendedKeyUsage.Id, false, var keyPairGenerator = new RsaKeyPairGenerator();
new ExtendedKeyUsage(KeyPurposeID.IdKPServerAuth)); keyPairGenerator.Init(keyGenerationParameters);
if (issuerPrivateKey == null) var subjectKeyPair = keyPairGenerator.GenerateKeyPair();
{
certificateGenerator.AddExtension(X509Extensions.BasicConstraints.Id, true, new BasicConstraints(true)); certificateGenerator.SetPublicKey(subjectKeyPair.Public);
}
// Set certificate intended purposes to only Server Authentication
var signatureFactory = new Asn1SignatureFactory(signatureAlgorithm, certificateGenerator.AddExtension(X509Extensions.ExtendedKeyUsage.Id, false,
issuerPrivateKey ?? subjectKeyPair.Private, secureRandom); new ExtendedKeyUsage(KeyPurposeID.IdKPServerAuth));
if (issuerPrivateKey == null)
// Self-sign the certificate {
var certificate = certificateGenerator.Generate(signatureFactory); certificateGenerator.AddExtension(X509Extensions.BasicConstraints.Id, true, new BasicConstraints(true));
}
// Corresponding private key
var privateKeyInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(subjectKeyPair.Private); var signatureFactory = new Asn1SignatureFactory(signatureAlgorithm,
issuerPrivateKey ?? subjectKeyPair.Private, secureRandom);
var seq = (Asn1Sequence)Asn1Object.FromByteArray(privateKeyInfo.ParsePrivateKey().GetDerEncoded());
// Self-sign the certificate
if (seq.Count != 9) var certificate = certificateGenerator.Generate(signatureFactory);
{
throw new PemException("Malformed sequence in RSA private key"); // Corresponding private key
} var privateKeyInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(subjectKeyPair.Private);
var rsa = RsaPrivateKeyStructure.GetInstance(seq); var seq = (Asn1Sequence)Asn1Object.FromByteArray(privateKeyInfo.ParsePrivateKey().GetDerEncoded());
var rsaparams = new RsaPrivateCrtKeyParameters(rsa.Modulus, rsa.PublicExponent, rsa.PrivateExponent,
rsa.Prime1, rsa.Prime2, rsa.Exponent1, if (seq.Count != 9)
rsa.Exponent2, rsa.Coefficient); {
throw new PemException("Malformed sequence in RSA private key");
// Set private key onto certificate instance }
var x509Certificate = withPrivateKey(certificate, rsaparams);
var rsa = RsaPrivateKeyStructure.GetInstance(seq);
if (!doNotSetFriendlyName) var rsaparams = new RsaPrivateCrtKeyParameters(rsa.Modulus, rsa.PublicExponent, rsa.PrivateExponent,
{ rsa.Prime1, rsa.Prime2, rsa.Exponent1,
try rsa.Exponent2, rsa.Coefficient);
{
x509Certificate.FriendlyName = ProxyConstants.CNRemoverRegex.Replace(subjectName, string.Empty); // Set private key onto certificate instance
} var x509Certificate = withPrivateKey(certificate, rsaparams);
catch (PlatformNotSupportedException)
{ if (!doNotSetFriendlyName)
doNotSetFriendlyName = true; {
} try
} {
x509Certificate.FriendlyName = ProxyConstants.CNRemoverRegex.Replace(subjectName, string.Empty);
return x509Certificate; }
} catch (PlatformNotSupportedException)
{
private static X509Certificate2 withPrivateKey(X509Certificate certificate, AsymmetricKeyParameter privateKey) doNotSetFriendlyName = true;
{ }
const string password = "password"; }
Pkcs12Store store;
return x509Certificate;
if (RunTime.IsRunningOnMono) }
{
var builder = new Pkcs12StoreBuilder(); private static X509Certificate2 withPrivateKey(X509Certificate certificate, AsymmetricKeyParameter privateKey)
builder.SetUseDerEncoding(true); {
store = builder.Build(); const string password = "password";
} Pkcs12Store store;
else
{ if (RunTime.IsRunningOnMono)
store = new Pkcs12Store(); {
} var builder = new Pkcs12StoreBuilder();
builder.SetUseDerEncoding(true);
var entry = new X509CertificateEntry(certificate); store = builder.Build();
store.SetCertificateEntry(certificate.SubjectDN.ToString(), entry); }
else
store.SetKeyEntry(certificate.SubjectDN.ToString(), new AsymmetricKeyEntry(privateKey), new[] { entry }); {
using (var ms = new MemoryStream()) store = new Pkcs12Store();
{ }
store.Save(ms, password.ToCharArray(), new SecureRandom(new CryptoApiRandomGenerator()));
var entry = new X509CertificateEntry(certificate);
return new X509Certificate2(ms.ToArray(), password, X509KeyStorageFlags.Exportable); store.SetCertificateEntry(certificate.SubjectDN.ToString(), entry);
}
} store.SetKeyEntry(certificate.SubjectDN.ToString(), new AsymmetricKeyEntry(privateKey), new[] { entry });
using (var ms = new MemoryStream())
/// <summary> {
/// Makes the certificate internal. store.Save(ms, password.ToCharArray(), new SecureRandom(new CryptoApiRandomGenerator()));
/// </summary>
/// <param name="hostName">hostname for certificate</param> return new X509Certificate2(ms.ToArray(), password, X509KeyStorageFlags.Exportable);
/// <param name="subjectName">The full subject.</param> }
/// <param name="validFrom">The valid from.</param> }
/// <param name="validTo">The valid to.</param>
/// <param name="signingCertificate">The signing certificate.</param> /// <summary>
/// <returns>X509Certificate2 instance.</returns> /// Makes the certificate internal.
/// <exception cref="System.ArgumentException"> /// </summary>
/// You must specify a Signing Certificate if and only if you are not creating a /// <param name="hostName">hostname for certificate</param>
/// root. /// <param name="subjectName">The full subject.</param>
/// </exception> /// <param name="validFrom">The valid from.</param>
private X509Certificate2 makeCertificateInternal(string hostName, string subjectName, /// <param name="validTo">The valid to.</param>
DateTime validFrom, DateTime validTo, X509Certificate2? signingCertificate) /// <param name="signingCertificate">The signing certificate.</param>
{ /// <returns>X509Certificate2 instance.</returns>
if (signingCertificate == null) /// <exception cref="System.ArgumentException">
{ /// You must specify a Signing Certificate if and only if you are not creating a
return generateCertificate(null, subjectName, subjectName, validFrom, validTo); /// root.
} /// </exception>
private X509Certificate2 makeCertificateInternal(string hostName, string subjectName,
var kp = DotNetUtilities.GetKeyPair(signingCertificate.PrivateKey); DateTime validFrom, DateTime validTo, X509Certificate2? signingCertificate)
return generateCertificate(hostName, subjectName, signingCertificate.Subject, validFrom, validTo, {
issuerPrivateKey: kp.Private); if (signingCertificate == null)
} {
return generateCertificate(null, subjectName, subjectName, validFrom, validTo);
/// <summary> }
/// Makes the certificate internal.
/// </summary> var kp = DotNetUtilities.GetKeyPair(signingCertificate.PrivateKey);
/// <param name="subject">The s subject cn.</param> return generateCertificate(hostName, subjectName, signingCertificate.Subject, validFrom, validTo,
/// <param name="switchToMtaIfNeeded">if set to <c>true</c> [switch to MTA if needed].</param> issuerPrivateKey: kp.Private);
/// <param name="signingCert">The signing cert.</param> }
/// <returns>X509Certificate2.</returns>
private X509Certificate2 makeCertificateInternal(string subject, /// <summary>
bool switchToMtaIfNeeded, X509Certificate2? signingCert = null) /// Makes the certificate internal.
{ /// </summary>
return makeCertificateInternal(subject, $"CN={subject}", /// <param name="subject">The s subject cn.</param>
DateTime.UtcNow.AddDays(-certificateGraceDays), DateTime.UtcNow.AddDays(certificateValidDays), /// <param name="switchToMtaIfNeeded">if set to <c>true</c> [switch to MTA if needed].</param>
signingCert); /// <param name="signingCert">The signing cert.</param>
} /// <returns>X509Certificate2.</returns>
} private X509Certificate2 makeCertificateInternal(string subject,
} bool switchToMtaIfNeeded, X509Certificate2? signingCert = null)
{
return makeCertificateInternal(subject, $"CN={subject}",
DateTime.UtcNow.AddDays(-certificateGraceDays), DateTime.UtcNow.AddDays(certificateValidDays),
signingCert);
}
}
}
using System; using System;
using System.IO; using System.IO;
using System.Net;
using System.Security.Cryptography.X509Certificates; using System.Security.Cryptography.X509Certificates;
using Org.BouncyCastle.Asn1; using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.Pkcs; using Org.BouncyCastle.Asn1.Pkcs;
...@@ -99,7 +100,13 @@ namespace Titanium.Web.Proxy.Network.Certificate ...@@ -99,7 +100,13 @@ namespace Titanium.Web.Proxy.Network.Certificate
if (hostName != null) if (hostName != null)
{ {
// add subject alternative names // add subject alternative names
var subjectAlternativeNames = new Asn1Encodable[] { new GeneralName(GeneralName.DnsName, hostName) }; var nameType = GeneralName.DnsName;
if (IPAddress.TryParse(hostName, out _))
{
nameType = GeneralName.IPAddress;
}
var subjectAlternativeNames = new Asn1Encodable[] { new GeneralName(nameType, hostName) };
var subjectAlternativeNamesExtension = new DerSequence(subjectAlternativeNames); var subjectAlternativeNamesExtension = new DerSequence(subjectAlternativeNames);
certificateGenerator.AddExtension(X509Extensions.SubjectAlternativeName.Id, false, certificateGenerator.AddExtension(X509Extensions.SubjectAlternativeName.Id, false,
......
using System; using System;
using System.Net;
using System.Reflection; using System.Reflection;
using System.Security.Cryptography.X509Certificates; using System.Security.Cryptography.X509Certificates;
using System.Threading; using System.Threading;
...@@ -220,11 +221,20 @@ namespace Titanium.Web.Proxy.Network.Certificate ...@@ -220,11 +221,20 @@ namespace Titanium.Web.Proxy.Network.Certificate
var altNameCollection = Activator.CreateInstance(typeAltNamesCollection); var altNameCollection = Activator.CreateInstance(typeAltNamesCollection);
var extNames = Activator.CreateInstance(typeExtNames); var extNames = Activator.CreateInstance(typeExtNames);
var altDnsNames = Activator.CreateInstance(typeCAlternativeName); var altDnsNames = Activator.CreateInstance(typeCAlternativeName);
typeValue = new object[] { 3, subject }; IPAddress ip;
typeCAlternativeName.InvokeMember("InitializeFromString", BindingFlags.InvokeMethod, null, altDnsNames, if (IPAddress.TryParse(subject, out ip))
typeValue); {
String ipBase64 = Convert.ToBase64String(ip.GetAddressBytes());
typeValue = new object[] { AlternativeNameType.XCN_CERT_ALT_NAME_IP_ADDRESS, EncodingType.XCN_CRYPT_STRING_BASE64, ipBase64 };
typeCAlternativeName.InvokeMember("InitializeFromRawData", BindingFlags.InvokeMethod, null, altDnsNames, typeValue);
}
else
{
typeValue = new object[] { 3, subject };//3==DNS, 8==IP ADDR
typeCAlternativeName.InvokeMember("InitializeFromString", BindingFlags.InvokeMethod, null, altDnsNames, typeValue);
}
typeValue = new[] { altDnsNames }; typeValue = new[] { altDnsNames };
typeAltNamesCollection.InvokeMember("Add", BindingFlags.InvokeMethod, null, altNameCollection, typeAltNamesCollection.InvokeMember("Add", BindingFlags.InvokeMethod, null, altNameCollection,
...@@ -298,5 +308,45 @@ namespace Titanium.Web.Proxy.Network.Certificate ...@@ -298,5 +308,45 @@ namespace Titanium.Web.Proxy.Network.Certificate
return new X509Certificate2(Convert.FromBase64String(empty), string.Empty, X509KeyStorageFlags.Exportable); return new X509Certificate2(Convert.FromBase64String(empty), string.Empty, X509KeyStorageFlags.Exportable);
} }
}
public enum EncodingType
{
XCN_CRYPT_STRING_ANY = 7,
XCN_CRYPT_STRING_BASE64 = 1,
XCN_CRYPT_STRING_BASE64_ANY = 6,
XCN_CRYPT_STRING_BASE64HEADER = 0,
XCN_CRYPT_STRING_BASE64REQUESTHEADER = 3,
XCN_CRYPT_STRING_BASE64URI = 13,
XCN_CRYPT_STRING_BASE64X509CRLHEADER = 9,
XCN_CRYPT_STRING_BINARY = 2,
XCN_CRYPT_STRING_CHAIN = 0x100,
XCN_CRYPT_STRING_ENCODEMASK = 0xff,
XCN_CRYPT_STRING_HASHDATA = 0x10000000,
XCN_CRYPT_STRING_HEX = 4,
XCN_CRYPT_STRING_HEX_ANY = 8,
XCN_CRYPT_STRING_HEXADDR = 10,
XCN_CRYPT_STRING_HEXASCII = 5,
XCN_CRYPT_STRING_HEXASCIIADDR = 11,
XCN_CRYPT_STRING_HEXRAW = 12,
XCN_CRYPT_STRING_NOCR = -2147483648,
XCN_CRYPT_STRING_NOCRLF = 0x40000000,
XCN_CRYPT_STRING_PERCENTESCAPE = 0x8000000,
XCN_CRYPT_STRING_STRICT = 0x20000000,
XCN_CRYPT_STRING_TEXT = 0x200
}
public enum AlternativeNameType
{
XCN_CERT_ALT_NAME_DIRECTORY_NAME = 5,
XCN_CERT_ALT_NAME_DNS_NAME = 3,
XCN_CERT_ALT_NAME_GUID = 10,
XCN_CERT_ALT_NAME_IP_ADDRESS = 8,
XCN_CERT_ALT_NAME_OTHER_NAME = 1,
XCN_CERT_ALT_NAME_REGISTERED_ID = 9,
XCN_CERT_ALT_NAME_RFC822_NAME = 2,
XCN_CERT_ALT_NAME_UNKNOWN = 0,
XCN_CERT_ALT_NAME_URL = 7,
XCN_CERT_ALT_NAME_USER_PRINCIPLE_NAME = 11
} }
} }
...@@ -35,7 +35,7 @@ namespace Titanium.Web.Proxy ...@@ -35,7 +35,7 @@ namespace Titanium.Web.Proxy
var clientStream = new HttpClientStream(clientConnection, clientConnection.GetStream(), BufferPool, cancellationToken); var clientStream = new HttpClientStream(clientConnection, clientConnection.GetStream(), BufferPool, cancellationToken);
Task<TcpServerConnection>? prefetchConnectionTask = null; Task<TcpServerConnection?>? prefetchConnectionTask = null;
bool closeServerConnection = false; bool closeServerConnection = false;
try try
...@@ -145,13 +145,16 @@ namespace Titanium.Web.Proxy ...@@ -145,13 +145,16 @@ namespace Titanium.Web.Proxy
// todo: this is a hack, because Titanium does not support HTTP protocol changing currently // todo: this is a hack, because Titanium does not support HTTP protocol changing currently
var connection = await tcpConnectionFactory.GetServerConnection(this, connectArgs, var connection = await tcpConnectionFactory.GetServerConnection(this, connectArgs,
true, SslExtensions.Http2ProtocolAsList, true, SslExtensions.Http2ProtocolAsList,
true, cancellationToken); true, true, cancellationToken);
http2Supported = connection.NegotiatedApplicationProtocol == if (connection != null)
SslApplicationProtocol.Http2; {
http2Supported = connection.NegotiatedApplicationProtocol ==
SslApplicationProtocol.Http2;
// release connection back to pool instead of closing when connection pool is enabled. // release connection back to pool instead of closing when connection pool is enabled.
await tcpConnectionFactory.Release(connection, true); await tcpConnectionFactory.Release(connection, true);
}
} }
catch (Exception) catch (Exception)
{ {
...@@ -162,22 +165,11 @@ namespace Titanium.Web.Proxy ...@@ -162,22 +165,11 @@ namespace Titanium.Web.Proxy
if (EnableTcpServerConnectionPrefetch) if (EnableTcpServerConnectionPrefetch)
{ {
IPAddress[]? ipAddresses = null; // don't pass cancellation token here
try // it could cause floating server connections when client exits
{ prefetchConnectionTask = tcpConnectionFactory.GetServerConnection(this, connectArgs,
// make sure the host can be resolved before creating the prefetch task true, null, false, true,
ipAddresses = await Dns.GetHostAddressesAsync(connectArgs.HttpClient.Request.RequestUri.Host); CancellationToken.None);
}
catch (SocketException) { }
if (ipAddresses != null && ipAddresses.Length > 0)
{
// don't pass cancellation token here
// it could cause floating server connections when client exits
prefetchConnectionTask = tcpConnectionFactory.GetServerConnection(this, connectArgs,
true, null, false,
CancellationToken.None);
}
} }
string connectHostname = requestLine.RequestUri.GetString(); string connectHostname = requestLine.RequestUri.GetString();
...@@ -272,9 +264,9 @@ namespace Titanium.Web.Proxy ...@@ -272,9 +264,9 @@ namespace Titanium.Web.Proxy
// create new connection to server. // create new connection to server.
// If we detected that client tunnel CONNECTs without SSL by checking for empty client hello then // If we detected that client tunnel CONNECTs without SSL by checking for empty client hello then
// this connection should not be HTTPS. // this connection should not be HTTPS.
var connection = await tcpConnectionFactory.GetServerConnection(this, connectArgs, var connection = (await tcpConnectionFactory.GetServerConnection(this, connectArgs,
true, null, true, null,
true, cancellationToken); true, false, cancellationToken))!;
try try
{ {
...@@ -349,9 +341,9 @@ namespace Titanium.Web.Proxy ...@@ -349,9 +341,9 @@ namespace Titanium.Web.Proxy
throw new Exception($"HTTP/2 Protocol violation. Empty string expected, '{line}' received"); throw new Exception($"HTTP/2 Protocol violation. Empty string expected, '{line}' received");
} }
var connection = await tcpConnectionFactory.GetServerConnection(this, connectArgs, var connection = (await tcpConnectionFactory.GetServerConnection(this, connectArgs,
true, SslExtensions.Http2ProtocolAsList, true, SslExtensions.Http2ProtocolAsList,
true, cancellationToken); true, false, cancellationToken))!;
try try
{ {
#if NETSTANDARD2_1 #if NETSTANDARD2_1
......
...@@ -154,7 +154,7 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -154,7 +154,7 @@ namespace Titanium.Web.Proxy.Network.Tcp
applicationProtocols = new List<SslApplicationProtocol> { applicationProtocol }; applicationProtocols = new List<SslApplicationProtocol> { applicationProtocol };
} }
return GetServerConnection(proxyServer, session, isConnect, applicationProtocols, noCache, cancellationToken); return GetServerConnection(proxyServer, session, isConnect, applicationProtocols, noCache, false, cancellationToken)!;
} }
/// <summary> /// <summary>
...@@ -165,10 +165,11 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -165,10 +165,11 @@ namespace Titanium.Web.Proxy.Network.Tcp
/// <param name="isConnect">Is this a CONNECT request.</param> /// <param name="isConnect">Is this a CONNECT request.</param>
/// <param name="applicationProtocols"></param> /// <param name="applicationProtocols"></param>
/// <param name="noCache">if set to <c>true</c> [no cache].</param> /// <param name="noCache">if set to <c>true</c> [no cache].</param>
/// <param name="prefetch">if set to <c>true</c> [prefetch].</param>
/// <param name="cancellationToken">The cancellation token for this async task.</param> /// <param name="cancellationToken">The cancellation token for this async task.</param>
/// <returns></returns> /// <returns></returns>
internal async Task<TcpServerConnection> GetServerConnection(ProxyServer proxyServer, SessionEventArgsBase session, bool isConnect, internal async Task<TcpServerConnection?> GetServerConnection(ProxyServer proxyServer, SessionEventArgsBase session, bool isConnect,
List<SslApplicationProtocol>? applicationProtocols, bool noCache, CancellationToken cancellationToken) List<SslApplicationProtocol>? applicationProtocols, bool noCache, bool prefetch, CancellationToken cancellationToken)
{ {
var customUpStreamProxy = session.CustomUpStreamProxy; var customUpStreamProxy = session.CustomUpStreamProxy;
...@@ -208,7 +209,7 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -208,7 +209,7 @@ namespace Titanium.Web.Proxy.Network.Tcp
var upStreamEndPoint = session.HttpClient.UpStreamEndPoint ?? proxyServer.UpStreamEndPoint; var upStreamEndPoint = session.HttpClient.UpStreamEndPoint ?? proxyServer.UpStreamEndPoint;
var upStreamProxy = customUpStreamProxy ?? (isHttps ? proxyServer.UpStreamHttpsProxy : proxyServer.UpStreamHttpProxy); var upStreamProxy = customUpStreamProxy ?? (isHttps ? proxyServer.UpStreamHttpsProxy : proxyServer.UpStreamHttpProxy);
return await GetServerConnection(proxyServer, host, port, session.HttpClient.Request.HttpVersion, isHttps, return await GetServerConnection(proxyServer, host, port, session.HttpClient.Request.HttpVersion, isHttps,
applicationProtocols, isConnect, session, upStreamEndPoint, upStreamProxy, noCache, cancellationToken); applicationProtocols, isConnect, session, upStreamEndPoint, upStreamProxy, noCache, prefetch, cancellationToken);
} }
/// <summary> /// <summary>
...@@ -225,12 +226,13 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -225,12 +226,13 @@ namespace Titanium.Web.Proxy.Network.Tcp
/// <param name="upStreamEndPoint">The local upstream endpoint to make request via.</param> /// <param name="upStreamEndPoint">The local upstream endpoint to make request via.</param>
/// <param name="externalProxy">The external proxy to make request via.</param> /// <param name="externalProxy">The external proxy to make request via.</param>
/// <param name="noCache">Not from cache/create new connection.</param> /// <param name="noCache">Not from cache/create new connection.</param>
/// <param name="prefetch">if set to <c>true</c> [prefetch].</param>
/// <param name="cancellationToken">The cancellation token for this async task.</param> /// <param name="cancellationToken">The cancellation token for this async task.</param>
/// <returns></returns> /// <returns></returns>
internal async Task<TcpServerConnection> GetServerConnection(ProxyServer proxyServer, string remoteHostName, int remotePort, internal async Task<TcpServerConnection?> GetServerConnection(ProxyServer proxyServer, string remoteHostName, int remotePort,
Version httpVersion, bool isHttps, List<SslApplicationProtocol>? applicationProtocols, bool isConnect, Version httpVersion, bool isHttps, List<SslApplicationProtocol>? applicationProtocols, bool isConnect,
SessionEventArgsBase sessionArgs, IPEndPoint? upStreamEndPoint, IExternalProxy? externalProxy, SessionEventArgsBase sessionArgs, IPEndPoint? upStreamEndPoint, IExternalProxy? externalProxy,
bool noCache, CancellationToken cancellationToken) bool noCache, bool prefetch, CancellationToken cancellationToken)
{ {
var sslProtocol = sessionArgs.ClientConnection.SslProtocol; var sslProtocol = sessionArgs.ClientConnection.SslProtocol;
var cacheKey = GetConnectionCacheKey(remoteHostName, remotePort, var cacheKey = GetConnectionCacheKey(remoteHostName, remotePort,
...@@ -259,7 +261,7 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -259,7 +261,7 @@ namespace Titanium.Web.Proxy.Network.Tcp
} }
var connection = await createServerConnection(remoteHostName, remotePort, httpVersion, isHttps, sslProtocol, var connection = await createServerConnection(remoteHostName, remotePort, httpVersion, isHttps, sslProtocol,
applicationProtocols, isConnect, proxyServer, sessionArgs, upStreamEndPoint, externalProxy, cacheKey, cancellationToken); applicationProtocols, isConnect, proxyServer, sessionArgs, upStreamEndPoint, externalProxy, cacheKey, prefetch, cancellationToken);
return connection; return connection;
} }
...@@ -279,12 +281,13 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -279,12 +281,13 @@ namespace Titanium.Web.Proxy.Network.Tcp
/// <param name="upStreamEndPoint">The local upstream endpoint to make request via.</param> /// <param name="upStreamEndPoint">The local upstream endpoint to make request via.</param>
/// <param name="externalProxy">The external proxy to make request via.</param> /// <param name="externalProxy">The external proxy to make request via.</param>
/// <param name="cacheKey">The connection cache key</param> /// <param name="cacheKey">The connection cache key</param>
/// <param name="prefetch">if set to <c>true</c> [prefetch].</param>
/// <param name="cancellationToken">The cancellation token for this async task.</param> /// <param name="cancellationToken">The cancellation token for this async task.</param>
/// <returns></returns> /// <returns></returns>
private async Task<TcpServerConnection> createServerConnection(string remoteHostName, int remotePort, private async Task<TcpServerConnection?> createServerConnection(string remoteHostName, int remotePort,
Version httpVersion, bool isHttps, SslProtocols sslProtocol, List<SslApplicationProtocol>? applicationProtocols, bool isConnect, Version httpVersion, bool isHttps, SslProtocols sslProtocol, List<SslApplicationProtocol>? applicationProtocols, bool isConnect,
ProxyServer proxyServer, SessionEventArgsBase sessionArgs, IPEndPoint? upStreamEndPoint, IExternalProxy? externalProxy, string cacheKey, ProxyServer proxyServer, SessionEventArgsBase sessionArgs, IPEndPoint? upStreamEndPoint, IExternalProxy? externalProxy, string cacheKey,
CancellationToken cancellationToken) bool prefetch, CancellationToken cancellationToken)
{ {
// deny connection to proxy end points to avoid infinite connection loop. // deny connection to proxy end points to avoid infinite connection loop.
if (Server.ProxyEndPoints.Any(x => x.Port == remotePort) if (Server.ProxyEndPoints.Any(x => x.Port == remotePort)
...@@ -350,6 +353,11 @@ retry: ...@@ -350,6 +353,11 @@ retry:
var ipAddresses = await Dns.GetHostAddressesAsync(hostname); var ipAddresses = await Dns.GetHostAddressesAsync(hostname);
if (ipAddresses == null || ipAddresses.Length == 0) if (ipAddresses == null || ipAddresses.Length == 0)
{ {
if (prefetch)
{
return null;
}
throw new Exception($"Could not resolve the hostname {hostname}"); throw new Exception($"Could not resolve the hostname {hostname}");
} }
...@@ -375,7 +383,7 @@ retry: ...@@ -375,7 +383,7 @@ retry:
? ProxyTypes.Socks4 ? ProxyTypes.Socks4
: ProxyTypes.Socks5; : ProxyTypes.Socks5;
proxySocket.ProxyEndPoint = new IPEndPoint(ipAddresses[0], port); proxySocket.ProxyEndPoint = new IPEndPoint(ipAddress, port);
if (!string.IsNullOrEmpty(externalProxy.UserName) && externalProxy.Password != null) if (!string.IsNullOrEmpty(externalProxy.UserName) && externalProxy.Password != null)
{ {
proxySocket.ProxyUser = externalProxy.UserName; proxySocket.ProxyUser = externalProxy.UserName;
...@@ -486,10 +494,15 @@ retry: ...@@ -486,10 +494,15 @@ retry:
{ {
sessionArgs.CustomUpStreamProxyUsed = newUpstreamProxy; sessionArgs.CustomUpStreamProxyUsed = newUpstreamProxy;
sessionArgs.TimeLine["Retrying Upstream Proxy Connection"] = DateTime.UtcNow; sessionArgs.TimeLine["Retrying Upstream Proxy Connection"] = DateTime.UtcNow;
return await createServerConnection(remoteHostName, remotePort, httpVersion, isHttps, sslProtocol, applicationProtocols, isConnect, proxyServer, sessionArgs, upStreamEndPoint, externalProxy, cacheKey, cancellationToken); return await createServerConnection(remoteHostName, remotePort, httpVersion, isHttps, sslProtocol, applicationProtocols, isConnect, proxyServer, sessionArgs, upStreamEndPoint, externalProxy, cacheKey, prefetch, cancellationToken);
} }
} }
if (prefetch)
{
return null;
}
throw new Exception($"Could not establish connection to {hostname}", lastException); throw new Exception($"Could not establish connection to {hostname}", lastException);
} }
...@@ -502,7 +515,7 @@ retry: ...@@ -502,7 +515,7 @@ retry:
stream = new HttpServerStream(new NetworkStream(tcpServerSocket, true), proxyServer.BufferPool, cancellationToken); stream = new HttpServerStream(new NetworkStream(tcpServerSocket, true), proxyServer.BufferPool, cancellationToken);
if ((externalProxy != null && externalProxy.ProxyType == ExternalProxyType.Http) && (isConnect || isHttps)) if (externalProxy != null && externalProxy.ProxyType == ExternalProxyType.Http && (isConnect || isHttps))
{ {
var authority = $"{remoteHostName}:{remotePort}".GetByteString(); var authority = $"{remoteHostName}:{remotePort}".GetByteString();
var connectRequest = new ConnectRequest(authority) var connectRequest = new ConnectRequest(authority)
...@@ -658,7 +671,7 @@ retry: ...@@ -658,7 +671,7 @@ retry:
} }
} }
internal async Task Release(Task<TcpServerConnection>? connectionCreateTask, bool closeServerConnection) internal async Task Release(Task<TcpServerConnection?>? connectionCreateTask, bool closeServerConnection)
{ {
if (connectionCreateTask == null) if (connectionCreateTask == null)
{ {
......
...@@ -35,7 +35,7 @@ namespace Titanium.Web.Proxy ...@@ -35,7 +35,7 @@ namespace Titanium.Web.Proxy
/// <param name="isHttps">Is HTTPS</param> /// <param name="isHttps">Is HTTPS</param>
private async Task handleHttpSessionRequest(ProxyEndPoint endPoint, HttpClientStream clientStream, private async Task handleHttpSessionRequest(ProxyEndPoint endPoint, HttpClientStream clientStream,
CancellationTokenSource cancellationTokenSource, TunnelConnectSessionEventArgs? connectArgs = null, CancellationTokenSource cancellationTokenSource, TunnelConnectSessionEventArgs? connectArgs = null,
Task<TcpServerConnection>? prefetchConnectionTask = null, bool isHttps = false) Task<TcpServerConnection?>? prefetchConnectionTask = null, bool isHttps = false)
{ {
var connectRequest = connectArgs?.HttpClient.ConnectRequest; var connectRequest = connectArgs?.HttpClient.ConnectRequest;
......
...@@ -91,10 +91,10 @@ namespace Titanium.Web.Proxy ...@@ -91,10 +91,10 @@ namespace Titanium.Web.Proxy
else else
{ {
var sessionArgs = new SessionEventArgs(this, endPoint, clientStream, null, cancellationTokenSource); var sessionArgs = new SessionEventArgs(this, endPoint, clientStream, null, cancellationTokenSource);
var connection = await tcpConnectionFactory.GetServerConnection(this, httpsHostName, port, var connection = (await tcpConnectionFactory.GetServerConnection(this, httpsHostName, port,
HttpHeader.VersionUnknown, false, null, HttpHeader.VersionUnknown, false, null,
true, sessionArgs, UpStreamEndPoint, true, sessionArgs, UpStreamEndPoint,
UpStreamHttpsProxy, true, cancellationToken); UpStreamHttpsProxy, true, false, cancellationToken))!;
try try
{ {
......
...@@ -7,13 +7,16 @@ namespace Titanium.Web.Proxy.IntegrationTests.Setup ...@@ -7,13 +7,16 @@ namespace Titanium.Web.Proxy.IntegrationTests.Setup
{ {
public class TestProxyServer : IDisposable public class TestProxyServer : IDisposable
{ {
public ProxyServer ProxyServer { get; private set; } public ProxyServer ProxyServer { get; }
public int ListeningPort => ProxyServer.ProxyEndPoints[0].Port; public int ListeningPort => ProxyServer.ProxyEndPoints[0].Port;
public CertificateManager CertificateManager => ProxyServer.CertificateManager; public CertificateManager CertificateManager => ProxyServer.CertificateManager;
public TestProxyServer(bool isReverseProxy, ProxyServer upStreamProxy = null) public TestProxyServer(bool isReverseProxy, ProxyServer upStreamProxy = null)
{ {
ProxyServer = new ProxyServer(); ProxyServer = new ProxyServer();
var explicitEndPoint = isReverseProxy ? var explicitEndPoint = isReverseProxy ?
(ProxyEndPoint)new TransparentProxyEndPoint(IPAddress.Any, 0, true) : (ProxyEndPoint)new TransparentProxyEndPoint(IPAddress.Any, 0, true) :
new ExplicitProxyEndPoint(IPAddress.Any, 0, true); new ExplicitProxyEndPoint(IPAddress.Any, 0, true);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment