Exemple #1
0
		private bool ProcessCrlEntryExtensions (MX.X509Crl.X509CrlEntry entry)
		{
			foreach (MX.X509Extension ext in entry.Extensions) {
				if (ext.Critical) {
					switch (ext.Oid) {
					case "2.5.29.21": // cRLReason
						// we processed/know about this extension
						break;
					default:
						return false;
					}
				}
			}
			return true;
		}
Exemple #2
0
		static MX.X509Crl CheckCrls (string subject, string ski, MX.X509Store store)
		{
			if (store == null)
				return null;

			var crls = store.Crls;
			foreach (MX.X509Crl crl in crls) {
				if (crl.IssuerName == subject && (ski.Length == 0 || ski == GetAuthorityKeyIdentifier (crl)))
					return crl;
			}
			return null; // No CRL found
		}
Exemple #3
0
		private bool ProcessCrlExtensions (MX.X509Crl crl)
		{
			foreach (MX.X509Extension ext in crl.Extensions) {
				if (ext.Critical) {
					switch (ext.Oid) {
					case "2.5.29.20": // cRLNumber
					case "2.5.29.35": // authorityKeyIdentifier
						// we processed/know about this extension
						break;
					default:
						return false;
					}
				}
			}
			return true;
		}
Exemple #4
0
		// but anyway System.dll v2 doesn't expose CRL in any way so...
		static string GetAuthorityKeyIdentifier (MX.X509Crl crl)
		{
			return GetAuthorityKeyIdentifier (crl.Extensions ["2.5.29.35"]);
		}
Exemple #5
0
		static string GetAuthorityKeyIdentifier (MX.X509Extension ext)
		{
			if (ext == null)
				return String.Empty;
			MX.Extensions.AuthorityKeyIdentifierExtension aki = new MX.Extensions.AuthorityKeyIdentifierExtension (ext);
			byte[] id = aki.Identifier;
			if (id == null)	
				return String.Empty;
			StringBuilder sb = new StringBuilder ();
			foreach (byte b in id)
				sb.Append (b.ToString ("X02"));
			return sb.ToString ();
		}
Exemple #6
0
			// Used when the obsolete ICertificatePolicy is set to DefaultCertificatePolicy
			// and the new ServerCertificateValidationCallback is not null
			internal ValidationResult ValidateChain (MSX.X509CertificateCollection certs)
			{
				// user_denied is true if the user callback is called and returns false
				bool user_denied = false;
				if (certs == null || certs.Count == 0)
					return null;

				ICertificatePolicy policy = ServicePointManager.CertificatePolicy;
				RemoteCertificateValidationCallback cb = ServicePointManager.ServerCertificateValidationCallback;

				X509Certificate2 leaf = new X509Certificate2 (certs [0].RawData);
				int status11 = 0; // Error code passed to the obsolete ICertificatePolicy callback
				SslPolicyErrors errors = 0;
				X509Chain chain = null;
				bool result = false;
#if MONOTOUCH
				// The X509Chain is not really usable with MonoTouch (since the decision is not based on this data)
				// However if someone wants to override the results (good or bad) from iOS then they will want all
				// the certificates that the server provided (which generally does not include the root) so, only  
				// if there's a user callback, we'll create the X509Chain but won't build it
				// ref: https://bugzilla.xamarin.com/show_bug.cgi?id=7245
				if (cb != null) {
#endif
				chain = new X509Chain ();
				chain.ChainPolicy = new X509ChainPolicy ();
#if !MONOTOUCH
				chain.ChainPolicy.RevocationMode = revocation_mode;
#endif
				for (int i = 1; i < certs.Count; i++) {
					X509Certificate2 c2 = new X509Certificate2 (certs [i].RawData);
					chain.ChainPolicy.ExtraStore.Add (c2);
				}
#if MONOTOUCH
				}
#else
				try {
					if (!chain.Build (leaf))
						errors |= GetErrorsFromChain (chain);
				} catch (Exception e) {
					Console.Error.WriteLine ("ERROR building certificate chain: {0}", e);
					Console.Error.WriteLine ("Please, report this problem to the Mono team");
					errors |= SslPolicyErrors.RemoteCertificateChainErrors;
				}

				// for OSX and iOS we're using the native API to check for the SSL server policy and host names
				if (!is_macosx) {
					if (!CheckCertificateUsage (leaf)) {
						errors |= SslPolicyErrors.RemoteCertificateChainErrors;
						status11 = -2146762490; //CERT_E_PURPOSE 0x800B0106
					}

					if (!CheckServerIdentity (certs [0], Host)) {
						errors |= SslPolicyErrors.RemoteCertificateNameMismatch;
						status11 = -2146762481; // CERT_E_CN_NO_MATCH 0x800B010F
					}
				} else {
#endif
					// Attempt to use OSX certificates
					// Ideally we should return the SecTrustResult
					OSX509Certificates.SecTrustResult trustResult = OSX509Certificates.SecTrustResult.Deny;
					try {
						trustResult = OSX509Certificates.TrustEvaluateSsl (certs, Host);
						// We could use the other values of trustResult to pass this extra information
						// to the .NET 2 callback for values like SecTrustResult.Confirm
						result = (trustResult == OSX509Certificates.SecTrustResult.Proceed ||
								  trustResult == OSX509Certificates.SecTrustResult.Unspecified);
					} catch {
						// Ignore
					}
					
					if (result) {
						// TrustEvaluateSsl was successful so there's no trust error
						// IOW we discard our own chain (since we trust OSX one instead)
						errors = 0;
					} else {
						// callback and DefaultCertificatePolicy needs this since 'result' is not specified
						status11 = (int) trustResult;
						errors |= SslPolicyErrors.RemoteCertificateChainErrors;
					}
#if !MONOTOUCH
				}
#endif

#if MONODROID && SECURITY_DEP
				result = AndroidPlatform.TrustEvaluateSsl (certs, sender, leaf, chain, errors);
				if (result) {
					// chain.Build() + GetErrorsFromChain() (above) will ALWAYS fail on
					// Android (there are no mozroots or preinstalled root certificates),
					// thus `errors` will ALWAYS have RemoteCertificateChainErrors.
					// Android just verified the chain; clear RemoteCertificateChainErrors.
					errors  &= ~SslPolicyErrors.RemoteCertificateChainErrors;
				}
#endif

				if (policy != null && (!(policy is DefaultCertificatePolicy) || cb == null)) {
					ServicePoint sp = null;
					HttpWebRequest req = sender as HttpWebRequest;
					if (req != null)
						sp = req.ServicePointNoLock;
					if (status11 == 0 && errors != 0)
						status11 = GetStatusFromChain (chain);

					// pre 2.0 callback
					result = policy.CheckValidationResult (sp, leaf, req, status11);
					user_denied = !result && !(policy is DefaultCertificatePolicy);
				}
				// If there's a 2.0 callback, it takes precedence
				if (cb != null) {
					result = cb (sender, leaf, chain, errors);
					user_denied = !result;
				}
				return new ValidationResult (result, user_denied, status11);
			}
Exemple #7
0
			// RFC2818 - HTTP Over TLS, Section 3.1
			// http://www.ietf.org/rfc/rfc2818.txt
			// 
			// 1.	if present MUST use subjectAltName dNSName as identity
			// 1.1.		if multiples entries a match of any one is acceptable
			// 1.2.		wildcard * is acceptable
			// 2.	URI may be an IP address -> subjectAltName.iPAddress
			// 2.1.		exact match is required
			// 3.	Use of the most specific Common Name (CN=) in the Subject
			// 3.1		Existing practice but DEPRECATED
			static bool CheckServerIdentity (MSX.X509Certificate cert, string targetHost) 
			{
				try {
					MSX.X509Extension ext = cert.Extensions ["2.5.29.17"];
					// 1. subjectAltName
					if (ext != null) {
						SubjectAltNameExtension subjectAltName = new SubjectAltNameExtension (ext);
						// 1.1 - multiple dNSName
						foreach (string dns in subjectAltName.DNSNames) {
							// 1.2 TODO - wildcard support
							if (Match (targetHost, dns))
								return true;
						}
						// 2. ipAddress
						foreach (string ip in subjectAltName.IPAddresses) {
							// 2.1. Exact match required
							if (ip == targetHost)
								return true;
						}
					}
					// 3. Common Name (CN=)
					return CheckDomainName (cert.SubjectName, targetHost);
				} catch (Exception e) {
					Console.Error.WriteLine ("ERROR processing certificate: {0}", e);
					Console.Error.WriteLine ("Please, report this problem to the Mono team");
					return false;
				}
			}
		internal ValidationResult ValidateChain (string host, MSX.X509CertificateCollection certs)
		{
			try {
				var certs2 = Convert (certs);
				var result = ValidateChain (host, certs2, 0);
				if (tlsStream != null)
					tlsStream.CertificateValidationFailed = result == null || !result.Trusted || result.UserDenied;
				return result;
			} catch {
				if (tlsStream != null)
					tlsStream.CertificateValidationFailed = true;
				throw;
			}
		}
		static X509Certificate2Collection Convert (MSX.X509CertificateCollection certificates)
		{
			if (certificates == null)
				return null;

			var certs2 = new X509Certificate2Collection ();
			for (int i = 0; i < certificates.Count; i++)
				certs2.Add (new X509Certificate2 (certificates [i].RawData));
			return certs2;
		}
Exemple #10
0
		internal static bool TrustEvaluateSsl (MSX.X509CertificateCollection collection, object sender, X509Certificate2 certificate, X509Chain chain, SslPolicyErrors errors)
		{
			if (trustEvaluateSsl2 != null)
				return trustEvaluateSsl2 (collection, sender, certificate, chain, errors);
			return trustEvaluateSsl (collection);
		}
Exemple #11
0
		public static SecTrustResult TrustEvaluateSsl (MSX.X509CertificateCollection certificates, string host)
		{
			if (certificates == null)
				return SecTrustResult.Deny;

			try {
				return _TrustEvaluateSsl (certificates, host);
			} catch {
				return SecTrustResult.Deny;
			}
		}
Exemple #12
0
		static SecTrustResult _TrustEvaluateSsl (MSX.X509CertificateCollection certificates, string hostName)
		{
			int certCount = certificates.Count;
			IntPtr [] cfDataPtrs = new IntPtr [certCount];
			IntPtr [] secCerts = new IntPtr [certCount];
			IntPtr certArray = IntPtr.Zero;
			IntPtr sslsecpolicy = IntPtr.Zero;
			IntPtr host = IntPtr.Zero;
			IntPtr sectrust = IntPtr.Zero;
			SecTrustResult result = SecTrustResult.Deny;

			try {
				for (int i = 0; i < certCount; i++)
					cfDataPtrs [i] = MakeCFData (certificates [i].RawData);
				
				for (int i = 0; i < certCount; i++){
					secCerts [i] = SecCertificateCreateWithData (IntPtr.Zero, cfDataPtrs [i]);
					if (secCerts [i] == IntPtr.Zero)
						return SecTrustResult.Deny;
				}
				certArray = FromIntPtrs (secCerts);
				host = CFStringCreateWithCharacters (IntPtr.Zero, hostName, hostName.Length);
				sslsecpolicy = SecPolicyCreateSSL (true, host);

				int code = SecTrustCreateWithCertificates (certArray, sslsecpolicy, out sectrust);
				if (code == 0)
					code = SecTrustEvaluate (sectrust, out result);
				return result;
			} finally {
				for (int i = 0; i < certCount; i++)
					if (cfDataPtrs [i] != IntPtr.Zero)
						CFRelease (cfDataPtrs [i]);

				if (certArray != IntPtr.Zero)
					CFRelease (certArray);
				
				for (int i = 0; i < certCount; i++)
					if (secCerts [i] != IntPtr.Zero)
						CFRelease (secCerts [i]);

				if (sslsecpolicy != IntPtr.Zero)
					CFRelease (sslsecpolicy);
				if (host != IntPtr.Zero)
					CFRelease (host);
				if (sectrust != IntPtr.Zero)
					CFRelease (sectrust);
			}
		}