Add a password field to the account identities
Some types of identities, e.g. "username:", now support having an optional password generated alongside of them. This can be used in the future to authenticate the user. Currently we intend to use this only for authentication over HTTP, so we generate the password for the user as they would need to store it into a local ~/.netrc. We don't want them to reuse an existing password that might be vulnerable. Change-Id: I047a97f00249c81638625d7654087ea71f8f386a Signed-off-by: Shawn O. Pearce <sop@google.com>
This commit is contained in:
@@ -100,6 +100,13 @@ public class ChangeUserName implements Callable<VoidResult> {
|
||||
try {
|
||||
final AccountExternalId id =
|
||||
new AccountExternalId(user.getAccountId(), key);
|
||||
|
||||
for (AccountExternalId i : old) {
|
||||
if (i.getPassword() != null) {
|
||||
id.setPassword(i.getPassword());
|
||||
}
|
||||
}
|
||||
|
||||
db.accountExternalIds().insert(Collections.singleton(id));
|
||||
} catch (OrmDuplicateKeyException dupeErr) {
|
||||
// If we are using this identity, don't report the exception.
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
// Copyright (C) 2010 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.account;
|
||||
|
||||
import com.google.gerrit.common.errors.NoSuchEntityException;
|
||||
import com.google.gerrit.reviewdb.AccountExternalId;
|
||||
import com.google.gerrit.reviewdb.ReviewDb;
|
||||
import com.google.gerrit.server.IdentifiedUser;
|
||||
import com.google.gwtorm.client.OrmException;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.assistedinject.Assisted;
|
||||
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.Collections;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
/** Operation to generate a password for an account. */
|
||||
public class GeneratePassword implements Callable<AccountExternalId> {
|
||||
private static final int LEN = 12;
|
||||
private static final SecureRandom rng;
|
||||
|
||||
static {
|
||||
try {
|
||||
rng = SecureRandom.getInstance("SHA1PRNG");
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new RuntimeException("Cannot create RNG for password generator", e);
|
||||
}
|
||||
}
|
||||
|
||||
public interface Factory {
|
||||
GeneratePassword create(AccountExternalId.Key forUser);
|
||||
}
|
||||
|
||||
private final AccountCache accountCache;
|
||||
private final ReviewDb db;
|
||||
private final IdentifiedUser user;
|
||||
|
||||
private final AccountExternalId.Key forUser;
|
||||
|
||||
@Inject
|
||||
GeneratePassword(final AccountCache accountCache, final ReviewDb db,
|
||||
final IdentifiedUser user,
|
||||
|
||||
@Assisted AccountExternalId.Key forUser) {
|
||||
this.accountCache = accountCache;
|
||||
this.db = db;
|
||||
this.user = user;
|
||||
|
||||
this.forUser = forUser;
|
||||
}
|
||||
|
||||
public AccountExternalId call() throws OrmException, NoSuchEntityException {
|
||||
AccountExternalId id = db.accountExternalIds().get(forUser);
|
||||
if (id == null || !user.getAccountId().equals(id.getAccountId())) {
|
||||
throw new NoSuchEntityException();
|
||||
}
|
||||
|
||||
id.setPassword(generate());
|
||||
db.accountExternalIds().update(Collections.singleton(id));
|
||||
accountCache.evict(user.getAccountId());
|
||||
return id;
|
||||
}
|
||||
|
||||
private String generate() {
|
||||
byte[] rand = new byte[LEN];
|
||||
rng.nextBytes(rand);
|
||||
|
||||
byte[] enc = Base64.encodeBase64(rand, false);
|
||||
StringBuilder r = new StringBuilder(LEN);
|
||||
for (int i = 0; i < LEN; i++) {
|
||||
if (enc[i] == '=') {
|
||||
break;
|
||||
}
|
||||
r.append((char) enc[i]);
|
||||
}
|
||||
return r.toString();
|
||||
}
|
||||
}
|
||||
@@ -32,7 +32,7 @@ import java.util.List;
|
||||
/** A version of the database schema. */
|
||||
public abstract class SchemaVersion {
|
||||
/** The current schema version. */
|
||||
private static final Class<? extends SchemaVersion> C = Schema_23.class;
|
||||
private static final Class<? extends SchemaVersion> C = Schema_24.class;
|
||||
|
||||
public static class Module extends AbstractModule {
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
// Copyright (C) 2010 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.schema;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Provider;
|
||||
|
||||
class Schema_24 extends SchemaVersion {
|
||||
@Inject
|
||||
Schema_24(Provider<Schema_23> prior) {
|
||||
super(prior);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user