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

Reply via email to