/// <summary>
        /// Create an Address with optional verifications.
        /// </summary>
        /// <param name="address">Address to create</param>
        /// <param name="verify">Verification flags to to control verification. You can verify the delivery address or the
        /// extended zip4 value. If you use the strict versions an HttpException to be raised if unsucessful.
        /// </param>
        /// <returns>Address instance.</returns>
        public Task <Address> CreateAddress(
            Address address,
            VerificationFlags verify = VerificationFlags.None)
        {
            var request = new EasyPostRequest("addresses", Method.POST);

            request.AddBody(address.AsDictionary(), "address");

            if ((verify & VerificationFlags.Delivery) != 0)
            {
                request.AddParameter("verify[]", "delivery", ParameterType.QueryString);
            }
            if ((verify & VerificationFlags.Zip4) != 0)
            {
                request.AddParameter("verify[]", "zip4", ParameterType.QueryString);
            }
            if ((verify & VerificationFlags.DeliveryStrict) != 0)
            {
                request.AddParameter("verify_strict[]", "delivery", ParameterType.QueryString);
            }
            if ((verify & VerificationFlags.Zip4Strict) != 0)
            {
                request.AddParameter("verify_strict[]", "zip4", ParameterType.QueryString);
            }

            return(Execute <Address>(request));
        }
        /// <summary>
        /// Verifies the end <see cref="Certificate"/> according to the SSL policy rules.
        /// </summary>
        /// <param name="server">The server that returned the certificate -or- a null reference if the certificate is a client certificate.</param>
        /// <param name="type">One of the <see cref="AuthType"/> values.</param>
        /// <param name="flags">One or more of the <see cref="VerificationFlags"/> values. VerificationFlags values can be combined with the OR operator.</param>
        /// <returns>One of the <see cref="CertificateStatus"/> values.</returns>
        /// <exception cref="CertificateException">An error occurs while verifying the certificate.</exception>
        public virtual CertificateStatus VerifyChain(string server, AuthType type, VerificationFlags flags)
        {
            // Convert the server string to a wide string memory pointer
            IntPtr serverName = IntPtr.Zero;
            IntPtr dataPtr    = IntPtr.Zero;

            try {
                if (server == null)
                {
                    serverName = IntPtr.Zero;
                }
                else
                {
                    serverName = Marshal.StringToHGlobalUni(server);
                }
                // create a HTTPSPolicyCallbackData and get a memory pointer to the structure
                SslPolicyParameters data = new SslPolicyParameters();
                data.cbSize         = Marshal.SizeOf(typeof(SslPolicyParameters));
                data.dwAuthType     = (int)type;
                data.pwszServerName = serverName;
                data.fdwChecks      = (int)flags;
                dataPtr             = Marshal.AllocHGlobal(data.cbSize);
                Marshal.StructureToPtr(data, dataPtr, false);
                // create a CERT_CHAIN_POLICY_PARA
                ChainPolicyParameters para = new ChainPolicyParameters();
                para.cbSize            = Marshal.SizeOf(typeof(ChainPolicyParameters));
                para.dwFlags           = (int)flags;
                para.pvExtraPolicyPara = dataPtr;
                // create a CERT_CHAIN_POLICY_STATUS
                ChainPolicyStatus status = new ChainPolicyStatus();
                status.cbSize = Marshal.SizeOf(typeof(ChainPolicyStatus));
                // verify the certificate
                if (SspiProvider.CertVerifyCertificateChainPolicy(new IntPtr(SecurityConstants.CERT_CHAIN_POLICY_SSL), m_Handle, ref para, ref status) == 0)
                {
                    throw new CertificateException("Unable to verify the certificate.");
                }
                if (Enum.IsDefined(typeof(CertificateStatus), status.dwError))
                {
                    return((CertificateStatus)status.dwError);
                }
                else
                {
                    return(CertificateStatus.OtherError);
                }
            } finally {
                // clean up
                if (dataPtr != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(dataPtr);
                }
                if (serverName != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(serverName);
                }
            }
        }
		/// <summary>
		/// Initializes a new CertificateVerificationResult instance.
		/// </summary>
		/// <param name="chain">The <see cref="CertificateChain"/> that has to be verified.</param>
		/// <param name="server">The server to which the <see cref="Certificate"/> has been issued.</param>
		/// <param name="type">One of the <see cref="AuthType"/> values.</param>
		/// <param name="flags">One of the <see cref="VerificationFlags"/> values.</param>
		/// <param name="callback">The delegate to call when the verification finishes.</param>
		/// <param name="asyncState">User-defined state data.</param>
		public CertificateVerificationResult(CertificateChain chain, string server, AuthType type, VerificationFlags flags, AsyncCallback callback, object asyncState) {
			m_Chain = chain;
			m_Server = server;
			m_Type = type;
			m_Flags = flags;
			m_AsyncState = asyncState;
			m_Callback = callback;
			m_WaitHandle = null;
			m_HasEnded = false;
		}
        /// <summary>
        /// Begins verification of the end <see cref="Certificate"/> according to the SSL policy rules.
        /// </summary>
        /// <param name="server">The server that returned the certificate -or- a null reference if the certificate is a client certificate.</param>
        /// <param name="type">One of the <see cref="AuthType"/> values.</param>
        /// <param name="flags">One or more of the <see cref="VerificationFlags"/> values. VerificationFlags values can be combined with the OR operator.</param>
        /// <param name="callback">The <see cref="AsyncCallback"/> delegate.</param>
        /// <param name="asyncState">An object that contains state information for this request.</param>
        /// <returns>An <see cref="IAsyncResult"/> that references the asynchronous connection.</returns>
        /// <exception cref="CertificateException">An error occurs while queuing the verification request.</exception>
        public virtual IAsyncResult BeginVerifyChain(string server, AuthType type, VerificationFlags flags, AsyncCallback callback, object asyncState)
        {
            CertificateVerificationResult ret = new CertificateVerificationResult(this, server, type, flags, callback, asyncState);

            if (!ThreadPool.QueueUserWorkItem(new WaitCallback(this.StartVerification), ret))
            {
                throw new CertificateException("Could not schedule the certificate chain for verification.");
            }
            return(ret);
        }
Example #5
0
 /// <summary>
 /// Initializes a new CertificateVerificationResult instance.
 /// </summary>
 /// <param name="chain">The <see cref="CertificateChain"/> that has to be verified.</param>
 /// <param name="server">The server to which the <see cref="Certificate"/> has been issued.</param>
 /// <param name="type">One of the <see cref="AuthType"/> values.</param>
 /// <param name="flags">One of the <see cref="VerificationFlags"/> values.</param>
 /// <param name="callback">The delegate to call when the verification finishes.</param>
 /// <param name="asyncState">User-defined state data.</param>
 public CertificateVerificationResult(CertificateChain chain, string server, AuthType type, VerificationFlags flags, AsyncCallback callback, object asyncState)
 {
     m_Chain      = chain;
     m_Server     = server;
     m_Type       = type;
     m_Flags      = flags;
     m_AsyncState = asyncState;
     m_Callback   = callback;
     m_WaitHandle = null;
     m_HasEnded   = false;
 }
        /// <summary>
        /// verifies the certificate chain against the certificate store
        /// </summary>
        /// <param name="allCertsReceived">the chain to verify</param>
        /// <param name="expectedCNName">the expected CN; may be null</param>
        /// <param name="authType">the authtype: is the certificate to verify a client or server certificate;
        /// i.e when verifying a client cert, pass AuthType.Client; when verifying a server cert: pass AuthType.Server</param>ram>
        /// <returns></returns>
        protected bool IsValidCertificate(CertificateChain allCertsReceived, string expectedCNName, AuthType authType)
        {
            VerificationFlags verificationFlags = VerificationFlags.None;

            if (expectedCNName == null)
            {
                verificationFlags = VerificationFlags.IgnoreInvalidName;
            }
            CertificateStatus status = allCertsReceived.VerifyChain(expectedCNName, authType, verificationFlags);

            return(status == CertificateStatus.ValidCertificate);
        }
        /// <summary>
        /// Verifies the end <see cref="Certificate"/> according to the SSL policy rules.
        /// </summary>
        /// <param name="server">The server that returned the certificate -or- a null reference if the certificate is a client certificate.</param>
        /// <param name="type">One of the <see cref="AuthType"/> values.</param>
        /// <param name="flags">One or more of the <see cref="VerificationFlags"/> values. VerificationFlags values can be combined with the OR operator.</param>
        /// <param name="crl">An optional CRL to check. This parameter can be null (<b>Nothing</b> in Visual Basic).</param>
        /// <returns>One of the <see cref="CertificateStatus"/> values.</returns>
        /// <exception cref="CertificateException">An error occurs while verifying the certificate.</exception>
        /// <remarks>Only the leaf certificate is checked against the CRL.</remarks>
        // Thanks go out to Gabriele Zannoni for implementing this method
        public virtual CertificateStatus VerifyChain(string server, AuthType type, VerificationFlags flags, byte[] crl)
        {
            CertificateStatus status = VerifyChain(server, type, flags);

            if (status != CertificateStatus.ValidCertificate || crl == null)
            {
                return(status);
            }
            try {
                if (!m_Certificate.VerifyRevocation(crl))
                {
                    return(CertificateStatus.Revoked);
                }
                else
                {
                    return(status);
                }
            } catch {
                return(CertificateStatus.RevocationFailure);
            }
        }
Example #8
0
        public void VerifyConfig(VerificationFlags verificationFlags = VerificationFlags.All)
        {
            List <string> errorMessages = new List <string>();

            if (DiscordLink.Obj.DiscordClient == null)
            {
                errorMessages.Add("[General Verification] No Discord client connected.");
            }

            if (verificationFlags.HasFlag(VerificationFlags.Static))
            {
                // Bot Token
                if (string.IsNullOrWhiteSpace(Data.BotToken))
                {
                    errorMessages.Add("[Bot Token] Bot token not configured. See Github page for install instructions.");
                }

                // Player configs
                foreach (DiscordPlayerConfig playerConfig in Data.PlayerConfigs)
                {
                    if (string.IsNullOrWhiteSpace(playerConfig.Username))
                    {
                        continue;
                    }

                    bool found = false;
                    foreach (User user in UserManager.Users)
                    {
                        if (user.Name == playerConfig.Username)
                        {
                            found = true;
                            break;
                        }
                    }
                    if (!found)
                    {
                        errorMessages.Add("[Player Configs] No user with name \"" + playerConfig.Username + "\" was found");
                    }
                }

                // Eco command channel
                if (!string.IsNullOrWhiteSpace(Data.EcoCommandChannel) && Data.EcoCommandChannel.Contains("#"))
                {
                    errorMessages.Add("[Eco Command Channel] Channel name contains a channel indicator (#). The channel indicator will be added automatically and adding one manually may cause message sending to fail");
                }

                if (!string.IsNullOrWhiteSpace(Data.InviteMessage) && !Data.InviteMessage.Contains(InviteCommandLinkToken))
                {
                    errorMessages.Add("[Invite Message] Message does not contain the invite link token " + InviteCommandLinkToken + ". If the invite link has been added manually, consider adding it to the network config instead");
                }

                // Report errors
                if (errorMessages.Count <= 0)
                {
                    Logger.Info("Static configuration verification completed without errors");
                }
                else
                {
                    string concatenatedMessages = "";
                    foreach (string message in errorMessages)
                    {
                        concatenatedMessages += message + "\n";
                    }
                    Logger.Error("Static configuration errors detected!\n" + concatenatedMessages.Trim());
                }
            }

            // Discord guild and channel information isn't available the first time this function is called
            if (verificationFlags.HasFlag(VerificationFlags.ChannelLinks) && DiscordLink.Obj.DiscordClient != null && ChannelLinks.Count > 0)
            {
                foreach (ChannelLink link in _channelLinks)
                {
                    if (link.Verify())
                    {
                        string linkID = link.ToString();
                        if (!_verifiedLinks.Contains(linkID))
                        {
                            _verifiedLinks.Add(linkID);
                            Logger.Info("Channel Link Verified: " + linkID);
                        }
                    }
                }

                if (_verifiedLinks.Count >= _channelLinks.Count)
                {
                    Logger.Info("All channel links sucessfully verified");
                }
                else if (_linkVerificationTimeoutTimer == null) // If no timer is used, then the discord guild info should already be set up
                {
                    ReportUnverifiedChannels();
                }
            }
        }
Example #9
0
		/// <summary>
		/// Begins verification of the end <see cref="Certificate"/> according to the SSL policy rules.
		/// </summary>
		/// <param name="server">The server that returned the certificate -or- a null reference if the certificate is a client certificate.</param>
		/// <param name="type">One of the <see cref="AuthType"/> values.</param>
		/// <param name="flags">One or more of the <see cref="VerificationFlags"/> values. VerificationFlags values can be combined with the OR operator.</param>
		/// <param name="callback">The <see cref="AsyncCallback"/> delegate.</param>
		/// <param name="asyncState">An object that contains state information for this request.</param>
		/// <returns>An <see cref="IAsyncResult"/> that references the asynchronous connection.</returns>
		/// <exception cref="CertificateException">An error occurs while queuing the verification request.</exception>
		public virtual IAsyncResult BeginVerifyChain(string server, AuthType type, VerificationFlags flags, AsyncCallback callback, object asyncState) {
			CertificateVerificationResult ret = new CertificateVerificationResult(this, server, type, flags, callback, asyncState);
			if (!ThreadPool.QueueUserWorkItem(new WaitCallback(this.StartVerification), ret))
				throw new CertificateException("Could not schedule the certificate chain for verification.");
			return ret;
		}
Example #10
0
		/// <summary>
		/// Verifies the end <see cref="Certificate"/> according to the SSL policy rules.
		/// </summary>
		/// <param name="server">The server that returned the certificate -or- a null reference if the certificate is a client certificate.</param>
		/// <param name="type">One of the <see cref="AuthType"/> values.</param>
		/// <param name="flags">One or more of the <see cref="VerificationFlags"/> values. VerificationFlags values can be combined with the OR operator.</param>
		/// <param name="crl">An optional CRL to check. This parameter can be null (<b>Nothing</b> in Visual Basic).</param>
		/// <returns>One of the <see cref="CertificateStatus"/> values.</returns>
		/// <exception cref="CertificateException">An error occurs while verifying the certificate.</exception>
		/// <remarks>Only the leaf certificate is checked against the CRL.</remarks>
		// Thanks go out to Gabriele Zannoni for implementing this method
		public virtual CertificateStatus VerifyChain(string server, AuthType type, VerificationFlags flags, byte[] crl) {
			CertificateStatus status = VerifyChain(server, type, flags);
			if (status != CertificateStatus.ValidCertificate || crl == null)
				return status;
			try {
				if (!m_Certificate.VerifyRevocation(crl))
					return CertificateStatus.Revoked;
				else
					return status;
			} catch {
				return CertificateStatus.RevocationFailure;
			}
		}
Example #11
0
		/// <summary>
		/// Verifies the end <see cref="Certificate"/> according to the SSL policy rules.
		/// </summary>
		/// <param name="server">The server that returned the certificate -or- a null reference if the certificate is a client certificate.</param>
		/// <param name="type">One of the <see cref="AuthType"/> values.</param>
		/// <param name="flags">One or more of the <see cref="VerificationFlags"/> values. VerificationFlags values can be combined with the OR operator.</param>
		/// <returns>One of the <see cref="CertificateStatus"/> values.</returns>
		/// <exception cref="CertificateException">An error occurs while verifying the certificate.</exception>
		public virtual CertificateStatus VerifyChain(string server, AuthType type, VerificationFlags flags) {
			// Convert the server string to a wide string memory pointer
			IntPtr serverName = IntPtr.Zero;
			IntPtr dataPtr = IntPtr.Zero;
			try {
				if (server == null) {
					serverName = IntPtr.Zero;
				} else {
					serverName = Marshal.StringToHGlobalUni(server);
				}
				// create a HTTPSPolicyCallbackData and get a memory pointer to the structure
				SslPolicyParameters data = new SslPolicyParameters();
				data.cbSize = Marshal.SizeOf(typeof(SslPolicyParameters));
				data.dwAuthType = (int)type;
				data.pwszServerName = serverName;
				data.fdwChecks = (int)flags;
				dataPtr = Marshal.AllocHGlobal(data.cbSize);
				Marshal.StructureToPtr(data, dataPtr, false);
				// create a CERT_CHAIN_POLICY_PARA
				ChainPolicyParameters para = new ChainPolicyParameters();
				para.cbSize = Marshal.SizeOf(typeof(ChainPolicyParameters));
				para.dwFlags = (int)flags;
				para.pvExtraPolicyPara = dataPtr;
				// create a CERT_CHAIN_POLICY_STATUS
				ChainPolicyStatus status = new ChainPolicyStatus();
				status.cbSize = Marshal.SizeOf(typeof(ChainPolicyStatus)); 
				// verify the certificate
				if (SspiProvider.CertVerifyCertificateChainPolicy(new IntPtr(SecurityConstants.CERT_CHAIN_POLICY_SSL), m_Handle, ref para, ref status) == 0)
					throw new CertificateException("Unable to verify the certificate.");
				if (Enum.IsDefined(typeof(CertificateStatus), status.dwError))
					return (CertificateStatus)status.dwError;
				else
					return CertificateStatus.OtherError;
			} finally {
				// clean up
				if (dataPtr != IntPtr.Zero)
					Marshal.FreeHGlobal(dataPtr);
				if (serverName != IntPtr.Zero)
					Marshal.FreeHGlobal(serverName);
			}
		}
        public unsafe int ValidateCertificate(QUIC_BUFFER *certificatePtr, QUIC_BUFFER *chainPtr, out X509Certificate2?certificate)
        {
            SslPolicyErrors sslPolicyErrors   = SslPolicyErrors.None;
            IntPtr          certificateBuffer = 0;
            int             certificateLength = 0;

            X509Chain?       chain  = null;
            X509Certificate2?result = null;

            try
            {
                if (certificatePtr is not null)
                {
                    chain = new X509Chain();
                    if (_certificateChainPolicy != null)
                    {
                        chain.ChainPolicy = _certificateChainPolicy;
                    }
                    else
                    {
                        chain.ChainPolicy.RevocationMode = _revocationMode;
                        chain.ChainPolicy.RevocationFlag = X509RevocationFlag.ExcludeRoot;

                        // TODO: configure chain.ChainPolicy.CustomTrustStore to mirror behavior of SslStream.VerifyRemoteCertificate (https://github.com/dotnet/runtime/issues/73053)
                    }

                    // set ApplicationPolicy unless already provided.
                    if (chain.ChainPolicy.ApplicationPolicy.Count == 0)
                    {
                        // Authenticate the remote party: (e.g. when operating in server mode, authenticate the client).
                        chain.ChainPolicy.ApplicationPolicy.Add(_isClient ? s_serverAuthOid : s_clientAuthOid);
                    }

                    if (MsQuicApi.UsesSChannelBackend)
                    {
                        result = new X509Certificate2((IntPtr)certificatePtr);
                    }
                    else
                    {
                        if (certificatePtr->Length > 0)
                        {
                            certificateBuffer = (IntPtr)certificatePtr->Buffer;
                            certificateLength = (int)certificatePtr->Length;
                            result            = new X509Certificate2(certificatePtr->Span);
                        }

                        if (chainPtr->Length > 0)
                        {
                            X509Certificate2Collection additionalCertificates = new X509Certificate2Collection();
                            additionalCertificates.Import(chainPtr->Span);
                            chain.ChainPolicy.ExtraStore.AddRange(additionalCertificates);
                        }
                    }
                }

                if (result is not null)
                {
                    bool checkCertName = !chain !.ChainPolicy !.VerificationFlags.HasFlag(X509VerificationFlags.IgnoreInvalidName);
                    sslPolicyErrors |= CertificateValidation.BuildChainAndVerifyProperties(chain !, result, checkCertName, !_isClient, _targetHost, certificateBuffer, certificateLength);
                }
                else if (_certificateRequired)
                {
                    sslPolicyErrors |= SslPolicyErrors.RemoteCertificateNotAvailable;
                }

                int status = QUIC_STATUS_SUCCESS;
                if (_validationCallback is not null)
                {
                    if (!_validationCallback(_connection, result, chain, sslPolicyErrors))
                    {
                        if (_isClient)
                        {
                            throw new AuthenticationException(SR.net_quic_cert_custom_validation);
                        }

                        status = QUIC_STATUS_USER_CANCELED;
                    }
                }
                else if (sslPolicyErrors != SslPolicyErrors.None)
                {
                    if (_isClient)
                    {
                        throw new AuthenticationException(SR.Format(SR.net_quic_cert_chain_validation, sslPolicyErrors));
                    }

                    status = QUIC_STATUS_HANDSHAKE_FAILURE;
                }

                certificate = result;
                return(status);
            }
            catch
            {
                result?.Dispose();
                throw;
            }
            finally
            {
                if (chain is not null)
                {
                    X509ChainElementCollection elements = chain.ChainElements;
                    for (int i = 0; i < elements.Count; i++)
                    {
                        elements[i].Certificate.Dispose();
                    }

                    chain.Dispose();
                }
            }
        }