Merge branch 'stable-2.11'

* stable-2.11:
  SshDaemon: Don't use deprecated IoAcceptor.dispose()
  PatchListLoader: Don't use deprecated TemporaryBuffer.LocalFile constructor
  Fix unused exception throws in EncryptedContactStore
  Remove unused imports
  Don't use deprecated PGPPublicKeyRingCollection constructor
  Print proper name for mergeability check tasks in show-queue command
  Print proper name for ListenableFutureTask in show-queue command
  Work around asciidoctor handling of nested ` and *
  Revert "Revert "Allow configuration of SSH rekey values""
  Revert "Revert "SSHD: Allow ECDSA based public key authentication""
  Revert "Revert "SSHD: Prevent double authentication for the same public key""
  Revert "Downgrade SSHD to 0.9.0-4-g5967cfd"
  Recommend --data-binary flag when testing submit rules from curl
  Change edit shortcut from 'm' to 'e'
  Fix NPE in MergeabilityCache.getIfPresent
  Fix F5 shortcut being hijacked by edit topic in Firefox
  Update 2.11 release notes
  Update version to 2.10.2
  Release notes for Gerrit 2.10.2
  Do not return 403 when clicking on Gitweb breadcrumb
  Add log messages to troubleshoot OAuth/OpenID linking
  Remove unused imports
  Convert to new AutoCloseable instances coming in JGit 4.0
  Remove unused OAuthToken in authorisation URL
  OnlineReindexer: log the success/failure numbers on exit
  Work around MyersDiff infinite loop in PatchListLoader
  Bind SecureStore and SecureStoreClassName in WebAppInitializer
  Update replication plugin
  Rework intra line diff to interrupt threads instead of killing them
  Update JGit to 3.7.0.201502260915-r.58-g65c379e
  Update replication plugin
  Workaround a RecursiveMerger bug [1], avoid online reindexing failure
  OAuth: Allow to link claimed identity to existing accounts
  OAuth: Allow to change username
  Allow PatchListLoader to use recursive merger
  Allow plugins to use self-provided licenses for used Maven Jars

Change-Id: Ie7f96abd97bd2c7e9205a708eed11f9052546187
This commit is contained in:
David Pursehouse 2015-04-07 10:48:14 +09:00
commit efdb2461d3
36 changed files with 434 additions and 148 deletions

View File

@ -210,8 +210,8 @@ Reference-level access control is also possible.
Permissions can be set on a single reference name to match one
branch (e.g. `refs/heads/master`), or on a reference namespace
(e.g. `refs/heads/*`) to match any branch starting with that
prefix. So a permission with `refs/heads/*` will match
(e.g. `+refs/heads/*+`) to match any branch starting with that
prefix. So a permission with `+refs/heads/*+` will match
`refs/heads/master` and `refs/heads/experimental`, etc.
Reference names can also be described with a regular expression
@ -227,7 +227,7 @@ particular regular expression flavor.
References can have the current user name automatically included,
creating dynamic access controls that change to match the currently
logged in user. For example to provide a personal sandbox space
to all developers, `refs/heads/sandbox/${username}/*` allowing
to all developers, `+refs/heads/sandbox/${username}/*+` allowing
the user 'joe' to use 'refs/heads/sandbox/joe/foo'.
When evaluating a reference-level access right, Gerrit will use
@ -405,19 +405,19 @@ link:user-upload.html#push_create[Upload changes] page.
==== refs/publish/*
`refs/publish/*` is an alternative name to `refs/for/*` when pushing new changes
`+refs/publish/*+` is an alternative name to `+refs/for/*+` when pushing new changes
and patch sets.
==== refs/drafts/*
Push to `refs/drafts/*` creates a change like push to `refs/for/*`, except the
Push to `+refs/drafts/*+` creates a change like push to `+refs/for/*+`, except the
resulting change remains hidden from public review. You then have the option
of adding individual reviewers before making the change public to all. The
change page will have a 'Publish' button which allows you to convert individual
draft patch sets of a change into public patch sets for review.
To block push permission to `refs/drafts/*` the following permission rule can
To block push permission to `+refs/drafts/*+` the following permission rule can
be configured:
====
@ -464,18 +464,18 @@ branch permissions, allowing the holder of both to create new branches
as well as bypass review for new commits on that branch.
To push lightweight (non-annotated) tags, grant
`Create Reference` for reference name `refs/tags/*`, as lightweight
`Create Reference` for reference name `+refs/tags/*+`, as lightweight
tags are implemented just like branches in Git.
For example, to grant the possibility to create new branches under the
namespace `foo`, you have to grant this permission on
`refs/heads/foo/*` for the group that should have it.
`+refs/heads/foo/*+` for the group that should have it.
Finally, if you plan to grant each user a personal namespace in
where they are free to create as many branches as they wish, you
should grant the create reference permission so it's possible
to create new branches. This is done by using the special
`${username}` keyword in the reference pattern, e.g.
`refs/heads/sandbox/${username}/*`. If you do, it's also recommended
`+refs/heads/sandbox/${username}/*+`. If you do, it's also recommended
you grant the users the push force permission to be able to clean up
stale branches.
@ -547,7 +547,7 @@ they are a member of, just like for any other user.
Ownership over a particular branch subspace may be delegated by
entering a branch pattern. To delegate control over all branches
that begin with `qa/` to the QA group, add `Owner` category
for reference `refs/heads/qa/*`. Members of the QA group can
for reference `+refs/heads/qa/*+`. Members of the QA group can
further refine access, but only for references that begin with
`refs/heads/qa/`. See <<project_owners,project owners>> to find
out more about this role.
@ -600,15 +600,15 @@ a new commit on their local system, so in practice they must also
have the `Read` access granted to upload a change.
For an open source, public Gerrit installation, it is common to
grant `Read` and `Push` for `refs/for/refs/heads/*`
grant `Read` and `Push` for `+refs/for/refs/heads/*+`
to `Registered Users` in the `All-Projects` ACL. For more
private installations, its common to simply grant `Read` and
`Push` for `refs/for/refs/heads/*` to all users of a project.
`Push` for `+refs/for/refs/heads/*+` to all users of a project.
* Force option
+
The force option has no function when granted to a branch in the
`refs/for/refs/heads/*` namespace.
`+refs/for/refs/heads/*+` namespace.
[[category_push_merge]]
@ -661,11 +661,11 @@ must be also granted in addition to `Push Annotated Tag`.
To push lightweight (non annotated) tags, grant
<<category_create,`Create Reference`>> for reference name
`refs/tags/*`, as lightweight tags are implemented just like
`+refs/tags/*+`, as lightweight tags are implemented just like
branches in Git.
To delete or overwrite an existing tag, grant `Push` with the force
option enabled for reference name `refs/tags/*`, as deleting a tag
option enabled for reference name `+refs/tags/*+`, as deleting a tag
requires the same permission as deleting a branch.
@ -1026,7 +1026,7 @@ Suggested access rights to grant:
== Enforcing site wide access policies
By granting the <<category_owner,`Owner`>> access right on the `refs/*` to a
By granting the <<category_owner,`Owner`>> access right on the `+refs/*+` to a
group, Gerrit administrators can delegate the responsibility of maintaining
access rights for that project to that group.

View File

@ -2621,8 +2621,8 @@ are specified in the link:#container[container section]:
If set to true, files with the MIME type `<name>` will be sent as
direct downloads to the user's browser, rather than being wrapped up
inside of zipped archives. The type name may be a complete type
name, e.g. `image/gif`, a generic media type, e.g. `image/*`,
or the wildcard `*/*` to match all types.
name, e.g. `image/gif`, a generic media type, e.g. `+image/*+`,
or the wildcard `+*/*+` to match all types.
+
By default, false for all MIME types.
@ -3064,6 +3064,14 @@ namespace. To alias `replication start` to `gerrit replicate`:
[[sshd]]
=== Section sshd
[[sshd.backend]]sshd.backend::
+
Starting from version 0.9.0 Apache SSHD project added support for NIO2
IoSession. To use the new NIO2 session the `backend` option must be set
to `NIO2`.
+
By default, `MINA`.
[[sshd.listenAddress]]sshd.listenAddress::
+
Specifies the local addresses the internal SSHD should listen
@ -3265,6 +3273,24 @@ programmatic configuration.
+
By default, true.
[[sshd.rekeyBytesLimit]]sshd.rekeyBytesLimit::
+
The SSH daemon will issue a rekeying after a certain amount of data.
This configuration option allows you to tweak that setting.
+
By default, 1073741824 (bytes, 1GB).
+
The rekeyBytesLimit cannot be set to lower than 32.
[[sshd.rekeyTimeLimit]]sshd.rekeyTimeLimit::
+
The SSH daemon will issue a rekeying after a certain amount of time.
This configuration option allows you to tweak that setting.
+
By default, 1h.
+
Set to 0 to disable this check.
[[suggest]]
=== Section suggest

View File

@ -215,7 +215,7 @@ gitweb CGI.
The CGI's `$projectroot` should be the same directory as
gerrit.basePath, or a fairly current replica. If a replica is
being used, ensure it uses a full mirror, so the `refs/changes/*`
being used, ensure it uses a full mirror, so the `+refs/changes/*+`
namespace is available.
----

View File

@ -64,7 +64,7 @@ As you can see, there are several sections.
The link:#project-section[+project+ section] appears once per project.
The link:#access-section[+access+ section] appears once per reference pattern,
such as `refs/*` or `refs/heads/*`. Only one access section per pattern is
such as `+refs/*+` or `+refs/heads/*+`. Only one access section per pattern is
allowed. You will find examples of keys and values in each category section
<<access_category,below>>.

View File

@ -1692,7 +1692,7 @@ class HelloServlet extends HttpServlet {
----
The auto registration only works for standard servlet mappings like
`/foo` or `/foo/*`. Regex style bindings must use a Guice ServletModule
`/foo` or `+/foo/*+`. Regex style bindings must use a Guice ServletModule
to register the HTTP servlets and declare it explicitly in the manifest
with the `Gerrit-HttpModule` attribute:
@ -1820,7 +1820,7 @@ BranchWebLinks will appear in the branch list in the last column.
== Documentation
If a plugin does not register a filter or servlet to handle URLs
`/Documentation/*` or `/static/*`, the core Gerrit server will
`+/Documentation/*+` or `+/static/*+`, the core Gerrit server will
automatically export these resources over HTTP from the plugin JAR.
Static resources under the `static/` directory in the JAR will be

View File

@ -9,32 +9,32 @@ In particular this error occurs:
1. if you push a commit for code review to a branch for which you
don't have upload permissions (access right
link:access-control.html#category_push_review['Push'] on
`refs/for/refs/heads/*`)
`+refs/for/refs/heads/*+`)
2. if you bypass code review without
link:access-control.html#category_push_direct['Push'] access right
on `refs/heads/*`
on `+refs/heads/*+`
3. if you bypass code review pushing to a non-existing branch without
link:access-control.html#category_create['Create Reference'] access
right on `refs/heads/*`
right on `+refs/heads/*+`
4. if you push an annotated tag without
link:access-control.html#category_push_annotated['Push Annotated Tag']
access right on 'refs/tags/*'
access right on `+refs/tags/*+`
5. if you push a signed tag without
link:access-control.html#category_push_signed['Push Signed Tag']
access right on 'refs/tags/*'
access right on `+refs/tags/*+`
6. if you push a lightweight tag without the access right link:access-control.html#category_create['Create
Reference'] for the reference name 'refs/tags/*'
Reference'] for the reference name `+refs/tags/*+`
7. if you push a tag with somebody else as tagger and you don't have the
link:access-control.html#category_forge_committer['Forge Committer']
access right for the reference name 'refs/tags/*'
access right for the reference name `+refs/tags/*+`
8. if you push to a project that is in state 'Read Only'
For new users it often happens that they accidentally try to bypass
code review. The push then fails with the error message 'prohibited
by Gerrit' because the project didn't allow to bypass code review.
Bypassing the code review is done by pushing directly to refs/heads/*
(e.g. refs/heads/master) instead of pushing to refs/for/* (e.g.
refs/for/master). Details about how to push commits for code review
Bypassing the code review is done by pushing directly to `+refs/heads/*+`
(e.g. `refs/heads/master`) instead of pushing to `+refs/for/*+` (e.g.
`refs/for/master`). Details about how to push commits for code review
are explained link:user-upload.html#push_create[here].

View File

@ -10,7 +10,7 @@ workflows for a project.
Being project owner means that you own a project in Gerrit.
Technically this is expressed by having the
link:access-control.html#category_owner[Owner] access right on
`refs/*` on that project. As project owner you have the permission to
`+refs/*+` on that project. As project owner you have the permission to
edit the access control list and the project settings of the project.
It also means that you should get familiar with these settings so that
you can adapt them to the needs of your project.
@ -127,12 +127,12 @@ Access rights can be assigned on a concrete ref, e.g.
`refs/heads/master` but also on ref patterns and regular expressions
for ref names.
A ref pattern ends with `/*` and describes a complete ref name
namespace, e.g. access rights assigned on `refs/heads/*` apply to all
A ref pattern ends with `+/*+` and describes a complete ref name
namespace, e.g. access rights assigned on `+refs/heads/*+` apply to all
branches.
Regular expressions must start with `^`, e.g. access rights assigned
on `^refs/heads/rel-.*` would apply to all `rel-*` branches.
on `+^refs/heads/rel-.*+` would apply to all `+rel-*+` branches.
[[groups]]
=== Groups

View File

@ -987,11 +987,11 @@ submit_type(cherry_pick).
----
[[SubmitTypePerBranch]]
=== Example 2: `Fast Forward Only` for all `refs/heads/stable*` branches
For all `refs/heads/stable*` branches we would like to enforce the `Fast
=== Example 2: `Fast Forward Only` for all `+refs/heads/stable*+` branches
For all `+refs/heads/stable*+` branches we would like to enforce the `Fast
Forward Only` submit type. A reason for this decision may be a need to never
break the build in the stable branches. For all other branches, those not
matching the `refs/heads/stable*` pattern, we would like to use the project's
matching the `+refs/heads/stable*+` pattern, we would like to use the project's
default submit type as defined on the project settings page.
`rules.pl`
@ -1004,13 +1004,13 @@ submit_type(T) :- gerrit:project_default_submit_type(T)
----
The first `submit_type` predicate defines the `Fast Forward Only` submit type
for `refs/heads/stable.*` branches. The second `submit_type` predicate returns
for `+refs/heads/stable.*+` branches. The second `submit_type` predicate returns
the project's default submit type.
=== Example 3: Don't require `Fast Forward Only` if only documentation was changed
Like in the previous example we want the `Fast Forward Only` submit type for the
`refs/heads/stable*` branches. However, if only documentation was changed
(only `*.txt` files), then we allow project's default submit type for such
`+refs/heads/stable*+` branches. However, if only documentation was changed
(only `+*.txt+` files), then we allow project's default submit type for such
changes.
`rules.pl`

View File

@ -70,8 +70,8 @@ For more details, see link:cmd-hook-commit-msg.html[commit-msg].
Change Upload
--------------
During upload by pushing to `refs/for/*`, `refs/drafts/*` or
`refs/heads/*`, Gerrit will try to find an existing review the
During upload by pushing to `+refs/for/*+`, `+refs/drafts/*+` or
`+refs/heads/*+`, Gerrit will try to find an existing review the
uploaded commit relates to. For an existing review to match, the
following properties have to match:

View File

@ -58,7 +58,7 @@ to changes for the current user:
== Project Dashboards
It is possible to share custom dashboards at a project level. To do
this define the dashboards in a `refs/meta/dashboards/*` branch of the
this define the dashboards in a `+refs/meta/dashboards/*+` branch of the
project. For each dashboard create a config file. The file path/name
will be used as name (equivalent to a title in a custom dashboard) for
the dashboard.

View File

@ -319,9 +319,9 @@ be rewritten.
Gerrit restricts direct pushes that bypass review to:
* `refs/heads/*`: any branch can be updated, created, deleted,
* `+refs/heads/*+`: any branch can be updated, created, deleted,
or rewritten by the pusher.
* `refs/tags/*`: annotated tag objects pointing to any other type
* `+refs/tags/*+`: annotated tag objects pointing to any other type
of Git object can be created.
To push branches, the proper access rights must be configured first.
@ -445,8 +445,8 @@ As Gerrit implements the entire SSH and Git server stack within its
own process space, Gerrit maintains complete control over how the
repository is updated, and what responses are sent to the `git push`
client invoked by the end-user, or by `repo upload`. This allows
Gerrit to provide magical refs, such as `refs/for/*` for new
change submission and `refs/changes/*` for change replacement.
Gerrit to provide magical refs, such as `+refs/for/*+` for new
change submission and `+refs/changes/*+` for change replacement.
When a push request is received to create a ref in one of these
namespaces Gerrit performs its own logic to update the database,
and then lies to the client about the result of the operation.

View File

@ -0,0 +1,31 @@
Release notes for Gerrit 2.10.2
===============================
There are no schema changes from link:ReleaseNotes-2.10.1.html[2.10.1].
Download:
link:https://gerrit-releases.storage.googleapis.com/gerrit-2.10.2.war[
https://gerrit-releases.storage.googleapis.com/gerrit-2.10.2.war]
Bug Fixes
---------
* Work around MyersDiff infinite loop in PatchListLoader. If the MyersDiff diff
doesn't finish within 5 seconds, interrupt it and fall back to a different diff
algorithm. From the user perspective, the only difference when the infinite
loop is detected is that the files in the commit will not be compared in-depth,
which will result in bigger edit regions.
Secondary Index
---------------
* Online reindexing: log the number of done/failed changes in the error_log.
Administrators can use the logged information to decide whether to activate the
new index version or not.
Gitweb
------
* Do not return `Forbidden` when clicking on Gitweb breadcrumb. Now when the
user clicks on the parent folder, redirect to Gerrit projects list screen with
the parent folder path as the filter.

View File

@ -8,7 +8,8 @@ link:https://gerrit-releases.storage.googleapis.com/gerrit-2.11.war[
https://gerrit-releases.storage.googleapis.com/gerrit-2.11.war]
Gerrit 2.11 includes the bug fixes done with
link:ReleaseNotes-2.10.1.html[Gerrit 2.10.1].
link:ReleaseNotes-2.10.1.html[Gerrit 2.10.1] and
link:ReleaseNotes-2.10.2.html[Gerrit 2.10.2].
These bug fixes are *not* listed in these release notes.

View File

@ -9,6 +9,7 @@ Version 2.11.x
[[2_10]]
Version 2.10.x
--------------
* link:ReleaseNotes-2.10.2.html[2.10.2]
* link:ReleaseNotes-2.10.1.html[2.10.1]
* link:ReleaseNotes-2.10.html[2.10]

View File

@ -22,30 +22,21 @@ import java.io.IOException;
@ExtensionPoint
public interface OAuthServiceProvider {
/**
* Retrieve the request token.
*
* @return request token
*/
OAuthToken getRequestToken();
/**
* Returns the URL where you should redirect your users to authenticate
* your application.
*
* @param requestToken the request token you need to authorize
* @return the URL where you should redirect your users
* @return the OAuth service URL to redirect your users for authentication
*/
String getAuthorizationUrl(OAuthToken requestToken);
String getAuthorizationUrl();
/**
* Retrieve the access token
*
* @param requestToken request token (obtained previously)
* @param verifier verifier code
* @return access token
*/
OAuthToken getAccessToken(OAuthToken requestToken, OAuthVerifier verifier);
OAuthToken getAccessToken(OAuthVerifier verifier);
/**
* After establishing of secure communication channel, this method supossed to

View File

@ -20,15 +20,18 @@ public class OAuthUserInfo {
private final String userName;
private final String emailAddress;
private final String displayName;
private final String claimedIdentity;
public OAuthUserInfo(String externalId,
String userName,
String emailAddress,
String displayName) {
String displayName,
String claimedIdentity) {
this.externalId = externalId;
this.userName = userName;
this.emailAddress = emailAddress;
this.displayName = displayName;
this.claimedIdentity = claimedIdentity;
}
public String getExternalId() {
@ -46,4 +49,8 @@ public class OAuthUserInfo {
public String getDisplayName() {
return displayName;
}
public String getClaimedIdentity() {
return claimedIdentity;
}
}

View File

@ -583,6 +583,12 @@ public class ChangeScreen extends Screen {
@Override
public void onKeyPress(KeyPressEvent event) {
if (Gerrit.isSignedIn()) {
// In Firefox this event is mistakenly called when F5 is pressed so
// differentiate F5 from 't' by checking the charCode(F5=0, t=116).
if (event.getNativeEvent().getCharCode() == 0) {
Window.Location.reload();
return;
}
if (topic.canEdit()) {
topic.onEdit();
}

View File

@ -79,7 +79,9 @@ public class OnlineReindexer {
SiteIndexer.Result result =
batchIndexer.indexAll(index, projectCache.all());
if (!result.success()) {
log.error("Online reindex of schema version {} failed", version(index));
log.error("Online reindex of schema version {} failed. Successfully"
+ " indexed {} changes, failed to index {} changes",
version(index), result.doneCount(), result.failedCount());
return;
}

View File

@ -11,9 +11,11 @@ java_library(
'//gerrit-common:annotations',
'//gerrit-extension-api:api',
'//gerrit-httpd:httpd',
'//gerrit-reviewdb:server',
'//gerrit-server:server',
'//lib:gson',
'//lib:guava',
'//lib:gwtorm',
'//lib/commons:codec',
'//lib/guice:guice',
'//lib/guice:guice-servlet',

View File

@ -23,9 +23,11 @@ import com.google.gerrit.extensions.auth.oauth.OAuthUserInfo;
import com.google.gerrit.extensions.auth.oauth.OAuthVerifier;
import com.google.gerrit.extensions.registration.DynamicItem;
import com.google.gerrit.httpd.WebSession;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.server.account.AccountException;
import com.google.gerrit.server.account.AccountManager;
import com.google.gerrit.server.account.AuthResult;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.servlet.SessionScoped;
@ -87,8 +89,7 @@ class OAuthSession {
}
log.debug("Login-Retrieve-User " + this);
token = oauth.getAccessToken(null,
new OAuthVerifier(request.getParameter("code")));
token = oauth.getAccessToken(new OAuthVerifier(request.getParameter("code")));
user = oauth.getUserInfo(token);
@ -103,7 +104,7 @@ class OAuthSession {
} else {
log.debug("Login-PHASE1 " + this);
redirectUrl = request.getRequestURI();
response.sendRedirect(oauth.getAuthorizationUrl(null) +
response.sendRedirect(oauth.getAuthorizationUrl() +
"&state=" + state);
return false;
}
@ -113,11 +114,48 @@ class OAuthSession {
throws IOException {
com.google.gerrit.server.account.AuthRequest areq =
new com.google.gerrit.server.account.AuthRequest(user.getExternalId());
areq.setUserName(user.getUserName());
areq.setEmailAddress(user.getEmailAddress());
areq.setDisplayName(user.getDisplayName());
AuthResult arsp;
try {
String claimedIdentifier = user.getClaimedIdentity();
Account.Id actualId = accountManager.lookup(user.getExternalId());
if (!Strings.isNullOrEmpty(claimedIdentifier)) {
Account.Id claimedId = accountManager.lookup(claimedIdentifier);
if (claimedId != null && actualId != null) {
if (claimedId.equals(actualId)) {
// Both link to the same account, that's what we expected.
log.debug("OAuth2: claimed identity equals current id");
} else {
// This is (for now) a fatal error. There are two records
// for what might be the same user.
//
log.error("OAuth accounts disagree over user identity:\n"
+ " Claimed ID: " + claimedId + " is " + claimedIdentifier
+ "\n" + " Delgate ID: " + actualId + " is "
+ user.getExternalId());
rsp.sendError(HttpServletResponse.SC_FORBIDDEN);
return;
}
} else if (claimedId != null && actualId == null) {
// Claimed account already exists: link to it.
//
log.info("OAuth2: linking claimed identity to {}",
claimedId.toString());
try {
accountManager.link(claimedId, areq);
} catch (OrmException e) {
log.error("Cannot link: " + user.getExternalId()
+ " to user identity:\n"
+ " Claimed ID: " + claimedId + " is " + claimedIdentifier);
rsp.sendError(HttpServletResponse.SC_FORBIDDEN);
return;
}
}
} else {
log.debug("OAuth2: claimed identity is empty");
}
areq.setUserName(user.getUserName());
areq.setEmailAddress(user.getEmailAddress());
areq.setDisplayName(user.getDisplayName());
arsp = accountManager.authenticate(areq);
} catch (AccountException e) {
log.error("Unable to authenticate user \"" + user + "\"", e);

View File

@ -144,6 +144,7 @@ class OpenIdServiceImpl {
final AuthRequest aReq;
try {
aReq = manager.authenticate(state.discovered, state.retTo.toString());
log.debug("OpenID: openid-realm={}", state.contextUrl);
aReq.setRealm(state.contextUrl);
if (requestRegistration(aReq)) {

View File

@ -14,6 +14,7 @@
package com.google.gerrit.pgm.util;
import static com.google.gerrit.server.config.GerritServerConfigModule.getSecureStoreClassName;
import static com.google.inject.Scopes.SINGLETON;
import static com.google.inject.Stage.PRODUCTION;
@ -24,7 +25,6 @@ import com.google.gerrit.lifecycle.LifecycleModule;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.config.GerritServerConfigModule;
import com.google.gerrit.server.config.SitePath;
import com.google.gerrit.server.config.SitePaths;
import com.google.gerrit.server.git.LocalDiskRepositoryManager;
import com.google.gerrit.server.schema.DataSourceModule;
import com.google.gerrit.server.schema.DataSourceProvider;
@ -41,20 +41,15 @@ import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.Module;
import com.google.inject.Provider;
import com.google.inject.ProvisionException;
import com.google.inject.TypeLiteral;
import com.google.inject.name.Named;
import com.google.inject.name.Names;
import com.google.inject.spi.Message;
import com.google.inject.util.Providers;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.storage.file.FileBasedConfig;
import org.eclipse.jgit.util.FS;
import org.kohsuke.args4j.Option;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.nio.file.Files;
import java.nio.file.Path;
@ -190,27 +185,7 @@ public abstract class SiteProgram extends AbstractProgram {
}
protected final String getConfiguredSecureStoreClass() {
Module m = new AbstractModule() {
@Override
protected void configure() {
bind(Path.class).annotatedWith(SitePath.class).toInstance(getSitePath());
bind(SitePaths.class);
}
};
Injector i = Guice.createInjector(m);
SitePaths site = i.getInstance(SitePaths.class);
FileBasedConfig cfg =
new FileBasedConfig(site.gerrit_config.toFile(), FS.DETECTED);
if (!cfg.getFile().exists()) {
return null;
}
try {
cfg.load();
return cfg.getString("gerrit", null, "secureStoreClass");
} catch (IOException | ConfigInvalidException e) {
throw new ProvisionException(e.getMessage(), e);
}
return getSecureStoreClassName(sitePath);
}
private String getDbType(Provider<DataSource> dsProvider) {

View File

@ -15,16 +15,16 @@
# Version should match lib/bouncycastle/BUCK
[library "bouncyCastleProvider"]
name = Bouncy Castle Crypto Provider v149
url = http://www.bouncycastle.org/download/bcprov-jdk15on-149.jar
sha1 = f5155f04330459104b79923274db5060c1057b99
name = Bouncy Castle Crypto Provider v151
url = http://www.bouncycastle.org/download/bcprov-jdk15on-151.jar
sha1 = 9ab8afcc2842d5ef06eb775a0a2b12783b99aa80
remove = bcprov-.*[.]jar
# Version should match lib/bouncycastle/BUCK
[library "bouncyCastleSSL"]
name = Bouncy Castle Crypto SSL v149
url = http://www.bouncycastle.org/download/bcpkix-jdk15on-149.jar
sha1 = 924cc7ad2f589630c97b918f044296ebf1bb6855
name = Bouncy Castle Crypto SSL v151
url = http://www.bouncycastle.org/download/bcpkix-jdk15on-151.jar
sha1 = 6c8c1f61bf27a09f9b1a8abc201523669bba9597
needs = bouncyCastleProvider
remove = bcpkix-.*[.]jar

View File

@ -40,8 +40,7 @@ public class DefaultRealm extends AbstractRealm {
@Override
public boolean allowsEdit(final Account.FieldName field) {
if (authConfig.getAuthType() == AuthType.HTTP
|| authConfig.getAuthType() == AuthType.OAUTH) {
if (authConfig.getAuthType() == AuthType.HTTP) {
switch (field) {
case USER_NAME:
return false;

View File

@ -16,14 +16,61 @@ package com.google.gerrit.server.config;
import static com.google.inject.Scopes.SINGLETON;
import com.google.gerrit.server.securestore.DefaultSecureStore;
import com.google.gerrit.server.securestore.SecureStore;
import com.google.gerrit.server.securestore.SecureStoreProvider;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.ProvisionException;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.storage.file.FileBasedConfig;
import org.eclipse.jgit.util.FS;
import java.io.IOException;
import java.nio.file.Path;
/** Creates {@link GerritServerConfig}. */
public class GerritServerConfigModule extends AbstractModule {
public static String getSecureStoreClassName(final Path sitePath) {
if (sitePath != null) {
return getSecureStoreFromGerritConfig(sitePath);
}
String secureStoreProperty = System.getProperty("gerrit.secure_store_class");
return nullToDefault(secureStoreProperty);
}
private static String getSecureStoreFromGerritConfig(final Path sitePath) {
AbstractModule m = new AbstractModule() {
@Override
protected void configure() {
bind(Path.class).annotatedWith(SitePath.class).toInstance(sitePath);
bind(SitePaths.class);
}
};
Injector injector = Guice.createInjector(m);
SitePaths site = injector.getInstance(SitePaths.class);
FileBasedConfig cfg = new FileBasedConfig(site.gerrit_config.toFile(), FS.DETECTED);
if (!cfg.getFile().exists()) {
return DefaultSecureStore.class.getName();
}
try {
cfg.load();
String className = cfg.getString("gerrit", null, "secureStoreClass");
return nullToDefault(className);
} catch (IOException | ConfigInvalidException e) {
throw new ProvisionException(e.getMessage(), e);
}
}
private static String nullToDefault(String className) {
return className != null ? className : DefaultSecureStore.class.getName();
}
@Override
protected void configure() {
bind(SitePaths.class);

View File

@ -38,6 +38,9 @@ import org.bouncycastle.openpgp.PGPPublicKey;
import org.bouncycastle.openpgp.PGPPublicKeyRing;
import org.bouncycastle.openpgp.PGPPublicKeyRingCollection;
import org.bouncycastle.openpgp.PGPUtil;
import org.bouncycastle.openpgp.bc.BcPGPPublicKeyRingCollection;
import org.bouncycastle.openpgp.operator.bc.BcPGPDataEncryptorBuilder;
import org.bouncycastle.openpgp.operator.bc.BcPublicKeyKeyEncryptionMethodGenerator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -49,7 +52,6 @@ import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SecureRandom;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
@ -94,7 +96,7 @@ class EncryptedContactStore implements ContactStore {
//
try {
encrypt("test", new Date(0), "test".getBytes("UTF-8"));
} catch (NoSuchProviderException | PGPException | IOException e) {
} catch (PGPException | IOException e) {
throw new ProvisionException("PGP encryption not available", e);
}
}
@ -107,7 +109,7 @@ class EncryptedContactStore implements ContactStore {
private static PGPPublicKeyRingCollection readPubRing(Path pub) {
try (InputStream fin = Files.newInputStream(pub);
InputStream in = PGPUtil.getDecoderStream(fin)) {
return new PGPPublicKeyRingCollection(in);
return new BcPGPPublicKeyRingCollection(in);
} catch (IOException | PGPException e) {
throw new ProvisionException("Cannot read " + pub, e);
}
@ -150,23 +152,26 @@ class EncryptedContactStore implements ContactStore {
u.put("account_id", String.valueOf(account.getId().get()));
u.put("data", encStr);
connFactory.open(storeUrl).store(u.toString().getBytes("UTF-8"));
} catch (IOException | PGPException | NoSuchProviderException e) {
} catch (IOException | PGPException e) {
log.error("Cannot store encrypted contact information", e);
throw new ContactInformationStoreException(e);
}
}
@SuppressWarnings("deprecation")
private final PGPEncryptedDataGenerator cpk()
throws NoSuchProviderException, PGPException {
private final PGPEncryptedDataGenerator cpk() {
final BcPGPDataEncryptorBuilder builder =
new BcPGPDataEncryptorBuilder(PGPEncryptedData.CAST5)
.setSecureRandom(prng);
PGPEncryptedDataGenerator cpk =
new PGPEncryptedDataGenerator(PGPEncryptedData.CAST5, true, prng, "BC");
cpk.addMethod(dest);
new PGPEncryptedDataGenerator(builder, true);
final BcPublicKeyKeyEncryptionMethodGenerator methodGenerator =
new BcPublicKeyKeyEncryptionMethodGenerator(dest);
cpk.addMethod(methodGenerator);
return cpk;
}
private byte[] encrypt(final String name, final Date date,
final byte[] rawText) throws NoSuchProviderException, PGPException,
final byte[] rawText) throws PGPException,
IOException {
final byte[] zText = compress(name, date, rawText);

View File

@ -15,6 +15,7 @@
package com.google.gerrit.server.git;
import com.google.common.collect.Lists;
import com.google.common.util.concurrent.ListenableFutureTask;
import com.google.gerrit.extensions.events.LifecycleListener;
import com.google.gerrit.lifecycle.LifecycleModule;
import com.google.gerrit.reviewdb.client.Project;
@ -28,6 +29,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.Thread.UncaughtExceptionHandler;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
@ -385,6 +387,26 @@ public class WorkQueue {
@Override
public String toString() {
//This is a workaround to be able to print a proper name when the task
//is wrapped into a ListenableFutureTask.
if (runnable instanceof ListenableFutureTask<?>) {
String errorMessage;
try {
for (Field field : ListenableFutureTask.class.getSuperclass()
.getDeclaredFields()) {
if (field.getType().isAssignableFrom(Callable.class)) {
field.setAccessible(true);
return ((Callable<?>) field.get(runnable)).toString();
}
}
errorMessage = "Cannot find wrapped Callable field";
} catch (SecurityException | IllegalArgumentException
| IllegalAccessException e) {
errorMessage = "Cannot call toString on Callable field";
}
log.debug("Cannot get a proper name for ListenableFutureTask: {}",
errorMessage);
}
return runnable.toString();
}
}

View File

@ -206,10 +206,10 @@ public class PatchListLoader extends CacheLoader<PatchListKey, PatchList> {
} catch (InterruptedException | TimeoutException e) {
log.warn(timeoutMillis + " ms timeout reached for Diff loader"
+ " in project " + key.projectKey.get()
+ " on commit " + key.getNewId()
+ " on commit " + key.getNewId().name()
+ " on path " + diffEntry.getNewPath()
+ " comparing " + diffEntry.getOldId()
+ ".." + diffEntry.getNewId());
+ " comparing " + diffEntry.getOldId().name()
+ ".." + diffEntry.getNewId().name());
result.cancel(true);
return toFileHeaderWithoutMyersDiff(diffFormatter, diffEntry);
} catch (ExecutionException e) {

View File

@ -0,0 +1,72 @@
// Copyright (C) 2014 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.sshd;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import org.apache.sshd.common.Session;
import org.apache.sshd.common.SessionListener;
import org.apache.sshd.server.PublickeyAuthenticator;
import org.apache.sshd.server.session.ServerSession;
import java.security.PublicKey;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@Singleton
public class CachingPublicKeyAuthenticator implements PublickeyAuthenticator,
SessionListener {
private final PublickeyAuthenticator authenticator;
private final Map<ServerSession, Map<PublicKey, Boolean>> sessionCache;
@Inject
public CachingPublicKeyAuthenticator(DatabasePubKeyAuth authenticator) {
this.authenticator = authenticator;
this.sessionCache = new ConcurrentHashMap<>();
}
@Override
public boolean authenticate(String username, PublicKey key,
ServerSession session) {
Map<PublicKey, Boolean> m = sessionCache.get(session);
if (m == null) {
m = new HashMap<>();
sessionCache.put(session, m);
session.addListener(this);
}
if (m.containsKey(key)) {
return m.get(key);
}
boolean r = authenticator.authenticate(username, key, session);
m.put(key, r);
return r;
}
@Override
public void sessionCreated(Session session) {
}
@Override
public void sessionEvent(Session sesssion, Event event) {
}
@Override
public void sessionClosed(Session session) {
sessionCache.remove(session);
}
}

View File

@ -15,6 +15,7 @@
package com.google.gerrit.sshd;
import static java.nio.charset.StandardCharsets.UTF_8;
import com.google.common.base.Preconditions;
import com.google.gerrit.common.FileUtil;
import com.google.gerrit.reviewdb.client.AccountSshKey;
@ -23,7 +24,6 @@ import com.google.gerrit.server.PeerDaemonUser;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.config.SitePaths;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import org.apache.commons.codec.binary.Base64;
import org.apache.sshd.common.KeyPairProvider;
@ -51,7 +51,6 @@ import java.util.Set;
/**
* Authenticates by public key through {@link AccountSshKey} entities.
*/
@Singleton
class DatabasePubKeyAuth implements PublickeyAuthenticator {
private static final Logger log =
LoggerFactory.getLogger(DatabasePubKeyAuth.class);
@ -96,10 +95,10 @@ class DatabasePubKeyAuth implements PublickeyAuthenticator {
}
@Override
public boolean authenticate(String username,
final PublicKey suppliedKey, final ServerSession session) {
final SshSession sd = session.getAttribute(SshSession.KEY);
public boolean authenticate(String username, PublicKey suppliedKey,
ServerSession session) {
SshSession sd = session.getAttribute(SshSession.KEY);
Preconditions.checkState(sd.getCurrentUser() == null);
if (PeerDaemonUser.USER_NAME.equals(username)) {
if (myHostKeys.contains(suppliedKey)
|| getPeerKeys().contains(suppliedKey)) {
@ -116,10 +115,10 @@ class DatabasePubKeyAuth implements PublickeyAuthenticator {
username = username.toLowerCase(Locale.US);
}
final Iterable<SshKeyCacheEntry> keyList = sshKeyCache.get(username);
final SshKeyCacheEntry key = find(keyList, suppliedKey);
Iterable<SshKeyCacheEntry> keyList = sshKeyCache.get(username);
SshKeyCacheEntry key = find(keyList, suppliedKey);
if (key == null) {
final String err;
String err;
if (keyList == SshKeyCacheImpl.NO_SUCH_USER) {
err = "user-not-found";
} else if (keyList == SshKeyCacheImpl.NO_KEYS) {
@ -137,7 +136,7 @@ class DatabasePubKeyAuth implements PublickeyAuthenticator {
// security check to ensure there aren't two users sharing the same
// user name on the server.
//
for (final SshKeyCacheEntry otherKey : keyList) {
for (SshKeyCacheEntry otherKey : keyList) {
if (!key.getAccount().equals(otherKey.getAccount())) {
sd.authenticationError(username, "keys-cross-accounts");
return false;

View File

@ -46,6 +46,7 @@ import org.apache.sshd.common.KeyExchange;
import org.apache.sshd.common.KeyPairProvider;
import org.apache.sshd.common.NamedFactory;
import org.apache.sshd.common.Random;
import org.apache.sshd.common.RequestHandler;
import org.apache.sshd.common.Session;
import org.apache.sshd.common.Signature;
import org.apache.sshd.common.SshdSocketAddress;
@ -68,10 +69,11 @@ import org.apache.sshd.common.forward.TcpipServerChannel;
import org.apache.sshd.common.future.CloseFuture;
import org.apache.sshd.common.future.SshFutureListener;
import org.apache.sshd.common.io.IoAcceptor;
import org.apache.sshd.common.io.IoServiceFactory;
import org.apache.sshd.common.io.IoServiceFactoryFactory;
import org.apache.sshd.common.io.IoSession;
import org.apache.sshd.common.io.mina.MinaServiceFactory;
import org.apache.sshd.common.io.mina.MinaServiceFactoryFactory;
import org.apache.sshd.common.io.mina.MinaSession;
import org.apache.sshd.common.io.nio2.Nio2ServiceFactoryFactory;
import org.apache.sshd.common.mac.HMACMD5;
import org.apache.sshd.common.mac.HMACMD596;
import org.apache.sshd.common.mac.HMACSHA1;
@ -80,7 +82,9 @@ import org.apache.sshd.common.random.BouncyCastleRandom;
import org.apache.sshd.common.random.JceRandom;
import org.apache.sshd.common.random.SingletonRandomFactory;
import org.apache.sshd.common.session.AbstractSession;
import org.apache.sshd.common.session.ConnectionService;
import org.apache.sshd.common.signature.SignatureDSA;
import org.apache.sshd.common.signature.SignatureECDSA;
import org.apache.sshd.common.signature.SignatureRSA;
import org.apache.sshd.common.util.Buffer;
import org.apache.sshd.common.util.SecurityUtils;
@ -92,6 +96,10 @@ import org.apache.sshd.server.auth.UserAuthPublicKey;
import org.apache.sshd.server.auth.gss.GSSAuthenticator;
import org.apache.sshd.server.auth.gss.UserAuthGSS;
import org.apache.sshd.server.channel.ChannelSession;
import org.apache.sshd.server.global.CancelTcpipForwardHandler;
import org.apache.sshd.server.global.KeepAliveHandler;
import org.apache.sshd.server.global.NoMoreSessionsHandler;
import org.apache.sshd.server.global.TcpipForwardHandler;
import org.apache.sshd.server.kex.DHG1;
import org.apache.sshd.server.kex.DHG14;
import org.apache.sshd.server.session.SessionFactory;
@ -137,6 +145,7 @@ import java.util.List;
*/
@Singleton
public class SshDaemon extends SshServer implements SshInfo, LifecycleListener {
@SuppressWarnings("hiding") // Don't use AbstractCloseable's logger.
private static final Logger log = LoggerFactory.getLogger(SshDaemon.class);
public static enum SshSessionBackend {
@ -184,6 +193,15 @@ public class SshDaemon extends SshServer implements SshInfo, LifecycleListener {
IDLE_TIMEOUT,
String.valueOf(SECONDS.toMillis(idleTimeoutSeconds)));
long rekeyTimeLimit = ConfigUtil.getTimeUnit(cfg, "sshd", null,
"rekeyTimeLimit", 3600, SECONDS);
getProperties().put(
REKEY_TIME_LIMIT,
String.valueOf(SECONDS.toMillis(rekeyTimeLimit)));
getProperties().put(REKEY_BYTES_LIMIT,
String.valueOf(cfg.getLong("sshd", "rekeyBytesLimit", 1024 * 1024 * 1024 /* 1GB */)));
final int maxConnectionsPerUser =
cfg.getInt("sshd", "maxConnectionsPerUser", 64);
if (0 < maxConnectionsPerUser) {
@ -196,8 +214,13 @@ public class SshDaemon extends SshServer implements SshInfo, LifecycleListener {
final String kerberosPrincipal = cfg.getString(
"sshd", null, "kerberosPrincipal");
System.setProperty(IoServiceFactory.class.getName(),
MinaServiceFactory.class.getName());
SshSessionBackend backend = cfg.getEnum(
"sshd", null, "backend", SshSessionBackend.MINA);
System.setProperty(IoServiceFactoryFactory.class.getName(),
backend == SshSessionBackend.MINA
? MinaServiceFactoryFactory.class.getName()
: Nio2ServiceFactoryFactory.class.getName());
if (SecurityUtils.isBouncyCastleRegistered()) {
initProviderBouncyCastle(cfg);
@ -254,6 +277,12 @@ public class SshDaemon extends SshServer implements SshInfo, LifecycleListener {
return new GerritServerSession(server, ioSession);
}
});
setGlobalRequestHandlers(Arrays.<RequestHandler<ConnectionService>> asList(
new KeepAliveHandler(),
new NoMoreSessionsHandler(),
new TcpipForwardHandler(),
new CancelTcpipForwardHandler()
));
hostKeys = computeHostKeys();
}
@ -303,8 +332,10 @@ public class SshDaemon extends SshServer implements SshInfo, LifecycleListener {
public synchronized void stop() {
if (daemonAcceptor != null) {
try {
daemonAcceptor.dispose();
daemonAcceptor.close(true).await();
log.info("Stopped Gerrit SSHD");
} catch (InterruptedException e) {
log.warn("Exception caught while closing", e);
} finally {
daemonAcceptor = null;
}
@ -405,6 +436,12 @@ public class SshDaemon extends SshServer implements SshInfo, LifecycleListener {
public void fill(byte[] bytes, int start, int len) {
random.nextBytes(bytes, start, len);
}
@Override
public int random(int n) {
// TODO Auto-generated method stub
return 0;
}
}
private void initProviderJce() {
@ -526,7 +563,11 @@ public class SshDaemon extends SshServer implements SshInfo, LifecycleListener {
private void initSignatures() {
setSignatureFactories(Arrays.<NamedFactory<Signature>> asList(
new SignatureDSA.Factory(), new SignatureRSA.Factory()));
new SignatureDSA.Factory(),
new SignatureRSA.Factory(),
new SignatureECDSA.NISTP256Factory(),
new SignatureECDSA.NISTP384Factory(),
new SignatureECDSA.NISTP521Factory()));
}
private void initCompression() {
@ -621,6 +662,11 @@ public class SshDaemon extends SshServer implements SshInfo, LifecycleListener {
@Override
public SshFile getFile(String file) {
return null;
}
@Override
public FileSystemView getNormalizedView() {
return this;
}};
}
});

View File

@ -81,7 +81,7 @@ public class SshModule extends LifecycleModule {
bind(QueueProvider.class).to(CommandExecutorQueueProvider.class).in(SINGLETON);
bind(GSSAuthenticator.class).to(GerritGSSAuthenticator.class);
bind(PublickeyAuthenticator.class).to(DatabasePubKeyAuth.class);
bind(PublickeyAuthenticator.class).to(CachingPublicKeyAuthenticator.class);
bind(ModuleGenerator.class).to(SshAutoRegisterModuleGenerator.class);
bind(SshPluginStarterCallback.class);

View File

@ -25,8 +25,8 @@ import com.google.gerrit.sshd.SshDaemon;
import com.google.gerrit.sshd.SshSession;
import com.google.inject.Inject;
import org.apache.sshd.common.future.CloseFuture;
import org.apache.sshd.common.io.IoAcceptor;
import org.apache.sshd.common.io.IoCloseFuture;
import org.apache.sshd.common.io.IoSession;
import org.apache.sshd.server.session.ServerSession;
import org.kohsuke.args4j.Argument;
@ -76,7 +76,7 @@ final class CloseConnection extends SshCommand {
if (sshSession != null && sshSession.getSessionId() == id) {
connectionFound = true;
stdout.println("closing connection " + sessionId + "...");
IoCloseFuture future = io.close(true);
CloseFuture future = io.close(true);
if (wait) {
try {
future.await();

View File

@ -56,6 +56,7 @@ import com.google.gerrit.server.schema.DataSourceType;
import com.google.gerrit.server.schema.DatabaseModule;
import com.google.gerrit.server.schema.SchemaModule;
import com.google.gerrit.server.schema.SchemaVersionCheck;
import com.google.gerrit.server.securestore.SecureStoreClassName;
import com.google.gerrit.server.ssh.NoSshModule;
import com.google.gerrit.server.ssh.SshAddressesModule;
import com.google.gerrit.solr.SolrIndexModule;
@ -74,6 +75,7 @@ import com.google.inject.name.Names;
import com.google.inject.servlet.GuiceFilter;
import com.google.inject.servlet.GuiceServletContextListener;
import com.google.inject.spi.Message;
import com.google.inject.util.Providers;
import org.eclipse.jgit.lib.Config;
import org.slf4j.Logger;
@ -207,6 +209,7 @@ public class WebAppInitializer extends GuiceServletContextListener
private Injector createDbInjector() {
final List<Module> modules = new ArrayList<>();
AbstractModule secureStore = createSecureStoreModule();
if (sitePath != null) {
Module sitePathModule = new AbstractModule() {
@Override
@ -219,13 +222,13 @@ public class WebAppInitializer extends GuiceServletContextListener
Module configModule = new GerritServerConfigModule();
modules.add(configModule);
Injector cfgInjector = Guice.createInjector(sitePathModule, configModule);
Injector cfgInjector = Guice.createInjector(sitePathModule, configModule, secureStore);
Config cfg = cfgInjector.getInstance(Key.get(Config.class,
GerritServerConfig.class));
String dbType = cfg.getString("database", null, "type");
final DataSourceType dst = Guice.createInjector(new DataSourceModule(),
configModule, sitePathModule).getInstance(
configModule, sitePathModule, secureStore).getInstance(
Key.get(DataSourceType.class, Names.named(dbType.toLowerCase())));
modules.add(new LifecycleModule() {
@Override
@ -240,6 +243,7 @@ public class WebAppInitializer extends GuiceServletContextListener
});
} else {
modules.add(secureStore);
modules.add(new LifecycleModule() {
@Override
protected void configure() {
@ -376,4 +380,16 @@ public class WebAppInitializer extends GuiceServletContextListener
manager = null;
}
}
private AbstractModule createSecureStoreModule() {
return new AbstractModule() {
@Override
public void configure() {
String secureStoreClassName =
GerritServerConfigModule.getSecureStoreClassName(sitePath);
bind(String.class).annotatedWith(SecureStoreClassName.class).toProvider(
Providers.of(secureStoreClassName));
}
};
}
}

View File

@ -2,19 +2,19 @@ include_defs('//lib/maven.defs')
# This version must match the version that also appears in
# gerrit-pgm/src/main/resources/com/google/gerrit/pgm/libraries.config
VERSION = '1.49'
VERSION = '1.51'
maven_jar(
name = 'bcprov',
id = 'org.bouncycastle:bcprov-jdk15on:' + VERSION,
sha1 = 'f5155f04330459104b79923274db5060c1057b99',
sha1 = '9ab8afcc2842d5ef06eb775a0a2b12783b99aa80',
license = 'DO_NOT_DISTRIBUTE', #'bouncycastle'
)
maven_jar(
name = 'bcpg',
id = 'org.bouncycastle:bcpg-jdk15on:' + VERSION,
sha1 = '081d84be5b125e1997ab0e2244d1a2276b5de76c',
sha1 = 'b5fa4c280dfbf8bf7c260bc1e78044c7a1de5133',
license = 'DO_NOT_DISTRIBUTE', #'bouncycastle'
deps = [':bcprov'],
)
@ -22,7 +22,7 @@ maven_jar(
maven_jar(
name = 'bcpkix',
id = 'org.bouncycastle:bcpkix-jdk15on:' + VERSION,
sha1 = '924cc7ad2f589630c97b918f044296ebf1bb6855',
sha1 = '6c8c1f61bf27a09f9b1a8abc201523669bba9597',
license = 'DO_NOT_DISTRIBUTE', #'bouncycastle'
deps = [':bcprov'],
)

View File

@ -8,18 +8,17 @@ EXCLUDE = [
maven_jar(
name = 'sshd',
id = 'org.apache.sshd:sshd-core:0.9.0-4-g5967cfd',
sha1 = '449ec11c4417b295dbf1661585a50c6ec7d9a452',
id = 'org.apache.sshd:sshd-core:0.14.0',
sha1 = 'cb12fa1b1b07fb5ce3aa4f99b189743897bd4fca',
license = 'Apache2.0',
deps = [':core'],
exclude = EXCLUDE,
repository = GERRIT,
)
maven_jar(
name = 'core',
id = 'org.apache.mina:mina-core:2.0.7',
sha1 = 'c878e2aa82de748474a624ec3933e4604e446dec',
id = 'org.apache.mina:mina-core:2.0.8',
sha1 = 'd6ff69fa049aeaecdf0c04cafbb1ab53b7487883',
license = 'Apache2.0',
exclude = EXCLUDE,
)