[PATCH] Provide a workaround for misconfigured Google Apps domains

Alex Vandiver alexmv at bestpractical.com
Wed May 26 06:06:34 UTC 2010


Interoperability with Google Apps For Your Domain can cause headaches;
if the administrator fails to add the requisite SRV records,
federation with other domains will obviously fail.  However, they will
be able to chat with other Google Talk users, so jabber will appear to
"work" from their point of view.

This adds a configuration option to delegate a SRV lookup to
gmail.com, when a domain lacking SRV records is likely a Google Apps
domain (judged based on the MX records on it).  As this option is a
heuristic, and attempts to compensate for flaws in other domains, it
is disabled by default.
---
 lib/DJabberd.pm         |    5 +++++
 lib/DJabberd/Config.pod |   11 +++++++++++
 lib/DJabberd/DNS.pm     |   44 +++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 59 insertions(+), 1 deletions(-)

diff --git a/lib/DJabberd.pm b/lib/DJabberd.pm
index a168fdb..788f609 100644
--- a/lib/DJabberd.pm
+++ b/lib/DJabberd.pm
@@ -121,6 +121,11 @@ sub set_config_sslcertificatefile {
 sub ssl_private_key_file { return $_[0]{ssl_private_key_file} }
 sub ssl_cert_file        { return $_[0]{ssl_cert_file}        }
 
+sub set_config_intuitgafyd {
+    my ($self, $val) = @_;
+    $DJabberd::GAFYD = as_bool($val);
+}
+
 sub set_config_oldssl {
     my ($self, $val) = @_;
     $self->{old_ssl} = as_bool($val);
diff --git a/lib/DJabberd/Config.pod b/lib/DJabberd/Config.pod
index a312b2b..e99cbfd 100644
--- a/lib/DJabberd/Config.pod
+++ b/lib/DJabberd/Config.pod
@@ -143,6 +143,17 @@ description; this is used for client service auto-discovery.
 If set, requires that clients have negotiated a TLS before
 authentication information is sent.
 
+=head2 IntuitGAFYD C<boolean>
+
+Interoperability with Google Apps For Your Domain can cause headaches;
+if the administrator fails to add the requisite SRV records,
+federation with other domains will obviously fail.  However, they will
+be able to chat with other Google Talk users, so jabber will appear to
+"work" from their point of view.  Turning this boolean on (it defaults
+to off) will detect misconfigured GAFYD domains (detected by examining
+their MX record) and return whatever C<gmail.com> would return for
+that SRV lookup.
+
 
 
 =head1 PLUGIN CONFIGURATION
diff --git a/lib/DJabberd/DNS.pm b/lib/DJabberd/DNS.pm
index 5a7e4a1..c5fcb36 100644
--- a/lib/DJabberd/DNS.pm
+++ b/lib/DJabberd/DNS.pm
@@ -57,10 +57,32 @@ sub srv {
         );
     };
 
+    my $gafyd = sub {
+        my @values = @_;
+        return $callback->(@values) if @values;
+        DJabberd::DNS->resolve(
+            type     => "MX",
+            domain   => $hostname,
+            port     => $port,
+            callback => sub {
+                # If we get nothing, fall back to the A lookup
+                return $try_a->() unless grep {$_->name eq "aspmx.l.google.com"} @_;
+                # Otherwise, reprise on gmail.com
+                $logger->debug("Has a GAFYD MX, trying gtalk's server");
+                return DJabberd::DNS->srv(
+                    domain   => "gmail.com",
+                    service  => $service,
+                    port     => $port,
+                    callback => $callback,
+                );
+            }
+        );
+    };
+
     $class->resolve(
         type     => 'SRV',
         domain   => "$service.$hostname",
-        callback => $try_a,
+        callback => $DJabberd::GAFYD ? $gafyd : $try_a,
         port     => $port,
     );
 }
@@ -226,7 +248,27 @@ sub event_read_srv {
     DJabberd::DNS->new(hostname => $targets[0]->target,
                        port     => $targets[0]->port,
                        callback => $cb);
+}
+
+sub event_read_mx {
+    my $self = shift;
+
+    my $cb = $self->{callback};
+    my @ans = $self->read_packets;
+
+    my @targets = sort {
+        $a->preference <=> $b->preference
+    } grep { ref $_ eq "Net::DNS::RR::MX" } @ans;
+
     $self->close;
+
+    return $cb->() unless @targets;
+
+    # FIXME:  we only do the first target now.  should do a chain.
+    $logger->debug("DNS socket for 'MX' found stuff, now doing hostname lookup on " . $targets[0]->exchange);
+    DJabberd::DNS->new(hostname => $targets[0]->exchange,
+                       port     => $self->{port},
+                       callback => $cb);
 }
 
 package DJabberd::IPEndPoint;
-- 
1.7.0.4



More information about the Djabberd mailing list