Exemplo n.º 1
0
    def __init__(self, socket, handlers, auth=False,
                 tls=None, tls_immediately=False, tls_wrapper=None,
                 command_timeout=None, data_timeout=None):
        self.handlers = handlers
        self.extensions = Extensions()

        self.io = IO(socket, tls_wrapper)

        self.bannered = False
        self.have_mailfrom = None
        self.have_rcptto = None
        self.ehlo_as = None
        self.authed = False

        self.extensions.add('8BITMIME')
        self.extensions.add('PIPELINING')
        self.extensions.add('ENHANCEDSTATUSCODES')
        self.extensions.add('SMTPUTF8')
        if tls and not tls_immediately:
            self.extensions.add('STARTTLS')
        if auth:
            if isinstance(auth, list):
                auth_obj = SASLAuth(auth)
            else:
                auth_obj = SASLAuth()
            auth_session = AuthSession(auth_obj, self.io)
            self.extensions.add('AUTH', auth_session)

        self.tls = validate_tls(tls, server_side=True)
        self.tls_immediately = tls_immediately

        self.command_timeout = command_timeout
        self.data_timeout = data_timeout or command_timeout
 def test_crammd5_malformed(self):
     self.sock.sendall(b'334 PHRlc3RAZXhhbXBsZS5jb20+\r\n')
     self.sock.recv(IsA(int)).AndReturn(b'bWFsZm9ybWVk\r\n')
     self.mox.ReplayAll()
     auth = AuthSession(SASLAuth(), self.io)
     with self.assertRaises(ServerAuthError):
         auth.server_attempt('CRAM-MD5')
Exemplo n.º 3
0
    def auth(self, authcid, secret, authzid=None, mechanism=None):
        """Negotiates authentication for the current SMTP session. This
        transaction may involve several back-and-forth packets to the server,
        depending on the SASL mechanism used, and this function will only
        return once all have completed.

        :param authcid: The authentication identity, usually the username.
        :param secret: The secret (i.e. password) string to send for the given
                       authentication and authorization identities.
        :param authzid: The authorization identity, if applicable.
        :param mechanism: SASL mechanism name to use instead of the best
                          available.
        :type mechanism: str
        :returns: |Reply| object populated with the response.

        """
        self._flush_pipeline()
        if 'AUTH' not in self.extensions:
            return unknown_command
        advertised = [self._encode(mech_name) for mech_name in
                      self.extensions.getparam('AUTH').split()]
        auth = AuthSession(SASLAuth(advertised), self.io)
        if not mechanism and auth.client_mechanisms:
            mechanism = auth.client_mechanisms[0].name
        return auth.client_attempt(authcid, secret, authzid, mechanism)
Exemplo n.º 4
0
 def test_plain(self):
     self.mox.ReplayAll()
     auth = AuthSession(SASLAuth(), self.io)
     result = auth.server_attempt(b'PLAIN dGVzdHppZAB0ZXN0dXNlcgB0ZXN0cGFzc3dvcmQ=')
     self.assertEqual(u'testuser', result.authcid)
     self.assertEqual(u'testpassword', result.secret)
     self.assertEqual(u'testzid', result.authzid)
 def test_client_bad_mech(self):
     self.sock.sendall(b'AUTH LOGIN\r\n')
     self.sock.recv(IsA(int)).AndReturn(b'535 Nope!\r\n')
     self.mox.ReplayAll()
     auth = AuthSession(SASLAuth(), self.io)
     reply = auth.client_attempt('*****@*****.**', 'asdf', None, 'LOGIN')
     self.assertEqual('535', reply.code)
     self.assertEqual('5.0.0 Nope!', reply.message)
Exemplo n.º 6
0
 def test_client_xoauth2(self):
     self.sock.sendall(b'AUTH XOAUTH2 dXNlcj10ZXN0QGV4YW1wbGUuY29tAWF1dGg9QmVhcmVyYXNkZgEB\r\n')
     self.sock.recv(IsA(int)).AndReturn(b'235 Ok\r\n')
     self.mox.ReplayAll()
     auth = AuthSession(SASLAuth([b'XOAUTH2']), self.io)
     reply = auth.client_attempt(u'*****@*****.**', u'asdf',
                                 None, b'XOAUTH2')
     self.assertEqual('235', reply.code)
     self.assertEqual('2.0.0 Ok', reply.message)
 def test_client_plain(self):
     self.sock.sendall(
         b'AUTH PLAIN amtsAHRlc3RAZXhhbXBsZS5jb20AYXNkZg==\r\n')
     self.sock.recv(IsA(int)).AndReturn(b'235 Ok\r\n')
     self.mox.ReplayAll()
     auth = AuthSession(SASLAuth(), self.io)
     reply = auth.client_attempt('*****@*****.**', 'asdf', 'jkl', 'PLAIN')
     self.assertEqual('235', reply.code)
     self.assertEqual('2.0.0 Ok', reply.message)
 def test_login(self):
     self.sock.sendall(b'334 UGFzc3dvcmQ6\r\n')
     self.sock.recv(IsA(int)).AndReturn(b'dGVzdHBhc3N3b3Jk\r\n')
     self.mox.ReplayAll()
     auth = AuthSession(SASLAuth(), self.io)
     result = auth.server_attempt('LOGIN dGVzdHVzZXI=')
     self.assertEqual(u'testuser', result.authcid)
     self.assertEqual(u'testpassword', result.secret)
     self.assertEqual(None, result.authzid)
Exemplo n.º 9
0
 def test_plain_noarg(self):
     self.sock.sendall(b'334 \r\n')
     self.sock.recv(IsA(int)).AndReturn(b'dGVzdHppZAB0ZXN0dXNlcgB0ZXN0cGFzc3dvcmQ=\r\n')
     self.mox.ReplayAll()
     auth = AuthSession(SASLAuth(), self.io)
     result = auth.server_attempt(b'PLAIN')
     self.assertEqual(u'testuser', result.authcid)
     self.assertEqual(u'testpassword', result.secret)
     self.assertEqual(u'testzid', result.authzid)
 def test_plain_canceled(self):
     self.sock.sendall(b'334 \r\n')
     self.sock.recv(IsA(int)).AndReturn(b'*\r\n')
     self.mox.ReplayAll()
     auth = AuthSession(SASLAuth(), self.io)
     with self.assertRaises(AuthenticationCanceled):
         auth.server_attempt('PLAIN')
     with self.assertRaises(AuthenticationCanceled):
         auth.server_attempt('PLAIN *')
 def test_client_login_bad_username(self):
     self.sock.sendall(b'AUTH LOGIN\r\n')
     self.sock.recv(IsA(int)).AndReturn(b'334 VXNlcm5hbWU6\r\n')
     self.sock.sendall(b'dGVzdEBleGFtcGxlLmNvbQ==\r\n')
     self.sock.recv(IsA(int)).AndReturn(b'535 Nope!\r\n')
     self.mox.ReplayAll()
     auth = AuthSession(SASLAuth(), self.io)
     reply = auth.client_attempt('*****@*****.**', 'asdf', None, 'LOGIN')
     self.assertEqual('535', reply.code)
     self.assertEqual('5.0.0 Nope!', reply.message)
Exemplo n.º 12
0
 def test_crammd5(self):
     self.sock.sendall(b'334 PHRlc3RAZXhhbXBsZS5jb20+\r\n')
     self.sock.recv(IsA(int)).AndReturn(b'dGVzdHVzZXIgNDkzMzA1OGU2ZjgyOTRkZTE0NDJkMTYxOTI3ZGI5NDQ=\r\n')
     self.mox.ReplayAll()
     auth = AuthSession(SASLAuth(), self.io)
     result = auth.server_attempt(b'CRAM-MD5')
     self.assertEqual(u'testuser', result.authcid)
     self.assertTrue(result.check_secret(u'testpassword'))
     self.assertFalse(result.check_secret(u'testwrong'))
     self.assertEqual(None, result.authzid)
Exemplo n.º 13
0
 def test_client_xoauth2_error(self):
     self.sock.sendall(b'AUTH XOAUTH2 dXNlcj10ZXN0QGV4YW1wbGUuY29tAWF1dGg9QmVhcmVyYXNkZgEB\r\n')
     self.sock.recv(IsA(int)).AndReturn(b'334 eyJzdGF0dXMiOiI0MDEiLCJzY2hlbWVzIjoiYmVhcmVyIG1hYyIsInNjb3BlIjoiaHR0cHM6Ly9tYWlsLmdvb2dsZS5jb20vIn0K\r\n')
     self.sock.sendall(b'\r\n')
     self.sock.recv(IsA(int)).AndReturn(b'535 Nope!\r\n')
     self.mox.ReplayAll()
     auth = AuthSession(SASLAuth([b'XOAUTH2']), self.io)
     reply = auth.client_attempt(u'*****@*****.**', u'asdf',
                                 None, b'XOAUTH2')
     self.assertEqual('535', reply.code)
     self.assertEqual('5.0.0 Nope!', reply.message)
Exemplo n.º 14
0
 def test_client_crammd5(self):
     self.sock.sendall(b'AUTH CRAM-MD5\r\n')
     self.sock.recv(IsA(int)).AndReturn(b'334 dGVzdCBjaGFsbGVuZ2U=\r\n')
     self.sock.sendall(b'dGVzdEBleGFtcGxlLmNvbSA1Yzk1OTBjZGE3ZTgxMDY5Mzk2ZjhiYjlkMzU1MzE1Yg==\r\n')
     self.sock.recv(IsA(int)).AndReturn(b'235 Ok\r\n')
     self.mox.ReplayAll()
     auth = AuthSession(SASLAuth(), self.io)
     reply = auth.client_attempt(u'*****@*****.**', u'asdf',
                                 None, b'CRAM-MD5')
     self.assertEqual('235', reply.code)
     self.assertEqual('2.0.0 Ok', reply.message)
 def test_client_login(self):
     self.sock.sendall(b'AUTH LOGIN\r\n')
     self.sock.recv(IsA(int)).AndReturn(b'334 VXNlcm5hbWU6\r\n')
     self.sock.sendall(b'dGVzdEBleGFtcGxlLmNvbQ==\r\n')
     self.sock.recv(IsA(int)).AndReturn(b'334 UGFzc3dvcmQ6\r\n')
     self.sock.sendall(b'YXNkZg==\r\n')
     self.sock.recv(IsA(int)).AndReturn(b'235 Ok\r\n')
     self.mox.ReplayAll()
     auth = AuthSession(SASLAuth(), self.io)
     reply = auth.client_attempt('*****@*****.**', 'asdf', None, 'LOGIN')
     self.assertEqual('235', reply.code)
     self.assertEqual('2.0.0 Ok', reply.message)
 def test_auth(self):
     self.sock.sendall(b'220 ESMTP server\r\n')
     self.sock.recv(IsA(int)).AndReturn(b'EHLO there\r\n')
     self.sock.sendall(b'250-Hello there\r\n250 AUTH PLAIN\r\n')
     self.sock.recv(IsA(int)).AndReturn(
         b'AUTH PLAIN dGVzdHppZAB0ZXN0dXNlcgB0ZXN0cGFzc3dvcmQ=\r\n')
     self.sock.sendall(b'235 2.7.0 Authentication successful\r\n')
     self.sock.recv(IsA(int)).AndReturn(b'QUIT\r\n')
     self.sock.sendall(b'221 2.0.0 Bye\r\n')
     self.mox.ReplayAll()
     s = Server(self.sock, None)
     s.extensions.reset()
     s.extensions.add('AUTH', AuthSession(SASLAuth([b'PLAIN']), s.io))
     s.handle()
     self.assertTrue(s.authed)
Exemplo n.º 17
0
    def auth(self, authcid, secret, authzid=None, mechanism='PLAIN'):
        """Negotiates authentication for the current SMTP session. This
        transaction may involve several back-and-forth packets to the server,
        depending on the SASL mechanism used, and this function will only
        return once all have completed.

        :param authcid: The authentication identity, usually the username.
        :param secret: The secret (i.e. password) string to send for the given
                       authentication and authorization identities.
        :param authzid: The authorization identity, if applicable.
        :param mechanism: SASL mechanism name to use for authentication.
        :type mechanism: str
        :returns: |Reply| object populated with the response.

        """
        self._flush_pipeline()
        auth = AuthSession(SASLAuth(), self.io)
        return auth.client_attempt(authcid, secret, authzid, mechanism)
Exemplo n.º 18
0
 def insecure_auth(self) -> SASLAuth:
     return SASLAuth.plaintext()
Exemplo n.º 19
0
 def initial_auth(self) -> SASLAuth:
     if self._reject_insecure_auth:
         return SASLAuth([])
     else:
         return self.insecure_auth
Exemplo n.º 20
0
 def insecure_auth(self) -> SASLAuth:
     return SASLAuth.plaintext()
Exemplo n.º 21
0
 def test_bytes(self):
     auth = AuthSession(SASLAuth(), self.io)
     self.assertEqual('PLAIN LOGIN CRAM-MD5', str(auth))
 def test_str(self):
     auth = AuthSession(SASLAuth(), self.io)
     self.assertEqual('CRAM-MD5 LOGIN PLAIN', str(auth))
 def test_invalid_mechanism(self):
     auth = AuthSession(SASLAuth(), self.io)
     with self.assertRaises(InvalidMechanismError):
         auth.server_attempt('TEST')
     with self.assertRaises(InvalidMechanismError):
         auth.server_attempt('B@D')