Squashed History

This commit is contained in:
Moxie Marlinspike
2013-12-08 23:11:09 -08:00
commit 4ad0dad3d9
103 changed files with 9737 additions and 0 deletions

View File

@@ -0,0 +1,68 @@
/**
* Copyright (C) 2013 Open WhisperSystems
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.whispersystems.textsecuregcm.auth;
import com.google.common.base.Optional;
import com.yammer.dropwizard.auth.AuthenticationException;
import com.yammer.dropwizard.auth.Authenticator;
import com.yammer.dropwizard.auth.basic.BasicCredentials;
import com.yammer.metrics.Metrics;
import com.yammer.metrics.core.Meter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.whispersystems.textsecuregcm.storage.Account;
import org.whispersystems.textsecuregcm.storage.AccountsManager;
import java.util.concurrent.TimeUnit;
public class AccountAuthenticator implements Authenticator<BasicCredentials, Account> {
private final Meter authenticationFailedMeter = Metrics.newMeter(AccountAuthenticator.class,
"authentication", "failed",
TimeUnit.MINUTES);
private final Meter authenticationSucceededMeter = Metrics.newMeter(AccountAuthenticator.class,
"authentication", "succeeded",
TimeUnit.MINUTES);
private final Logger logger = LoggerFactory.getLogger(AccountAuthenticator.class);
private final AccountsManager accountsManager;
public AccountAuthenticator(AccountsManager accountsManager) {
this.accountsManager = accountsManager;
}
@Override
public Optional<Account> authenticate(BasicCredentials basicCredentials)
throws AuthenticationException
{
Optional<Account> account = accountsManager.get(basicCredentials.getUsername());
if (!account.isPresent()) {
return Optional.absent();
}
if (account.get().getAuthenticationCredentials().verify(basicCredentials.getPassword())) {
authenticationSucceededMeter.mark();
return account;
}
authenticationFailedMeter.mark();
return Optional.absent();
}
}

View File

@@ -0,0 +1,76 @@
/**
* Copyright (C) 2013 Open WhisperSystems
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.whispersystems.textsecuregcm.auth;
import org.apache.commons.codec.binary.Hex;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
public class AuthenticationCredentials {
private final Logger logger = LoggerFactory.getLogger(AuthenticationCredentials.class);
private final String hashedAuthenticationToken;
private final String salt;
public AuthenticationCredentials(String hashedAuthenticationToken, String salt) {
this.hashedAuthenticationToken = hashedAuthenticationToken;
this.salt = salt;
}
public AuthenticationCredentials(String authenticationToken) {
try {
this.salt = Math.abs(SecureRandom.getInstance("SHA1PRNG").nextInt()) + "";
this.hashedAuthenticationToken = getHashedValue(salt, authenticationToken);
} catch (NoSuchAlgorithmException e) {
throw new AssertionError(e);
}
}
public String getHashedAuthenticationToken() {
return hashedAuthenticationToken;
}
public String getSalt() {
return salt;
}
public boolean verify(String authenticationToken) {
String theirValue = getHashedValue(salt, authenticationToken);
logger.debug("Comparing: " + theirValue + " , " + this.hashedAuthenticationToken);
return theirValue.equals(this.hashedAuthenticationToken);
}
private static String getHashedValue(String salt, String token) {
Logger logger = LoggerFactory.getLogger(AuthenticationCredentials.class);
logger.debug("Getting hashed token: " + salt + " , " + token);
try {
return new String(Hex.encodeHex(MessageDigest.getInstance("SHA1").digest((salt + token).getBytes("UTF-8"))));
} catch (NoSuchAlgorithmException | UnsupportedEncodingException e) {
throw new AssertionError(e);
}
}
}

View File

@@ -0,0 +1,73 @@
/**
* Copyright (C) 2013 Open WhisperSystems
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.whispersystems.textsecuregcm.auth;
import org.whispersystems.textsecuregcm.util.Base64;
import org.whispersystems.textsecuregcm.util.Util;
import java.io.IOException;
public class AuthorizationHeader {
private final String user;
private final String password;
public AuthorizationHeader(String header) throws InvalidAuthorizationHeaderException {
try {
if (header == null) {
throw new InvalidAuthorizationHeaderException("Null header");
}
String[] headerParts = header.split(" ");
if (headerParts == null || headerParts.length < 2) {
throw new InvalidAuthorizationHeaderException("Invalid authorization header: " + header);
}
if (!"Basic".equals(headerParts[0])) {
throw new InvalidAuthorizationHeaderException("Unsupported authorization method: " + headerParts[0]);
}
String concatenatedValues = new String(Base64.decode(headerParts[1]));
if (Util.isEmpty(concatenatedValues)) {
throw new InvalidAuthorizationHeaderException("Bad decoded value: " + concatenatedValues);
}
String[] credentialParts = concatenatedValues.split(":");
if (credentialParts == null || credentialParts.length < 2) {
throw new InvalidAuthorizationHeaderException("Badly formated credentials: " + concatenatedValues);
}
this.user = credentialParts[0];
this.password = credentialParts[1];
} catch (IOException ioe) {
throw new InvalidAuthorizationHeaderException(ioe);
}
}
public String getUserName() {
return user;
}
public String getPassword() {
return password;
}
}

View File

@@ -0,0 +1,74 @@
/**
* Copyright (C) 2013 Open WhisperSystems
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.whispersystems.textsecuregcm.auth;
import com.google.common.base.Optional;
import com.yammer.dropwizard.auth.AuthenticationException;
import com.yammer.dropwizard.auth.Authenticator;
import com.yammer.dropwizard.auth.basic.BasicCredentials;
import com.yammer.metrics.Metrics;
import com.yammer.metrics.core.Meter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.whispersystems.textsecuregcm.configuration.FederationConfiguration;
import org.whispersystems.textsecuregcm.federation.FederatedPeer;
import java.util.List;
import java.util.concurrent.TimeUnit;
public class FederatedPeerAuthenticator implements Authenticator<BasicCredentials, FederatedPeer> {
private final Meter authenticationFailedMeter = Metrics.newMeter(FederatedPeerAuthenticator.class,
"authentication", "failed",
TimeUnit.MINUTES);
private final Meter authenticationSucceededMeter = Metrics.newMeter(FederatedPeerAuthenticator.class,
"authentication", "succeeded",
TimeUnit.MINUTES);
private final Logger logger = LoggerFactory.getLogger(FederatedPeerAuthenticator.class);
private final List<FederatedPeer> peers;
public FederatedPeerAuthenticator(FederationConfiguration config) {
this.peers = config.getPeers();
}
@Override
public Optional<FederatedPeer> authenticate(BasicCredentials basicCredentials)
throws AuthenticationException
{
if (peers == null) {
authenticationFailedMeter.mark();
return Optional.absent();
}
for (FederatedPeer peer : peers) {
if (basicCredentials.getUsername().equals(peer.getName()) &&
basicCredentials.getPassword().equals(peer.getAuthenticationToken()))
{
authenticationSucceededMeter.mark();
return Optional.of(peer);
}
}
authenticationFailedMeter.mark();
return Optional.absent();
}
}

View File

@@ -0,0 +1,28 @@
/**
* Copyright (C) 2013 Open WhisperSystems
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.whispersystems.textsecuregcm.auth;
public class InvalidAuthorizationHeaderException extends Exception {
public InvalidAuthorizationHeaderException(String s) {
super(s);
}
public InvalidAuthorizationHeaderException(Exception e) {
super(e);
}
}

View File

@@ -0,0 +1,69 @@
/**
* Copyright (C) 2013 Open WhisperSystems
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.whispersystems.textsecuregcm.auth;
import com.sun.jersey.api.model.Parameter;
import com.sun.jersey.core.spi.component.ComponentContext;
import com.sun.jersey.core.spi.component.ComponentScope;
import com.sun.jersey.spi.inject.Injectable;
import com.sun.jersey.spi.inject.InjectableProvider;
import com.yammer.dropwizard.auth.Auth;
import com.yammer.dropwizard.auth.Authenticator;
import com.yammer.dropwizard.auth.basic.BasicAuthProvider;
import com.yammer.dropwizard.auth.basic.BasicCredentials;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class MultiBasicAuthProvider<T1,T2> implements InjectableProvider<Auth, Parameter> {
private final Logger logger = LoggerFactory.getLogger(MultiBasicAuthProvider.class);
private final BasicAuthProvider<T1> provider1;
private final BasicAuthProvider<T2> provider2;
private final Class<?> clazz1;
private final Class<?> clazz2;
public MultiBasicAuthProvider(Authenticator<BasicCredentials, T1> authenticator1,
Class<?> clazz1,
Authenticator<BasicCredentials, T2> authenticator2,
Class<?> clazz2,
String realm)
{
this.provider1 = new BasicAuthProvider<T1>(authenticator1, realm);
this.provider2 = new BasicAuthProvider<T2>(authenticator2, realm);
this.clazz1 = clazz1;
this.clazz2 = clazz2;
}
@Override
public ComponentScope getScope() {
return ComponentScope.PerRequest;
}
@Override
public Injectable<?> getInjectable(ComponentContext componentContext,
Auth auth, Parameter parameter)
{
if (parameter.getParameterClass().equals(clazz1)) {
return this.provider1.getInjectable(componentContext, auth, parameter);
} else {
return this.provider2.getInjectable(componentContext, auth, parameter);
}
}
}