Update of /cvsroot/tmda/tmda/bin
In directory usw-pr-cvs1:/tmp/cvs-serv2544/bin
Modified Files:
ChangeLog tmda-ofmipd
Log Message:
Add new authentication sources for tmda-ofmipd. Authenticate
against a pop3, imap, or imaps server using the `-R' option.
Patch contributed by David Guerizec in
<[EMAIL PROTECTED]> on tmda-workers.
Index: ChangeLog
===================================================================
RCS file: /cvsroot/tmda/tmda/bin/ChangeLog,v
retrieving revision 1.225
retrieving revision 1.226
diff -u -r1.225 -r1.226
--- ChangeLog 21 Aug 2002 22:37:42 -0000 1.225
+++ ChangeLog 2 Sep 2002 01:23:53 -0000 1.226
@@ -1,3 +1,8 @@
+2002-09-01 Jason R. Mastaler <[EMAIL PROTECTED]>
+
+ * tmda-ofmipd: Add -R option for authentication against a pop3,
+ imap or imaps server.
+
2002-08-21 Jason R. Mastaler <[EMAIL PROTECTED]>
* tmda-rfilter (autorespond_to_sender): New function. Determine
Index: tmda-ofmipd
===================================================================
RCS file: /cvsroot/tmda/tmda/bin/tmda-ofmipd,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -r1.13 -r1.14
--- tmda-ofmipd 25 Jul 2002 22:49:09 -0000 1.13
+++ tmda-ofmipd 2 Sep 2002 01:23:53 -0000 1.14
@@ -55,6 +55,14 @@
default is FQDN:8025 (i.e, port 8025 on the fully qualified
domain name for the local host).
+ -R proto[://host[:port]]
+ --remoteauth proto[://host[:port]]
+ Host to connect to to check username and password.
+ - proto can be one of imap, imaps (ssl) or pop3
+ - host defaults to localhost
+ - port defaults to 143 (imap), 993 (imaps) or 110 (pop3)
+ Example: -R imaps://myimapserver.net
+
-A <program>
--authprog <program>
checkpassword compatible command used to check username/password. e.g,
@@ -112,6 +120,16 @@
program = sys.argv[0]
configdir = None
authprog = None
+remoteauth = { 'proto': None,
+ 'host': 'localhost',
+ 'port': None,
+ 'enable': 0,
+ }
+defaultauthports = { 'imap': 143,
+ 'imaps': 993,
+ 'pop3': 110,
+ # 'pop3s': 995,
+ }
connections = 20
if os.getuid() == 0:
@@ -158,15 +176,16 @@
try:
opts, args = getopt.getopt(sys.argv[1:],
- 'p:u:A:a:c:C:dVh', ['proxyport=',
- 'username=',
- 'authfile=',
- 'authprog=',
- 'configdir=',
- 'connections=',
- 'debug',
- 'version',
- 'help'])
+ 'p:u:R:A:a:c:C:dVh', ['proxyport=',
+ 'username=',
+ 'authfile=',
+ 'remoteauth=',
+ 'authprog=',
+ 'configdir=',
+ 'connections=',
+ 'debug',
+ 'version',
+ 'help'])
except getopt.error, msg:
usage(1, msg)
@@ -185,6 +204,30 @@
proxyport = arg
elif opt in ('-u', '--username'):
username = arg
+ elif opt in ('-R', '--remoteauth'):
+ # arg is like: imap://host:port
+ try:
+ authproto, arg = arg.split('://', 1)
+ except ValueError:
+ authproto, arg = arg, None
+ remoteauth['proto'] = authproto
+ remoteauth['port'] = defaultauthports[authproto]
+ if authproto not in defaultauthports.keys():
+ raise ValueError, 'Protocole not supported: ' + authproto + \
+ '\nPlease pick one of ' + repr(defaultauthports.keys())
+ if arg:
+ try:
+ authhost, authport = arg.split(':', 1)
+ except ValueError:
+ authhost = arg
+ authport = defaultauthports[authproto]
+ if authhost:
+ remoteauth['host'] = authhost
+ if authport:
+ remoteauth['port'] = authport
+ print >> DEBUGSTREAM, "auth method: %s://%s:%s" % \
+ (remoteauth['proto'], remoteauth['host'], remoteauth['port'])
+ remoteauth['enable'] = 1
elif opt in ('-A', '--authprog'):
authprog = arg
elif opt in ('-a', '--authfile'):
@@ -235,6 +278,7 @@
def run_authprog(username, password):
"""authprog should return 0 for auth ok, and a positive integer in
case of a problem."""
+ print >> DEBUGSTREAM, "Trying authprog method"
return pipecmd('%s' % authprog, '%s\0%s\0' % (username, password))
@@ -248,6 +292,104 @@
("\\", "\\\\").replace("'", "'\\\\\\''"))
return rcpttos_quoted
+if remoteauth['proto'] == 'imaps':
+ vmaj, vmin = sys.version_info[:2]
+ # Python version 2.2 and before don't have IMAP4_SSL
+ import imaplib
+ if vmaj <= 2 or (vmaj == 2 and vmin <= 2):
+ class IMAP4_SSL(imaplib.IMAP4):
+ # extends IMAP4 class to talk SSL cause it's not yet
+ # implemented in python 2.2
+ def open(self, host, port):
+ """Setup connection to remote server on "host:port".
+ This connection will be used by the routines:
+ read, readline, send, shutdown.
+ """
+ self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ self.sock.connect((self.host, self.port))
+ self.sslsock = socket.ssl(self.sock)
+ self.file = self.sock.makefile('rb')
+
+ def read(self, size):
+ """Read 'size' bytes from remote."""
+ buf = self.sslsock.read(size)
+ return buf
+
+ def readline(self):
+ """Read line from remote."""
+ line = [ ]
+ c = self.sslsock.read(1)
+ while c:
+ line.append(c)
+ if c == '\n':
+ break
+ c = self.sslsock.read(1)
+ buf = ''.join(line)
+ return buf
+
+ def send(self, data):
+ """Send data to remote."""
+ bytes = len(data)
+ while bytes > 0:
+ sent = self.sslsock.write(data)
+ if sent == bytes:
+ break # avoid copy
+ data = data[sent:]
+ bytes = bytes - sent
+ else:
+ IMAP4_SSL = imaplib.IMAP4_SSL
+
+
+def run_remoteauth(username, password):
+ print >> DEBUGSTREAM, "trying %s connection to %s@%s:%s" % \
+ (remoteauth['proto'], username, remoteauth['host'],
+ remoteauth['port'])
+ port = defaultauthports[remoteauth['proto']]
+ if remoteauth['proto'] == 'imap':
+ import imaplib
+ if remoteauth['port']:
+ port = int(remoteauth['port'])
+ M = imaplib.IMAP4(remoteauth['host'], port)
+ try:
+ M.login(username, password)
+ M.logout()
+ return 1
+ except:
+ print >> DEBUGSTREAM, "imap connection to %s@%s failed" % \
+ (username, remoteauth['host'])
+ return 0
+ elif remoteauth['proto'] == 'pop3':
+ import poplib
+ if remoteauth['port']:
+ port = int(remoteauth['port'])
+ M = poplib.POP3(remoteauth['host'], port)
+ try:
+ M.user(username)
+ M.pass_(password)
+ M.quit()
+ return 1
+ except:
+ print >> DEBUGSTREAM, "pop3 connection to %s@%s failed" % \
+ (username, remoteauth['host'])
+ return 0
+ elif remoteauth['proto'] == 'imaps':
+ import imaplib
+ if remoteauth['port']:
+ port = int(remoteauth['port'])
+ M = IMAP4_SSL(remoteauth['host'], port)
+ try:
+ M.login(username, password)
+ M.logout()
+ return 1
+ except:
+ print >> DEBUGSTREAM, "imaps connection to %s@%s failed" % \
+ (username, remoteauth['host'])
+ return 0
+ # proto not implemented
+ print >> DEBUGSTREAM, "Error: protocole %s not implemented" % \
+ remoteauth['proto']
+ return 0
+
def authfile2dict(authfile):
"""Iterate over a tmda-ofmipd authentication file, and return a
@@ -330,8 +472,12 @@
return 501
self.__auth_username = username.lower()
self.__auth_password = password
+ if remoteauth['enable']:
+ # Try first with the remote auth
+ if run_remoteauth(username, password):
+ return 1
if authprog:
- # Try first with the authprog
+ # Then with the authprog
if run_authprog(username, password) == 0:
return 1
# Now we can fall back on the authfile
@@ -353,8 +499,12 @@
return 0
self.__auth_username = username.lower()
self.__auth_password = password
+ if remoteauth['enable']:
+ # Try first with the remote auth
+ if run_remoteauth(username, password):
+ return 1
if authprog:
- # Try first with the authprog
+ # Then with the authprog
if run_authprog(username, password) == 0:
return 1
# Now we can fall back on the authfile
_______________________________________
tmda-cvs mailing list
http://tmda.net/lists/listinfo/tmda-cvs