using System; using System.Net; using System.Security.Cryptography.X509Certificates; using System.Security.Cryptography; using System.Security; namespace Intel.WebStorage { class WebStorageConnectionOptions : IWebStorageConnectionOptions { public const int MAX_PWD_LENGTH = 32; public const int MIN_PWD_LENGTH = 8; public const int MAX_USERNAME_LENGTH = 32; //Client certificate OIDs private const string OID_LOCAL = "2.16.840.1.113741.1.2.2"; private const string OID_REMOTE = "2.16.840.1.113741.1.2.1"; // Max timeout is 100 seconds. This is the default timeout for httpClient timeout // (https://learn.microsoft.com/en-us/dotnet/api/system.net.http.httpclient.timeout?view=netframework-4.8) private const int MAX_TIME_OUT = 100000; private const int DEFAULT_TIME_OUT = 30000; private const int MIN_TIME_OUT = 5000; private int _timeout; private X509Certificate2 _clientCert; private string _clientCertificareCN; private string _proxyUser; private string _proxyAddress; private SecureString _proxyPassword; private ServerCertificateValidationCallback _serverCertificateValidationCallback; public WebStorageConnectionOptions() { _timeout = DEFAULT_TIME_OUT; //default 30 second time for sleeping ME _clientCertificareCN = null; _clientCert = null; _proxyAddress = null; _proxyUser = null; _proxyPassword = null; } public int TimeOut { get { return _timeout; } set { if (value > MAX_TIME_OUT || value < MIN_TIME_OUT) throw new WebStorageException("Time out value must be between the range " + MIN_TIME_OUT.ToString() + " and " + MAX_TIME_OUT.ToString()); ; _timeout = value; } } public string ClientCertificateCommonName { get { return _clientCertificareCN; } set { if (!String.IsNullOrEmpty(value)) { // In the common name field of the DN of a X509 certificate, the limit is up to 64 characters if (value.Length > 64) throw new WebStorageException("Invalid argument - invalid certificate CN"); ClientCertificate = getCertFromStore(value)[0]; //If empty string the WebStorage will search a certificate with the appropriate OIDs } _clientCertificareCN = value; } } /// /// The certificate to use for establishing the connection. /// To set this property by providing a certificate name string only, use the ClientCertificateCommonName property. /// public X509Certificate2 ClientCertificate { get { return _clientCert; } set { _clientCertificareCN = null; _clientCert = value; } } public string ProxyUser { get { return _proxyUser; } set { if (String.IsNullOrEmpty(value)) _proxyUser = ""; else { _proxyUser = value; if (_proxyUser.Length > MAX_USERNAME_LENGTH) throw new WebStorageException("Invalid Argument - Username can contain up to 32 characters."); } } } public SecureString ProxyPassword { get { return _proxyPassword; } set { if (value == null || value.Length == 0 ) { _proxyPassword = new SecureString(); } else { if (value.Length < MIN_PWD_LENGTH || value.Length > MAX_PWD_LENGTH) throw new WebStorageException("Invalid Argument - Password can contain between 8 to 32 characters."); _proxyPassword?.Dispose(); _proxyPassword = value; } } } public string ProxyAddress { get { return _proxyAddress; } set { if (String.IsNullOrEmpty(value)) throw new WebStorageException("Host name is null or an empty string."); if (!Uri.IsWellFormedUriString(value, 0)) throw new WebStorageException("Incorrect uri."); _proxyAddress = value; } } public IWebProxy Proxy { get { WebProxy result = null; if (_proxyAddress != null) { result = new WebProxy(_proxyAddress, false); } if (result != null && _proxyUser != null && _proxyPassword != null) { result.Credentials = new NetworkCredential(_proxyUser, _proxyPassword.Copy()); } return result; } } public ServerCertificateValidationCallback ServerCertificateValidationCallback { get { return _serverCertificateValidationCallback; } set { _serverCertificateValidationCallback = value; } } //Return a specific certificate from the cert store. //If empty string the WebStorage will search a certificate with the appropriate OIDs private X509Certificate2Collection getCertFromStore(String clientCert) { X509Certificate2Collection certificatesCollection = new X509Certificate2Collection(); // Open CurrentUser cert store X509EnhancedKeyUsageExtension ex; using (X509Store currentUserStore = new X509Store(StoreName.My, StoreLocation.CurrentUser)) { currentUserStore.Open(OpenFlags.ReadOnly); foreach (X509Certificate2 certificate in currentUserStore.Certificates) { if (String.Compare(clientCert, "") == 0 || certificate.Subject.ToLower().Contains(clientCert.ToLower())) { // Checking that the Enhanced Key Usage in the certificate is the one for AMT foreach (X509Extension extension in certificate.Extensions) { ex = extension as X509EnhancedKeyUsageExtension; if (ex != null) { foreach (Oid OID in ex.EnhancedKeyUsages) { if (OID.Value == OID_REMOTE || OID.Value == OID_LOCAL) certificatesCollection.Add(certificate); } } } } } } // Open LocalMachine cert store using (X509Store localMachineStore = new X509Store(StoreName.My, StoreLocation.LocalMachine)) { localMachineStore.Open(OpenFlags.ReadOnly); foreach (X509Certificate2 certificate in localMachineStore.Certificates) { if (String.Compare(clientCert, "") == 0 || certificate.Subject.ToLower().Contains(clientCert.ToLower())) { // Checking that the Enhanced Key Usage in the certificate is the one for AMT foreach (X509Extension extension in certificate.Extensions) { ex = extension as X509EnhancedKeyUsageExtension; if (ex != null) { foreach (Oid OID in ex.EnhancedKeyUsages) { if (OID.Value == OID_REMOTE || OID.Value == OID_LOCAL) certificatesCollection.Add(certificate); } } } } } } if (certificatesCollection.Count < 1) throw new WebStorageException("Can not find appropriate certificate in certificate store"); return certificatesCollection; } } }//end namspace