~openerp-commiter/openobject-addons/extra-6.0

« back to all changes in this revision

Viewing changes to document_sftp/sftp_server/AuthHandler.py

  • Committer: Fabien Pinckaers
  • Date: 2009-04-22 19:24:14 UTC
  • mfrom: (3589.8.19 trunk-extra-addons)
  • Revision ID: fp@tinyerp.com-20090422192414-rke20j736h6dx9j7
adding_test_server

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# -*- encoding: utf-8 -*-
2
 
##############################################################################
3
 
#
4
 
#    OpenERP, Open Source Management Solution   
5
 
#    Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>). All Rights Reserved
6
 
#    $Id$
7
 
#
8
 
#    This program is free software: you can redistribute it and/or modify
9
 
#    it under the terms of the GNU General Public License as published by
10
 
#    the Free Software Foundation, either version 3 of the License, or
11
 
#    (at your option) any later version.
12
 
#
13
 
#    This program is distributed in the hope that it will be useful,
14
 
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 
#    GNU General Public License for more details.
17
 
#
18
 
#    You should have received a copy of the GNU General Public License
19
 
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20
 
#
21
 
##############################################################################
22
 
 
23
 
import paramiko
24
 
class AuthHandler (paramiko.AuthHandler):
25
 
    """
26
 
    Internal class to handle the mechanics of authentication.
27
 
    """
28
 
    def _parse_userauth_request(self, m):
29
 
        if not self.transport.server_mode:
30
 
            # er, uh... what?
31
 
            m = Message()
32
 
            m.add_byte(chr(MSG_USERAUTH_FAILURE))
33
 
            m.add_string('none')
34
 
            m.add_boolean(0)
35
 
            self.transport._send_message(m)
36
 
            return
37
 
        if self.authenticated:
38
 
            # ignore
39
 
            return
40
 
        username = m.get_string()
41
 
        service = m.get_string()
42
 
        method = m.get_string()
43
 
        self.transport._log(DEBUG, 'Auth request (type=%s) service=%s, username=%s' % (method, service, username))
44
 
        if service != 'ssh-connection':
45
 
            self._disconnect_service_not_available()
46
 
            return
47
 
        if (self.auth_username is not None) and (self.auth_username != username):
48
 
            self.transport._log(WARNING, 'Auth rejected because the client attempted to change username in mid-flight')
49
 
            self._disconnect_no_more_auth()
50
 
            return
51
 
        self.auth_username = username
52
 
 
53
 
        if method == 'none':
54
 
            result = self.transport.server_object.check_auth_none(username)
55
 
        elif method == 'password':
56
 
            changereq = m.get_boolean()
57
 
            password = m.get_string()
58
 
            try:
59
 
                password = password.decode('UTF-8')
60
 
            except UnicodeError:
61
 
                # some clients/servers expect non-utf-8 passwords!
62
 
                # in this case, just return the raw byte string.
63
 
                pass
64
 
            if changereq:
65
 
                # always treated as failure, since we don't support changing passwords, but collect
66
 
                # the list of valid auth types from the callback anyway
67
 
                self.transport._log(DEBUG, 'Auth request to change passwords (rejected)')
68
 
                newpassword = m.get_string()
69
 
                try:
70
 
                    newpassword = newpassword.decode('UTF-8', 'replace')
71
 
                except UnicodeError:
72
 
                    pass
73
 
                result = AUTH_FAILED
74
 
            else:
75
 
                result = self.transport.server_object.check_auth_password(username, password)
76
 
        elif method == 'publickey':
77
 
            sig_attached = m.get_boolean()
78
 
            keytype = m.get_string()
79
 
            keyblob = m.get_string()
80
 
            try:
81
 
                key = self.transport._key_info[keytype](Message(keyblob))
82
 
            except SSHException, e:
83
 
                self.transport._log(INFO, 'Auth rejected: public key: %s' % str(e))
84
 
                key = None
85
 
            except:
86
 
                self.transport._log(INFO, 'Auth rejected: unsupported or mangled public key')
87
 
                key = None
88
 
            if key is None:
89
 
                self._disconnect_no_more_auth()
90
 
                return
91
 
            # first check if this key is okay... if not, we can skip the verify
92
 
            result = self.transport.server_object.check_auth_publickey(username, key)
93
 
            if result != AUTH_FAILED:
94
 
                # key is okay, verify it
95
 
                if not sig_attached:
96
 
                    # client wants to know if this key is acceptable, before it
97
 
                    # signs anything...  send special "ok" message
98
 
                    m = Message()
99
 
                    m.add_byte(chr(MSG_USERAUTH_PK_OK))
100
 
                    m.add_string(keytype)
101
 
                    m.add_string(keyblob)
102
 
                    self.transport._send_message(m)
103
 
                    return
104
 
                sig = Message(m.get_string())
105
 
                blob = self._get_session_blob(key, service, username)
106
 
                if not key.verify_ssh_sig(blob, sig):
107
 
                    self.transport._log(INFO, 'Auth rejected: invalid signature')
108
 
                    result = AUTH_FAILED
109
 
        elif method == 'keyboard-interactive':
110
 
            lang = m.get_string()
111
 
            submethods = m.get_string()
112
 
            result = self.transport.server_object.check_auth_interactive(username, submethods)
113
 
            if isinstance(result, InteractiveQuery):
114
 
                # make interactive query instead of response
115
 
                self._interactive_query(result)
116
 
                return
117
 
        else:
118
 
            result = self.transport.server_object.check_auth_none(username)
119
 
        # okay, send result
120
 
        self._send_auth_result(username, method, result)
121
 
        
122