/*
* Password Management Servlets (PWM)
* http://www.pwm-project.org
*
* Copyright (c) 2006-2009 Novell, Inc.
* Copyright (c) 2009-2017 The PWM Project
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package password.pwm.util;
import password.pwm.AppProperty;
import password.pwm.PwmApplication;
import password.pwm.PwmConstants;
import password.pwm.error.PwmUnrecoverableException;
import password.pwm.http.HttpHeader;
import password.pwm.http.PwmRequest;
import password.pwm.util.java.StringUtil;
import password.pwm.util.logging.PwmLogger;
import java.io.Serializable;
/**
* Simple data object containing username/password info derived from a "Basic" Authorization HTTP Header.
*
* @author Jason D. Rivard
*/
public class BasicAuthInfo implements Serializable {
private static final PwmLogger LOGGER = PwmLogger.forClass(BasicAuthInfo.class);
private final String username;
private final PasswordData password;
/**
* Extracts the basic auth info from the header
*
* @param pwmRequest http servlet request
* @return a BasicAuthInfo object containing username/password, or null if the "Authorization" header doesn't exist or is malformed
*/
public static BasicAuthInfo parseAuthHeader(
final PwmApplication pwmApplication,
final PwmRequest pwmRequest
) {
final String authHeader = pwmRequest.readHeaderValueAsString(HttpHeader.Authorization);
if (authHeader != null) {
if (authHeader.contains(PwmConstants.HTTP_BASIC_AUTH_PREFIX)) {
// ***** Get the encoded username/chpass string
// Strip off "Basic " from "Basic c2pvaG5zLmNzaTo=bm92ZWxs"
final String toStrip = PwmConstants.HTTP_BASIC_AUTH_PREFIX+" ";
final String encodedValue = authHeader.substring(toStrip.length(), authHeader.length());
try {
// ***** Decode the username/chpass string
final String charSet = pwmApplication.getConfig().readAppProperty(AppProperty.HTTP_BASIC_AUTH_CHARSET);
final String decoded = new String(StringUtil.base64Decode(encodedValue), charSet);
// The decoded string should now look something like:
// "cn=user,o=company:chpass" or "user:chpass"
return parseHeaderString(decoded);
} catch (Exception e) {
LOGGER.debug(pwmRequest, "error decoding auth header");
}
}
}
return null;
}
public static BasicAuthInfo parseHeaderString(final String input) {
try {
// The decoded string should now look something like:
// "cn=user,o=company:chpass" or "user:chpass"
final int index = input.indexOf(":");
if (index != -1) {
// ***** Separate "username:chpass"
final String username = input.substring(0, index);
final PasswordData password = new PasswordData(input.substring(index + 1));
return new BasicAuthInfo(username, password);
} else {
return new BasicAuthInfo(input, null);
}
} catch (Exception e) {
LOGGER.error("error decoding auth header: " + e.getMessage());
throw new IllegalArgumentException("invalid basic authentication input string: " + e.getMessage(), e);
}
}
public String toAuthHeader()
throws PwmUnrecoverableException
{
final StringBuilder sb = new StringBuilder();
sb.append(this.getUsername());
sb.append(":");
sb.append(this.getPassword().getStringValue());
sb.replace(0, sb.length(), StringUtil.base64Encode(sb.toString().getBytes(PwmConstants.DEFAULT_CHARSET)));
sb.insert(0, PwmConstants.HTTP_BASIC_AUTH_PREFIX+" ");
return sb.toString();
}
// --------------------------- CONSTRUCTORS ---------------------------
public BasicAuthInfo(
final String username,
final PasswordData password
) {
this.username = username;
this.password = password;
}
// --------------------- GETTER / SETTER METHODS ---------------------
public PasswordData getPassword() {
return password;
}
public String getUsername() {
return username;
}
// ------------------------ CANONICAL METHODS ------------------------
public boolean equals(final Object o) {
if (this == o) {
return true;
}
if (!(o instanceof BasicAuthInfo)) {
return false;
}
final BasicAuthInfo basicAuthInfo = (BasicAuthInfo) o;
return !(password != null ? !password.equals(basicAuthInfo.password) : basicAuthInfo.password != null) && !(username != null ? !username.equals(basicAuthInfo.username) : basicAuthInfo.username != null);
}
public int hashCode() {
int result;
result = (username != null ? username.hashCode() : 0);
result = 29 * result + (password != null ? password.hashCode() : 0);
return result;
}
}