| // Copyright (C) 2009 The Android Open Source Project | |
| // | |
| // Licensed under the Apache License, Version 2.0 (the "License"); | |
| // you may not use this file except in compliance with the License. | |
| // You may obtain a copy of the License at | |
| // | |
| // http://www.apache.org/licenses/LICENSE-2.0 | |
| // | |
| // Unless required by applicable law or agreed to in writing, software | |
| // distributed under the License is distributed on an "AS IS" BASIS, | |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| // See the License for the specific language governing permissions and | |
| // limitations under the License. | |
| package com.google.gerrit.server.config; | |
| import static com.google.gerrit.server.account.externalids.ExternalId.SCHEME_MAILTO; | |
| import static com.google.gerrit.server.account.externalids.ExternalId.SCHEME_USERNAME; | |
| import static com.google.gerrit.server.account.externalids.ExternalId.SCHEME_UUID; | |
| import com.google.gerrit.extensions.client.AuthType; | |
| import com.google.gerrit.extensions.client.GitBasicAuthPolicy; | |
| import com.google.gerrit.server.account.externalids.ExternalId; | |
| import com.google.gerrit.server.auth.openid.OpenIdProviderPattern; | |
| import com.google.gerrit.server.mail.SignedToken; | |
| import com.google.gerrit.server.mail.XsrfException; | |
| import com.google.inject.Inject; | |
| import com.google.inject.Singleton; | |
| import java.util.ArrayList; | |
| import java.util.Arrays; | |
| import java.util.Collection; | |
| import java.util.Collections; | |
| import java.util.List; | |
| import java.util.concurrent.TimeUnit; | |
| import org.eclipse.jgit.lib.Config; | |
| /** Authentication related settings from {@code gerrit.config}. */ | |
| @Singleton | |
| public class AuthConfig { | |
| private final AuthType authType; | |
| private final String httpHeader; | |
| private final String httpDisplaynameHeader; | |
| private final String httpEmailHeader; | |
| private final String httpExternalIdHeader; | |
| private final String registerPageUrl; | |
| private final String registerUrl; | |
| private final String registerText; | |
| private final boolean trustContainerAuth; | |
| private final boolean enableRunAs; | |
| private final boolean userNameToLowerCase; | |
| private final boolean useContributorAgreements; | |
| private final String loginUrl; | |
| private final String loginText; | |
| private final String logoutUrl; | |
| private final String switchAccountUrl; | |
| private final String editFullNameUrl; | |
| private final String httpPasswordUrl; | |
| private final String openIdSsoUrl; | |
| private final List<String> openIdDomains; | |
| private final List<OpenIdProviderPattern> trustedOpenIDs; | |
| private final List<OpenIdProviderPattern> allowedOpenIDs; | |
| private final String cookiePath; | |
| private final String cookieDomain; | |
| private final boolean cookieSecure; | |
| private final SignedToken emailReg; | |
| private final boolean allowRegisterNewEmail; | |
| private final boolean userNameCaseInsensitive; | |
| private final boolean userNameCaseInsensitiveMigrationMode; | |
| private GitBasicAuthPolicy gitBasicAuthPolicy; | |
| @Inject | |
| AuthConfig(@GerritServerConfig Config cfg) throws XsrfException { | |
| authType = toType(cfg); | |
| httpHeader = cfg.getString("auth", null, "httpheader"); | |
| httpDisplaynameHeader = cfg.getString("auth", null, "httpdisplaynameheader"); | |
| httpEmailHeader = cfg.getString("auth", null, "httpemailheader"); | |
| httpExternalIdHeader = cfg.getString("auth", null, "httpexternalidheader"); | |
| loginUrl = cfg.getString("auth", null, "loginurl"); | |
| loginText = cfg.getString("auth", null, "logintext"); | |
| logoutUrl = cfg.getString("auth", null, "logouturl"); | |
| switchAccountUrl = cfg.getString("auth", null, "switchAccountUrl"); | |
| editFullNameUrl = cfg.getString("auth", null, "editFullNameUrl"); | |
| httpPasswordUrl = cfg.getString("auth", null, "httpPasswordUrl"); | |
| registerPageUrl = cfg.getString("auth", null, "registerPageUrl"); | |
| registerUrl = cfg.getString("auth", null, "registerUrl"); | |
| registerText = cfg.getString("auth", null, "registerText"); | |
| openIdSsoUrl = cfg.getString("auth", null, "openidssourl"); | |
| openIdDomains = Arrays.asList(cfg.getStringList("auth", null, "openIdDomain")); | |
| trustedOpenIDs = toPatterns(cfg, "trustedOpenID"); | |
| allowedOpenIDs = toPatterns(cfg, "allowedOpenID"); | |
| cookiePath = cfg.getString("auth", null, "cookiepath"); | |
| cookieDomain = cfg.getString("auth", null, "cookiedomain"); | |
| cookieSecure = cfg.getBoolean("auth", "cookiesecure", false); | |
| trustContainerAuth = cfg.getBoolean("auth", "trustContainerAuth", false); | |
| enableRunAs = cfg.getBoolean("auth", null, "enableRunAs", true); | |
| gitBasicAuthPolicy = getBasicAuthPolicy(cfg); | |
| useContributorAgreements = cfg.getBoolean("auth", "contributoragreements", false); | |
| userNameToLowerCase = cfg.getBoolean("auth", "userNameToLowerCase", false); | |
| allowRegisterNewEmail = cfg.getBoolean("auth", "allowRegisterNewEmail", true); | |
| userNameCaseInsensitive = cfg.getBoolean("auth", "userNameCaseInsensitive", false); | |
| userNameCaseInsensitiveMigrationMode = | |
| cfg.getBoolean("auth", "userNameCaseInsensitiveMigrationMode", false); | |
| if (gitBasicAuthPolicy == GitBasicAuthPolicy.HTTP_LDAP | |
| && authType != AuthType.LDAP | |
| && authType != AuthType.LDAP_BIND) { | |
| throw new IllegalStateException( | |
| "use auth.gitBasicAuthPolicy HTTP_LDAP only with auth.type LDAP or LDAP_BIND"); | |
| } else if (gitBasicAuthPolicy == GitBasicAuthPolicy.OAUTH && authType != AuthType.OAUTH) { | |
| throw new IllegalStateException( | |
| "use auth.gitBasicAuthPolicy OAUTH only with auth.type OAUTH"); | |
| } | |
| String key = cfg.getString("auth", null, "registerEmailPrivateKey"); | |
| if (key != null && !key.isEmpty()) { | |
| int age = | |
| (int) | |
| ConfigUtil.getTimeUnit( | |
| cfg, | |
| "auth", | |
| null, | |
| "maxRegisterEmailTokenAge", | |
| TimeUnit.SECONDS.convert(12, TimeUnit.HOURS), | |
| TimeUnit.SECONDS); | |
| emailReg = new SignedToken(age, key); | |
| } else { | |
| emailReg = null; | |
| } | |
| } | |
| private static List<OpenIdProviderPattern> toPatterns(Config cfg, String name) { | |
| String[] s = cfg.getStringList("auth", null, name); | |
| if (s.length == 0) { | |
| s = new String[] {"http://", "https://"}; | |
| } | |
| List<OpenIdProviderPattern> r = new ArrayList<>(); | |
| for (String pattern : s) { | |
| r.add(OpenIdProviderPattern.create(pattern)); | |
| } | |
| return Collections.unmodifiableList(r); | |
| } | |
| private static AuthType toType(Config cfg) { | |
| return cfg.getEnum("auth", null, "type", AuthType.OPENID); | |
| } | |
| private GitBasicAuthPolicy getBasicAuthPolicy(Config cfg) { | |
| GitBasicAuthPolicy defaultAuthPolicy = | |
| isLdapAuthType() | |
| ? GitBasicAuthPolicy.LDAP | |
| : isOAuthType() ? GitBasicAuthPolicy.OAUTH : GitBasicAuthPolicy.HTTP; | |
| return cfg.getEnum("auth", null, "gitBasicAuthPolicy", defaultAuthPolicy); | |
| } | |
| /** Type of user authentication used by this Gerrit server. */ | |
| public AuthType getAuthType() { | |
| return authType; | |
| } | |
| public String getLoginHttpHeader() { | |
| return httpHeader; | |
| } | |
| public String getHttpDisplaynameHeader() { | |
| return httpDisplaynameHeader; | |
| } | |
| public String getHttpEmailHeader() { | |
| return httpEmailHeader; | |
| } | |
| public String getHttpExternalIdHeader() { | |
| return httpExternalIdHeader; | |
| } | |
| public String getLoginUrl() { | |
| return loginUrl; | |
| } | |
| public String getLoginText() { | |
| return loginText; | |
| } | |
| public String getLogoutURL() { | |
| return logoutUrl; | |
| } | |
| public String getSwitchAccountUrl() { | |
| return switchAccountUrl; | |
| } | |
| public String getEditFullNameUrl() { | |
| return editFullNameUrl; | |
| } | |
| public String getHttpPasswordUrl() { | |
| return httpPasswordUrl; | |
| } | |
| public String getOpenIdSsoUrl() { | |
| return openIdSsoUrl; | |
| } | |
| public List<String> getOpenIdDomains() { | |
| return openIdDomains; | |
| } | |
| public String getCookiePath() { | |
| return cookiePath; | |
| } | |
| public String getCookieDomain() { | |
| return cookieDomain; | |
| } | |
| public boolean getCookieSecure() { | |
| return cookieSecure; | |
| } | |
| public SignedToken getEmailRegistrationToken() { | |
| return emailReg; | |
| } | |
| /** OpenID identities which the server permits for authentication. */ | |
| public List<OpenIdProviderPattern> getAllowedOpenIDs() { | |
| return allowedOpenIDs; | |
| } | |
| /** Whether git-over-http should trust authentication done by container. */ | |
| public boolean isTrustContainerAuth() { | |
| return trustContainerAuth; | |
| } | |
| /** Returns true if users with Run As capability can impersonate others. */ | |
| public boolean isRunAsEnabled() { | |
| return enableRunAs; | |
| } | |
| /** Whether user name should be converted to lower-case before validation */ | |
| public boolean isUserNameToLowerCase() { | |
| return userNameToLowerCase; | |
| } | |
| /** Whether user name should be matched case insenitive */ | |
| public boolean isUserNameCaseInsensitive() { | |
| return userNameCaseInsensitive; | |
| } | |
| /** Whether user name case insensitive migration is in progress */ | |
| public boolean isUserNameCaseInsensitiveMigrationMode() { | |
| return userNameCaseInsensitiveMigrationMode; | |
| } | |
| public GitBasicAuthPolicy getGitBasicAuthPolicy() { | |
| return gitBasicAuthPolicy; | |
| } | |
| /** Whether contributor agreements are used. */ | |
| public boolean isUseContributorAgreements() { | |
| return useContributorAgreements; | |
| } | |
| public boolean isIdentityTrustable(Collection<ExternalId> ids) { | |
| switch (getAuthType()) { | |
| case DEVELOPMENT_BECOME_ANY_ACCOUNT: | |
| case HTTP: | |
| case HTTP_LDAP: | |
| case LDAP: | |
| case LDAP_BIND: | |
| case CLIENT_SSL_CERT_LDAP: | |
| case CUSTOM_EXTENSION: | |
| case OAUTH: | |
| // only way in is through some external system that the admin trusts | |
| // | |
| return true; | |
| case OPENID_SSO: | |
| // There's only one provider in SSO mode, so it must be okay. | |
| return true; | |
| case OPENID: | |
| // All identities must be trusted in order to trust the account. | |
| // | |
| for (ExternalId e : ids) { | |
| if (!isTrusted(e)) { | |
| return false; | |
| } | |
| } | |
| return true; | |
| default: | |
| // Assume not, we don't understand the login format. | |
| // | |
| return false; | |
| } | |
| } | |
| private boolean isTrusted(ExternalId id) { | |
| if (id.isScheme(SCHEME_MAILTO)) { | |
| // mailto identities are created by sending a unique validation | |
| // token to the address and asking them to come back to the site | |
| // with that token. | |
| // | |
| return true; | |
| } | |
| if (id.isScheme(SCHEME_UUID)) { | |
| // UUID identities are absolutely meaningless and cannot be | |
| // constructed through any normal login process we use. | |
| // | |
| return true; | |
| } | |
| if (id.isScheme(SCHEME_USERNAME)) { | |
| // We can trust their username, its local to our server only. | |
| // | |
| return true; | |
| } | |
| for (OpenIdProviderPattern p : trustedOpenIDs) { | |
| if (p.matches(id)) { | |
| return true; | |
| } | |
| } | |
| return false; | |
| } | |
| public String getRegisterPageUrl() { | |
| return registerPageUrl; | |
| } | |
| public String getRegisterUrl() { | |
| return registerUrl; | |
| } | |
| public String getRegisterText() { | |
| return registerText; | |
| } | |
| public boolean isLdapAuthType() { | |
| return authType == AuthType.LDAP || authType == AuthType.LDAP_BIND; | |
| } | |
| public boolean isOAuthType() { | |
| return authType == AuthType.OAUTH; | |
| } | |
| public boolean isAllowRegisterNewEmail() { | |
| return allowRegisterNewEmail; | |
| } | |
| } |