Merge changes If8296539,Id907cc10
* changes: Close security hole allowing normal user to become admin Remove the generateHttpPassword capability
This commit is contained in:
commit
76623a1a56
@ -1205,13 +1205,6 @@ This capability doesn't imply permissions to the show-caches command. For that
|
|||||||
you need the <<capability_viewCaches,view caches capability>>.
|
you need the <<capability_viewCaches,view caches capability>>.
|
||||||
|
|
||||||
|
|
||||||
[[capability_generateHttpPassword]]
|
|
||||||
=== Generate HTTP Password
|
|
||||||
|
|
||||||
Allow the user to generate HTTP passwords for other users. Typically this would
|
|
||||||
be assigned to a non-interactive users group.
|
|
||||||
|
|
||||||
|
|
||||||
[[capability_kill]]
|
[[capability_kill]]
|
||||||
=== Kill Task
|
=== Kill Task
|
||||||
|
|
||||||
|
@ -26,12 +26,12 @@ verification step we force within the UI.
|
|||||||
Caller must be a member of the privileged 'Administrators' group,
|
Caller must be a member of the privileged 'Administrators' group,
|
||||||
or have been granted
|
or have been granted
|
||||||
link:access-control.html#capability_modifyAccount[the 'Modify Account' global capability].
|
link:access-control.html#capability_modifyAccount[the 'Modify Account' global capability].
|
||||||
|
For security reasons only the members of the privileged 'Administrators'
|
||||||
|
group can add or delete SSH keys for a user.
|
||||||
|
|
||||||
To set the HTTP password for the user account (option --http-password) or
|
To set the HTTP password for the user account (option --http-password) or
|
||||||
to clear the HTTP password (option --clear-http-password) caller must be
|
to clear the HTTP password (option --clear-http-password) caller must be
|
||||||
a member of the privileged 'Administrators' group, or have been granted
|
a member of the privileged 'Administrators' group.
|
||||||
link:access-control.html#capability_generateHttpPassword[the 'Generate HTTP Password' global capability]
|
|
||||||
in addition to 'Modify Account' global capability.
|
|
||||||
|
|
||||||
== SCRIPTING
|
== SCRIPTING
|
||||||
This command is intended to be used in scripts.
|
This command is intended to be used in scripts.
|
||||||
|
@ -61,9 +61,6 @@ public class GlobalCapability {
|
|||||||
/** Can flush any cache except the active web_sessions cache. */
|
/** Can flush any cache except the active web_sessions cache. */
|
||||||
public static final String FLUSH_CACHES = "flushCaches";
|
public static final String FLUSH_CACHES = "flushCaches";
|
||||||
|
|
||||||
/** Can generate HTTP passwords for user other than self. */
|
|
||||||
public static final String GENERATE_HTTP_PASSWORD = "generateHttpPassword";
|
|
||||||
|
|
||||||
/** Can terminate any task using the kill command. */
|
/** Can terminate any task using the kill command. */
|
||||||
public static final String KILL_TASK = "killTask";
|
public static final String KILL_TASK = "killTask";
|
||||||
|
|
||||||
@ -112,7 +109,6 @@ public class GlobalCapability {
|
|||||||
NAMES_ALL.add(CREATE_PROJECT);
|
NAMES_ALL.add(CREATE_PROJECT);
|
||||||
NAMES_ALL.add(EMAIL_REVIEWERS);
|
NAMES_ALL.add(EMAIL_REVIEWERS);
|
||||||
NAMES_ALL.add(FLUSH_CACHES);
|
NAMES_ALL.add(FLUSH_CACHES);
|
||||||
NAMES_ALL.add(GENERATE_HTTP_PASSWORD);
|
|
||||||
NAMES_ALL.add(KILL_TASK);
|
NAMES_ALL.add(KILL_TASK);
|
||||||
NAMES_ALL.add(MODIFY_ACCOUNT);
|
NAMES_ALL.add(MODIFY_ACCOUNT);
|
||||||
NAMES_ALL.add(PRIORITY);
|
NAMES_ALL.add(PRIORITY);
|
||||||
|
@ -63,7 +63,7 @@ public class AddSshKey implements RestModifyView<AccountResource, Input> {
|
|||||||
public Response<SshKeyInfo> apply(AccountResource rsrc, Input input)
|
public Response<SshKeyInfo> apply(AccountResource rsrc, Input input)
|
||||||
throws AuthException, BadRequestException, OrmException, IOException {
|
throws AuthException, BadRequestException, OrmException, IOException {
|
||||||
if (self.get() != rsrc.getUser()
|
if (self.get() != rsrc.getUser()
|
||||||
&& !self.get().getCapabilities().canModifyAccount()) {
|
&& !self.get().getCapabilities().canAdministrateServer()) {
|
||||||
throw new AuthException("not allowed to add SSH keys");
|
throw new AuthException("not allowed to add SSH keys");
|
||||||
}
|
}
|
||||||
return apply(rsrc.getUser(), input);
|
return apply(rsrc.getUser(), input);
|
||||||
|
@ -169,12 +169,6 @@ public class CapabilityControl {
|
|||||||
|| canAdministrateServer();
|
|| canAdministrateServer();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return true if the user can generate HTTP passwords for users other than self. */
|
|
||||||
public boolean canGenerateHttpPassword() {
|
|
||||||
return canPerform(GlobalCapability.GENERATE_HTTP_PASSWORD)
|
|
||||||
|| canAdministrateServer();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @return true if the user can impersonate another user. */
|
/** @return true if the user can impersonate another user. */
|
||||||
public boolean canRunAs() {
|
public boolean canRunAs() {
|
||||||
return canPerform(GlobalCapability.RUN_AS);
|
return canPerform(GlobalCapability.RUN_AS);
|
||||||
|
@ -14,9 +14,11 @@
|
|||||||
|
|
||||||
package com.google.gerrit.server.account;
|
package com.google.gerrit.server.account;
|
||||||
|
|
||||||
|
import com.google.gerrit.extensions.restapi.AuthException;
|
||||||
import com.google.gerrit.extensions.restapi.Response;
|
import com.google.gerrit.extensions.restapi.Response;
|
||||||
import com.google.gerrit.extensions.restapi.RestModifyView;
|
import com.google.gerrit.extensions.restapi.RestModifyView;
|
||||||
import com.google.gerrit.reviewdb.server.ReviewDb;
|
import com.google.gerrit.reviewdb.server.ReviewDb;
|
||||||
|
import com.google.gerrit.server.CurrentUser;
|
||||||
import com.google.gerrit.server.account.DeleteSshKey.Input;
|
import com.google.gerrit.server.account.DeleteSshKey.Input;
|
||||||
import com.google.gerrit.server.ssh.SshKeyCache;
|
import com.google.gerrit.server.ssh.SshKeyCache;
|
||||||
import com.google.gwtorm.server.OrmException;
|
import com.google.gwtorm.server.OrmException;
|
||||||
@ -32,18 +34,26 @@ public class DeleteSshKey implements
|
|||||||
public static class Input {
|
public static class Input {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private final Provider<CurrentUser> self;
|
||||||
private final Provider<ReviewDb> dbProvider;
|
private final Provider<ReviewDb> dbProvider;
|
||||||
private final SshKeyCache sshKeyCache;
|
private final SshKeyCache sshKeyCache;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
DeleteSshKey(Provider<ReviewDb> dbProvider, SshKeyCache sshKeyCache) {
|
DeleteSshKey(Provider<ReviewDb> dbProvider,
|
||||||
|
Provider<CurrentUser> self,
|
||||||
|
SshKeyCache sshKeyCache) {
|
||||||
|
this.self = self;
|
||||||
this.dbProvider = dbProvider;
|
this.dbProvider = dbProvider;
|
||||||
this.sshKeyCache = sshKeyCache;
|
this.sshKeyCache = sshKeyCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Response<?> apply(AccountResource.SshKey rsrc, Input input)
|
public Response<?> apply(AccountResource.SshKey rsrc, Input input)
|
||||||
throws OrmException {
|
throws AuthException, OrmException {
|
||||||
|
if (self.get() != rsrc.getUser()
|
||||||
|
&& !self.get().getCapabilities().canAdministrateServer()) {
|
||||||
|
throw new AuthException("not allowed to delete SSH keys");
|
||||||
|
}
|
||||||
dbProvider.get().accountSshKeys()
|
dbProvider.get().accountSshKeys()
|
||||||
.deleteKeys(Collections.singleton(rsrc.getSshKey().getKey()));
|
.deleteKeys(Collections.singleton(rsrc.getSshKey().getKey()));
|
||||||
sshKeyCache.evict(rsrc.getUser().getUserName());
|
sshKeyCache.evict(rsrc.getUser().getUserName());
|
||||||
|
@ -20,7 +20,6 @@ import static com.google.gerrit.common.data.GlobalCapability.CREATE_GROUP;
|
|||||||
import static com.google.gerrit.common.data.GlobalCapability.CREATE_PROJECT;
|
import static com.google.gerrit.common.data.GlobalCapability.CREATE_PROJECT;
|
||||||
import static com.google.gerrit.common.data.GlobalCapability.EMAIL_REVIEWERS;
|
import static com.google.gerrit.common.data.GlobalCapability.EMAIL_REVIEWERS;
|
||||||
import static com.google.gerrit.common.data.GlobalCapability.FLUSH_CACHES;
|
import static com.google.gerrit.common.data.GlobalCapability.FLUSH_CACHES;
|
||||||
import static com.google.gerrit.common.data.GlobalCapability.GENERATE_HTTP_PASSWORD;
|
|
||||||
import static com.google.gerrit.common.data.GlobalCapability.KILL_TASK;
|
import static com.google.gerrit.common.data.GlobalCapability.KILL_TASK;
|
||||||
import static com.google.gerrit.common.data.GlobalCapability.MODIFY_ACCOUNT;
|
import static com.google.gerrit.common.data.GlobalCapability.MODIFY_ACCOUNT;
|
||||||
import static com.google.gerrit.common.data.GlobalCapability.PRIORITY;
|
import static com.google.gerrit.common.data.GlobalCapability.PRIORITY;
|
||||||
@ -115,7 +114,6 @@ class GetCapabilities implements RestReadView<AccountResource> {
|
|||||||
have.put(CREATE_PROJECT, cc.canCreateProject());
|
have.put(CREATE_PROJECT, cc.canCreateProject());
|
||||||
have.put(EMAIL_REVIEWERS, cc.canEmailReviewers());
|
have.put(EMAIL_REVIEWERS, cc.canEmailReviewers());
|
||||||
have.put(FLUSH_CACHES, cc.canFlushCaches());
|
have.put(FLUSH_CACHES, cc.canFlushCaches());
|
||||||
have.put(GENERATE_HTTP_PASSWORD, cc.canGenerateHttpPassword());
|
|
||||||
have.put(KILL_TASK, cc.canKillTask());
|
have.put(KILL_TASK, cc.canKillTask());
|
||||||
have.put(MODIFY_ACCOUNT, cc.canModifyAccount());
|
have.put(MODIFY_ACCOUNT, cc.canModifyAccount());
|
||||||
have.put(RUN_GC, cc.canRunGC());
|
have.put(RUN_GC, cc.canRunGC());
|
||||||
|
@ -36,7 +36,7 @@ public class GetHttpPassword implements RestReadView<AccountResource> {
|
|||||||
public String apply(AccountResource rsrc) throws AuthException,
|
public String apply(AccountResource rsrc) throws AuthException,
|
||||||
ResourceNotFoundException {
|
ResourceNotFoundException {
|
||||||
if (self.get() != rsrc.getUser()
|
if (self.get() != rsrc.getUser()
|
||||||
&& !self.get().getCapabilities().canGenerateHttpPassword()) {
|
&& !self.get().getCapabilities().canAdministrateServer()) {
|
||||||
throw new AuthException("not allowed to get http password");
|
throw new AuthException("not allowed to get http password");
|
||||||
}
|
}
|
||||||
AccountState s = rsrc.getUser().state();
|
AccountState s = rsrc.getUser().state();
|
||||||
|
@ -79,19 +79,19 @@ public class PutHttpPassword implements RestModifyView<AccountResource, Input> {
|
|||||||
String newPassword;
|
String newPassword;
|
||||||
if (input.generate) {
|
if (input.generate) {
|
||||||
if (self.get() != rsrc.getUser()
|
if (self.get() != rsrc.getUser()
|
||||||
&& !self.get().getCapabilities().canGenerateHttpPassword()) {
|
&& !self.get().getCapabilities().canAdministrateServer()) {
|
||||||
throw new AuthException("not allowed to generate HTTP password");
|
throw new AuthException("not allowed to generate HTTP password");
|
||||||
}
|
}
|
||||||
newPassword = generate();
|
newPassword = generate();
|
||||||
|
|
||||||
} else if (input.httpPassword == null) {
|
} else if (input.httpPassword == null) {
|
||||||
if (self.get() != rsrc.getUser()
|
if (self.get() != rsrc.getUser()
|
||||||
&& !self.get().getCapabilities().canGenerateHttpPassword()) {
|
&& !self.get().getCapabilities().canAdministrateServer()) {
|
||||||
throw new AuthException("not allowed to clear HTTP password");
|
throw new AuthException("not allowed to clear HTTP password");
|
||||||
}
|
}
|
||||||
newPassword = null;
|
newPassword = null;
|
||||||
} else {
|
} else {
|
||||||
if (!self.get().getCapabilities().canGenerateHttpPassword()) {
|
if (!self.get().getCapabilities().canAdministrateServer()) {
|
||||||
throw new AuthException("not allowed to set HTTP password directly, "
|
throw new AuthException("not allowed to set HTTP password directly, "
|
||||||
+ "requires the Generate HTTP Password permission");
|
+ "requires the Generate HTTP Password permission");
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,6 @@ public class CapabilityConstants extends TranslationBundle {
|
|||||||
public String createProject;
|
public String createProject;
|
||||||
public String emailReviewers;
|
public String emailReviewers;
|
||||||
public String flushCaches;
|
public String flushCaches;
|
||||||
public String generateHttpPassword;
|
|
||||||
public String killTask;
|
public String killTask;
|
||||||
public String modifyAccount;
|
public String modifyAccount;
|
||||||
public String priority;
|
public String priority;
|
||||||
|
@ -5,7 +5,6 @@ createGroup = Create Group
|
|||||||
createProject = Create Project
|
createProject = Create Project
|
||||||
emailReviewers = Email Reviewers
|
emailReviewers = Email Reviewers
|
||||||
flushCaches = Flush Caches
|
flushCaches = Flush Caches
|
||||||
generateHttpPassword = Generate HTTP Password
|
|
||||||
killTask = Kill Task
|
killTask = Kill Task
|
||||||
modifyAccount = Modify Account
|
modifyAccount = Modify Account
|
||||||
priority = Priority
|
priority = Priority
|
||||||
|
@ -18,6 +18,7 @@ import com.google.common.base.Strings;
|
|||||||
import com.google.gerrit.common.data.GlobalCapability;
|
import com.google.gerrit.common.data.GlobalCapability;
|
||||||
import com.google.gerrit.common.errors.EmailException;
|
import com.google.gerrit.common.errors.EmailException;
|
||||||
import com.google.gerrit.extensions.annotations.RequiresCapability;
|
import com.google.gerrit.extensions.annotations.RequiresCapability;
|
||||||
|
import com.google.gerrit.extensions.restapi.AuthException;
|
||||||
import com.google.gerrit.extensions.restapi.RawInput;
|
import com.google.gerrit.extensions.restapi.RawInput;
|
||||||
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
|
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
|
||||||
import com.google.gerrit.extensions.restapi.RestApiException;
|
import com.google.gerrit.extensions.restapi.RestApiException;
|
||||||
@ -260,7 +261,7 @@ final class SetAccountCommand extends SshCommand {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void deleteSshKey(SshKeyInfo i) throws OrmException {
|
private void deleteSshKey(SshKeyInfo i) throws AuthException, OrmException {
|
||||||
AccountSshKey sshKey = new AccountSshKey(
|
AccountSshKey sshKey = new AccountSshKey(
|
||||||
new AccountSshKey.Id(user.getAccountId(), i.seq), i.sshPublicKey);
|
new AccountSshKey.Id(user.getAccountId(), i.seq), i.sshPublicKey);
|
||||||
deleteSshKey.apply(
|
deleteSshKey.apply(
|
||||||
|
Loading…
Reference in New Issue
Block a user