change hard coding of AF_UNSPEC to user-defined address-families per repository

Some environments that return AAAA records for their IMAP servers can pose
problems for clients that do not have end-to-end IPv6 connectivity for a number
of reasons (e.g. policy, lack of full routing, security, etc..)

Even with a fallback mechanism in place, you can still arrive at IMAP
implementations that could prevent authentication from unknown IPv6 space. This
in itself is not enough to fallback to IPv4 since there is an actual connection
on that socket.

This change is for introducing a user-defined value:

  [Repository imap-remote]
  ipv6 = no

to create a preference per repository on which AF to connect to the remote
server on

ipv6 = yes (AF_INET6)
ipv6 = no (AF_INET)
unspecified = default

Signed-off-by: Ebben Aries <e@dscp.org>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
This commit is contained in:
Ebben Aries 2016-02-22 17:45:18 -07:00 committed by Nicolas Sebrecht
parent 8f94ef1973
commit 9bfd610230
3 changed files with 20 additions and 1 deletions

View File

@ -74,7 +74,7 @@ class UsefulIMAPMixIn(object):
"""open_socket()
Open socket choosing first address family available."""
msg = (-1, 'could not open socket')
for res in socket.getaddrinfo(self.host, self.port, socket.AF_UNSPEC, socket.SOCK_STREAM):
for res in socket.getaddrinfo(self.host, self.port, self.af, socket.SOCK_STREAM):
af, socktype, proto, canonname, sa = res
try:
# use socket of our own, possiblly socksified socket.
@ -175,6 +175,9 @@ class WrappedIMAP4_SSL(UsefulIMAPMixIn, IMAP4_SSL):
"""Improved version of imaplib.IMAP4_SSL overriding select()."""
def __init__(self, *args, **kwargs):
if "af" in kwargs:
self.af = kwargs['af']
del kwargs['af']
if "use_socket" in kwargs:
self.socket = kwargs['use_socket']
del kwargs['use_socket']
@ -209,6 +212,9 @@ class WrappedIMAP4(UsefulIMAPMixIn, IMAP4):
"""Improved version of imaplib.IMAP4 overriding select()."""
def __init__(self, *args, **kwargs):
if "af" in kwargs:
self.af = kwargs['af']
del kwargs['af']
if "use_socket" in kwargs:
self.socket = kwargs['use_socket']
del kwargs['use_socket']

View File

@ -23,6 +23,7 @@ import base64
import json
import urllib
import socket
import time
import errno
from sys import exc_info
@ -80,6 +81,13 @@ class IMAPServer:
self.goodpassword = None
self.usessl = repos.getssl()
self.useipv6 = repos.getipv6()
if self.useipv6 == True:
self.af = socket.AF_INET6
elif self.useipv6 == False:
self.af = socket.AF_INET
else:
self.af = socket.AF_UNSPEC
self.hostname = \
None if self.preauth_tunnel else repos.gethost()
self.port = repos.getport()
@ -487,6 +495,7 @@ class IMAPServer:
fingerprint=self.fingerprint,
use_socket=self.proxied_socket,
tls_level=self.tlslevel,
af=self.af,
)
else:
self.ui.connecting(self.hostname, self.port)
@ -494,6 +503,7 @@ class IMAPServer:
self.hostname, self.port,
timeout=socket.getdefaulttimeout(),
use_socket=self.proxied_socket,
af=self.af,
)
if not self.preauth_tunnel:

View File

@ -194,6 +194,9 @@ class IMAPRepository(BaseRepository):
return self.getconfint('remoteport', None)
def getipv6(self):
return self.getconfboolean('ipv6', None)
def getssl(self):
return self.getconfboolean('ssl', 1)