Line data Source code
1 : // Copyright (C) 2009 The Android Open Source Project
2 : //
3 : // Licensed under the Apache License, Version 2.0 (the "License");
4 : // you may not use this file except in compliance with the License.
5 : // You may obtain a copy of the License at
6 : //
7 : // http://www.apache.org/licenses/LICENSE-2.0
8 : //
9 : // Unless required by applicable law or agreed to in writing, software
10 : // distributed under the License is distributed on an "AS IS" BASIS,
11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : // See the License for the specific language governing permissions and
13 : // limitations under the License.
14 :
15 : package com.google.gerrit.server.config;
16 :
17 : import static com.google.gerrit.server.account.externalids.ExternalId.SCHEME_MAILTO;
18 : import static com.google.gerrit.server.account.externalids.ExternalId.SCHEME_USERNAME;
19 : import static com.google.gerrit.server.account.externalids.ExternalId.SCHEME_UUID;
20 :
21 : import com.google.gerrit.extensions.client.AuthType;
22 : import com.google.gerrit.extensions.client.GitBasicAuthPolicy;
23 : import com.google.gerrit.server.account.externalids.ExternalId;
24 : import com.google.gerrit.server.auth.openid.OpenIdProviderPattern;
25 : import com.google.gerrit.server.mail.SignedToken;
26 : import com.google.gerrit.server.mail.XsrfException;
27 : import com.google.inject.Inject;
28 : import com.google.inject.Singleton;
29 : import java.util.ArrayList;
30 : import java.util.Arrays;
31 : import java.util.Collection;
32 : import java.util.Collections;
33 : import java.util.List;
34 : import java.util.concurrent.TimeUnit;
35 : import org.eclipse.jgit.lib.Config;
36 :
37 : /** Authentication related settings from {@code gerrit.config}. */
38 : @Singleton
39 : public class AuthConfig {
40 : private final AuthType authType;
41 : private final String httpHeader;
42 : private final String httpDisplaynameHeader;
43 : private final String httpEmailHeader;
44 : private final String httpExternalIdHeader;
45 : private final String registerPageUrl;
46 : private final String registerUrl;
47 : private final String registerText;
48 : private final boolean trustContainerAuth;
49 : private final boolean enableRunAs;
50 : private final boolean userNameToLowerCase;
51 : private final boolean useContributorAgreements;
52 : private final String loginUrl;
53 : private final String loginText;
54 : private final String logoutUrl;
55 : private final String switchAccountUrl;
56 : private final String editFullNameUrl;
57 : private final String httpPasswordUrl;
58 : private final String openIdSsoUrl;
59 : private final List<String> openIdDomains;
60 : private final List<OpenIdProviderPattern> trustedOpenIDs;
61 : private final List<OpenIdProviderPattern> allowedOpenIDs;
62 : private final String cookiePath;
63 : private final String cookieDomain;
64 : private final boolean cookieSecure;
65 : private final SignedToken emailReg;
66 : private final boolean allowRegisterNewEmail;
67 : private final boolean userNameCaseInsensitive;
68 : private final boolean userNameCaseInsensitiveMigrationMode;
69 : private GitBasicAuthPolicy gitBasicAuthPolicy;
70 :
71 : @Inject
72 152 : AuthConfig(@GerritServerConfig Config cfg) throws XsrfException {
73 152 : authType = toType(cfg);
74 152 : httpHeader = cfg.getString("auth", null, "httpheader");
75 152 : httpDisplaynameHeader = cfg.getString("auth", null, "httpdisplaynameheader");
76 152 : httpEmailHeader = cfg.getString("auth", null, "httpemailheader");
77 152 : httpExternalIdHeader = cfg.getString("auth", null, "httpexternalidheader");
78 152 : loginUrl = cfg.getString("auth", null, "loginurl");
79 152 : loginText = cfg.getString("auth", null, "logintext");
80 152 : logoutUrl = cfg.getString("auth", null, "logouturl");
81 152 : switchAccountUrl = cfg.getString("auth", null, "switchAccountUrl");
82 152 : editFullNameUrl = cfg.getString("auth", null, "editFullNameUrl");
83 152 : httpPasswordUrl = cfg.getString("auth", null, "httpPasswordUrl");
84 152 : registerPageUrl = cfg.getString("auth", null, "registerPageUrl");
85 152 : registerUrl = cfg.getString("auth", null, "registerUrl");
86 152 : registerText = cfg.getString("auth", null, "registerText");
87 152 : openIdSsoUrl = cfg.getString("auth", null, "openidssourl");
88 152 : openIdDomains = Arrays.asList(cfg.getStringList("auth", null, "openIdDomain"));
89 152 : trustedOpenIDs = toPatterns(cfg, "trustedOpenID");
90 152 : allowedOpenIDs = toPatterns(cfg, "allowedOpenID");
91 152 : cookiePath = cfg.getString("auth", null, "cookiepath");
92 152 : cookieDomain = cfg.getString("auth", null, "cookiedomain");
93 152 : cookieSecure = cfg.getBoolean("auth", "cookiesecure", false);
94 152 : trustContainerAuth = cfg.getBoolean("auth", "trustContainerAuth", false);
95 152 : enableRunAs = cfg.getBoolean("auth", null, "enableRunAs", true);
96 152 : gitBasicAuthPolicy = getBasicAuthPolicy(cfg);
97 152 : useContributorAgreements = cfg.getBoolean("auth", "contributoragreements", false);
98 152 : userNameToLowerCase = cfg.getBoolean("auth", "userNameToLowerCase", false);
99 152 : allowRegisterNewEmail = cfg.getBoolean("auth", "allowRegisterNewEmail", true);
100 152 : userNameCaseInsensitive = cfg.getBoolean("auth", "userNameCaseInsensitive", false);
101 152 : userNameCaseInsensitiveMigrationMode =
102 152 : cfg.getBoolean("auth", "userNameCaseInsensitiveMigrationMode", false);
103 :
104 152 : if (gitBasicAuthPolicy == GitBasicAuthPolicy.HTTP_LDAP
105 : && authType != AuthType.LDAP
106 : && authType != AuthType.LDAP_BIND) {
107 0 : throw new IllegalStateException(
108 : "use auth.gitBasicAuthPolicy HTTP_LDAP only with auth.type LDAP or LDAP_BIND");
109 152 : } else if (gitBasicAuthPolicy == GitBasicAuthPolicy.OAUTH && authType != AuthType.OAUTH) {
110 0 : throw new IllegalStateException(
111 : "use auth.gitBasicAuthPolicy OAUTH only with auth.type OAUTH");
112 : }
113 :
114 152 : String key = cfg.getString("auth", null, "registerEmailPrivateKey");
115 152 : if (key != null && !key.isEmpty()) {
116 19 : int age =
117 : (int)
118 19 : ConfigUtil.getTimeUnit(
119 : cfg,
120 : "auth",
121 : null,
122 : "maxRegisterEmailTokenAge",
123 19 : TimeUnit.SECONDS.convert(12, TimeUnit.HOURS),
124 : TimeUnit.SECONDS);
125 19 : emailReg = new SignedToken(age, key);
126 19 : } else {
127 151 : emailReg = null;
128 : }
129 152 : }
130 :
131 : private static List<OpenIdProviderPattern> toPatterns(Config cfg, String name) {
132 152 : String[] s = cfg.getStringList("auth", null, name);
133 152 : if (s.length == 0) {
134 152 : s = new String[] {"http://", "https://"};
135 : }
136 :
137 152 : List<OpenIdProviderPattern> r = new ArrayList<>();
138 152 : for (String pattern : s) {
139 152 : r.add(OpenIdProviderPattern.create(pattern));
140 : }
141 152 : return Collections.unmodifiableList(r);
142 : }
143 :
144 : private static AuthType toType(Config cfg) {
145 152 : return cfg.getEnum("auth", null, "type", AuthType.OPENID);
146 : }
147 :
148 : private GitBasicAuthPolicy getBasicAuthPolicy(Config cfg) {
149 : GitBasicAuthPolicy defaultAuthPolicy =
150 152 : isLdapAuthType()
151 1 : ? GitBasicAuthPolicy.LDAP
152 152 : : isOAuthType() ? GitBasicAuthPolicy.OAUTH : GitBasicAuthPolicy.HTTP;
153 152 : return cfg.getEnum("auth", null, "gitBasicAuthPolicy", defaultAuthPolicy);
154 : }
155 :
156 : /** Type of user authentication used by this Gerrit server. */
157 : public AuthType getAuthType() {
158 152 : return authType;
159 : }
160 :
161 : public String getLoginHttpHeader() {
162 0 : return httpHeader;
163 : }
164 :
165 : public String getHttpDisplaynameHeader() {
166 1 : return httpDisplaynameHeader;
167 : }
168 :
169 : public String getHttpEmailHeader() {
170 1 : return httpEmailHeader;
171 : }
172 :
173 : public String getHttpExternalIdHeader() {
174 0 : return httpExternalIdHeader;
175 : }
176 :
177 : public String getLoginUrl() {
178 1 : return loginUrl;
179 : }
180 :
181 : public String getLoginText() {
182 1 : return loginText;
183 : }
184 :
185 : public String getLogoutURL() {
186 99 : return logoutUrl;
187 : }
188 :
189 : public String getSwitchAccountUrl() {
190 3 : return switchAccountUrl;
191 : }
192 :
193 : public String getEditFullNameUrl() {
194 0 : return editFullNameUrl;
195 : }
196 :
197 : public String getHttpPasswordUrl() {
198 0 : return httpPasswordUrl;
199 : }
200 :
201 : public String getOpenIdSsoUrl() {
202 0 : return openIdSsoUrl;
203 : }
204 :
205 : public List<String> getOpenIdDomains() {
206 99 : return openIdDomains;
207 : }
208 :
209 : public String getCookiePath() {
210 1 : return cookiePath;
211 : }
212 :
213 : public String getCookieDomain() {
214 1 : return cookieDomain;
215 : }
216 :
217 : public boolean getCookieSecure() {
218 1 : return cookieSecure;
219 : }
220 :
221 : public SignedToken getEmailRegistrationToken() {
222 138 : return emailReg;
223 : }
224 :
225 : /** OpenID identities which the server permits for authentication. */
226 : public List<OpenIdProviderPattern> getAllowedOpenIDs() {
227 99 : return allowedOpenIDs;
228 : }
229 :
230 : /** Whether git-over-http should trust authentication done by container. */
231 : public boolean isTrustContainerAuth() {
232 99 : return trustContainerAuth;
233 : }
234 :
235 : /** Returns true if users with Run As capability can impersonate others. */
236 : public boolean isRunAsEnabled() {
237 99 : return enableRunAs;
238 : }
239 :
240 : /** Whether user name should be converted to lower-case before validation */
241 : public boolean isUserNameToLowerCase() {
242 40 : return userNameToLowerCase;
243 : }
244 :
245 : /** Whether user name should be matched case insenitive */
246 : public boolean isUserNameCaseInsensitive() {
247 152 : return userNameCaseInsensitive;
248 : }
249 :
250 : /** Whether user name case insensitive migration is in progress */
251 : public boolean isUserNameCaseInsensitiveMigrationMode() {
252 151 : return userNameCaseInsensitiveMigrationMode;
253 : }
254 :
255 : public GitBasicAuthPolicy getGitBasicAuthPolicy() {
256 99 : return gitBasicAuthPolicy;
257 : }
258 :
259 : /** Whether contributor agreements are used. */
260 : public boolean isUseContributorAgreements() {
261 3 : return useContributorAgreements;
262 : }
263 :
264 : public boolean isIdentityTrustable(Collection<ExternalId> ids) {
265 150 : switch (getAuthType()) {
266 : case DEVELOPMENT_BECOME_ANY_ACCOUNT:
267 : case HTTP:
268 : case HTTP_LDAP:
269 : case LDAP:
270 : case LDAP_BIND:
271 : case CLIENT_SSL_CERT_LDAP:
272 : case CUSTOM_EXTENSION:
273 : case OAUTH:
274 : // only way in is through some external system that the admin trusts
275 : //
276 16 : return true;
277 :
278 : case OPENID_SSO:
279 : // There's only one provider in SSO mode, so it must be okay.
280 0 : return true;
281 :
282 : case OPENID:
283 : // All identities must be trusted in order to trust the account.
284 : //
285 138 : for (ExternalId e : ids) {
286 138 : if (!isTrusted(e)) {
287 3 : return false;
288 : }
289 138 : }
290 138 : return true;
291 :
292 : default:
293 : // Assume not, we don't understand the login format.
294 : //
295 0 : return false;
296 : }
297 : }
298 :
299 : private boolean isTrusted(ExternalId id) {
300 138 : if (id.isScheme(SCHEME_MAILTO)) {
301 : // mailto identities are created by sending a unique validation
302 : // token to the address and asking them to come back to the site
303 : // with that token.
304 : //
305 138 : return true;
306 : }
307 :
308 138 : if (id.isScheme(SCHEME_UUID)) {
309 : // UUID identities are absolutely meaningless and cannot be
310 : // constructed through any normal login process we use.
311 : //
312 0 : return true;
313 : }
314 :
315 138 : if (id.isScheme(SCHEME_USERNAME)) {
316 : // We can trust their username, its local to our server only.
317 : //
318 138 : return true;
319 : }
320 :
321 3 : for (OpenIdProviderPattern p : trustedOpenIDs) {
322 3 : if (p.matches(id)) {
323 0 : return true;
324 : }
325 3 : }
326 3 : return false;
327 : }
328 :
329 : public String getRegisterPageUrl() {
330 0 : return registerPageUrl;
331 : }
332 :
333 : public String getRegisterUrl() {
334 0 : return registerUrl;
335 : }
336 :
337 : public String getRegisterText() {
338 0 : return registerText;
339 : }
340 :
341 : public boolean isLdapAuthType() {
342 152 : return authType == AuthType.LDAP || authType == AuthType.LDAP_BIND;
343 : }
344 :
345 : public boolean isOAuthType() {
346 152 : return authType == AuthType.OAUTH;
347 : }
348 :
349 : public boolean isAllowRegisterNewEmail() {
350 7 : return allowRegisterNewEmail;
351 : }
352 : }
|