summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'Swiften/TLS/ServerIdentityVerifier.cpp')
-rw-r--r--Swiften/TLS/ServerIdentityVerifier.cpp83
1 files changed, 83 insertions, 0 deletions
diff --git a/Swiften/TLS/ServerIdentityVerifier.cpp b/Swiften/TLS/ServerIdentityVerifier.cpp
new file mode 100644
index 0000000..05efd31
--- /dev/null
+++ b/Swiften/TLS/ServerIdentityVerifier.cpp
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2010 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include "Swiften/TLS/ServerIdentityVerifier.h"
+
+#include "Swiften/Base/foreach.h"
+#include "Swiften/IDN/IDNA.h"
+
+namespace Swift {
+
+ServerIdentityVerifier::ServerIdentityVerifier(const JID& jid) {
+ domain = jid.getDomain();
+ encodedDomain = IDNA::getEncoded(domain);
+}
+
+bool ServerIdentityVerifier::certificateVerifies(Certificate::ref certificate) {
+ bool hasSAN = false;
+
+ // DNS names
+ std::vector<String> dnsNames = certificate->getDNSNames();
+ foreach (const String& dnsName, dnsNames) {
+ if (matchesDomain(dnsName)) {
+ return true;
+ }
+ }
+ hasSAN |= !dnsNames.empty();
+
+ // SRV names
+ std::vector<String> srvNames = certificate->getSRVNames();
+ foreach (const String& srvName, srvNames) {
+ // Only match SRV names that begin with the service; this isn't required per
+ // spec, but we're being purist about this.
+ if (srvName.beginsWith("_xmpp-client.") && matchesDomain(srvName.getSubstring(String("_xmpp-client.").getUTF8Size(), srvName.npos()))) {
+ return true;
+ }
+ }
+ hasSAN |= !srvNames.empty();
+
+ // XmppAddr
+ std::vector<String> xmppAddresses = certificate->getXMPPAddresses();
+ foreach (const String& xmppAddress, xmppAddresses) {
+ if (matchesAddress(xmppAddress)) {
+ return true;
+ }
+ }
+ hasSAN |= !xmppAddresses.empty();
+
+ // CommonNames. Only check this if there was no SAN (according to spec).
+ if (!hasSAN) {
+ std::vector<String> commonNames = certificate->getCommonNames();
+ foreach (const String& commonName, commonNames) {
+ if (matchesDomain(commonName)) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+bool ServerIdentityVerifier::matchesDomain(const String& s) {
+ if (s.beginsWith("*.")) {
+ String matchString(s.getSubstring(2, s.npos()));
+ String matchDomain = encodedDomain;
+ int dotIndex = matchDomain.find('.');
+ if (dotIndex >= 0) {
+ matchDomain = matchDomain.getSubstring(dotIndex + 1, matchDomain.npos());
+ }
+ return matchString == matchDomain;
+ }
+ else {
+ return s == encodedDomain;
+ }
+}
+
+bool ServerIdentityVerifier::matchesAddress(const String& s) {
+ return s == domain;
+}
+
+}