1 # Copyright (C) 2005-2007 Jelmer Vernooij <jelmer@samba.org>
3 # This program is free software; you can redistribute it and/or modify
4 # it under the terms of the GNU General Public License as published by
5 # the Free Software Foundation; either version 3 of the License, or
6 # (at your option) any later version.
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
13 # You should have received a copy of the GNU General Public License
14 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 """Authentication token retrieval."""
18 from bzrlib.config import AuthenticationConfig
19 from bzrlib.ui import ui_factory
20 from bzrlib.plugins.svn.ra import (get_username_prompt_provider,
21 get_simple_prompt_provider,
22 get_ssl_server_trust_prompt_provider,
23 get_ssl_client_cert_pw_prompt_provider,
24 get_simple_provider, get_username_provider,
25 get_ssl_client_cert_file_provider,
26 get_ssl_client_cert_pw_file_provider,
27 get_ssl_server_trust_file_provider,
30 from bzrlib.plugins.svn import constants, ra
34 class SubversionAuthenticationConfig(AuthenticationConfig):
35 """Simple extended version of AuthenticationConfig that can provide
36 the information Subversion requires.
38 def __init__(self, scheme, host, port, path, file=None):
39 super(SubversionAuthenticationConfig, self).__init__(file)
45 def get_svn_username(self, realm, may_save):
46 """Look up a Subversion user name in the Bazaar authentication cache.
48 :param realm: Authentication realm (optional)
49 :param may_save: Whether or not the username should be saved.
51 username = self.get_user(self.scheme, host=self.host, path=self.path, realm=realm)
52 return (username, False)
54 def get_svn_simple(self, realm, username, may_save, pool):
55 """Look up a Subversion user name+password combination in the Bazaar
58 :param realm: Authentication realm (optional)
59 :param username: Username, if it is already known, or None.
60 :param may_save: Whether or not the username should be saved.
61 :param pool: Allocation pool, is ignored.
63 username = self.get_user(self.scheme,
64 host=self.host, path=self.path, realm=realm) or username
65 password = self.get_password(self.scheme, host=self.host,
66 path=self.path, user=simple_cred.username,
67 realm=realm, prompt="%s %s password" % (realm, simple_cred.username))
68 return (username, password, False)
70 def get_svn_ssl_server_trust(self, realm, failures, cert_info, may_save,
72 """Return a Subversion auth provider that verifies SSL server trust.
74 :param realm: Realm name (optional)
75 :param failures: Failures to check for (bit field, SVN_AUTH_SSL_*)
76 :param cert_info: Certificate information
77 :param may_save: Whether this information may be stored.
79 credentials = self.get_credentials(self.scheme, host=self.host)
80 if (credentials is not None and
81 credentials.has_key("verify_certificates") and
82 credentials["verify_certificates"] == False):
84 constants.AUTH_SSL_NOTYETVALID +
85 constants.AUTH_SSL_EXPIRED +
86 constants.AUTH_SSL_CNMISMATCH +
87 constants.AUTH_SSL_UNKNOWNCA +
88 constants.AUTH_SSL_OTHER)
91 return (accepted_failures, False)
93 def get_svn_username_prompt_provider(self, retries):
94 """Return a Subversion auth provider for retrieving the username, as
95 accepted by svn_auth_open().
97 :param retries: Number of allowed retries.
99 return get_username_prompt_provider(self.get_svn_username,
102 def get_svn_simple_prompt_provider(self, retries):
103 """Return a Subversion auth provider for retrieving a
104 username+password combination, as accepted by svn_auth_open().
106 :param retries: Number of allowed retries.
108 return get_simple_prompt_provider(self.get_svn_simple, retries)
110 def get_svn_ssl_server_trust_prompt_provider(self):
111 """Return a Subversion auth provider for checking
112 whether a SSL server is trusted."""
113 return get_ssl_server_trust_prompt_provider(
114 self.get_svn_ssl_server_trust)
116 def get_svn_auth_providers(self):
117 """Return a list of auth providers for this authentication file.
119 return [self.get_svn_username_prompt_provider(1),
120 self.get_svn_simple_prompt_provider(1),
121 self.get_svn_ssl_server_trust_prompt_provider()]
123 def get_ssl_client_cert_pw(realm, may_save, pool):
124 """Simple SSL client certificate password prompter.
126 :param realm: Realm, optional.
127 :param may_save: Whether the password can be cached.
129 password = ui_factory.get_password(
130 "Please enter password for client certificate[realm=%s]" % realm)
131 return (password, False)
134 def get_ssl_client_cert_pw_provider(tries):
135 return get_ssl_client_cert_pw_prompt_provider(
136 get_ssl_client_cert_pw, tries)
138 def get_stock_svn_providers():
139 providers = [get_simple_provider(),
140 get_username_provider(),
141 get_ssl_client_cert_file_provider(),
142 get_ssl_client_cert_pw_file_provider(),
143 get_ssl_server_trust_file_provider(),
146 if hasattr(ra, 'get_windows_simple_provider'):
147 providers.append(ra.get_windows_simple_provider())
149 if hasattr(ra, 'get_keychain_simple_provider'):
150 providers.append(ra.get_keychain_simple_provider())
152 if hasattr(ra, 'get_windows_ssl_server_trust_provider'):
153 providers.append(ra.get_windows_ssl_server_trust_provider())
158 def create_auth_baton(url):
159 """Create an authentication baton for the specified URL."""
160 assert isinstance(url, str)
161 (scheme, netloc, path, _, _) = urlparse.urlsplit(url)
162 (creds, host) = urllib.splituser(netloc)
163 (host, port) = urllib.splitport(host)
165 auth_config = SubversionAuthenticationConfig(scheme, host, port, path)
167 # Specify Subversion providers first, because they use file data
168 # rather than prompting the user.
169 providers = get_stock_svn_providers()
171 (major, minor, patch, tag) = ra.version()
172 if major == 1 and minor >= 5:
173 providers += auth_config.get_svn_auth_providers()
174 providers += [get_ssl_client_cert_pw_provider(1)]
176 auth_baton = Auth(providers)
177 if creds is not None:
178 (user, password) = urllib.splitpasswd(creds)
180 auth_baton.set_parameter(constants.AUTH_PARAM_DEFAULT_USERNAME, user)
181 if password is not None:
182 auth_baton.set_parameter(constants.AUTH_PARAM_DEFAULT_PASSWORD, password)