HttpSslHandlerProxyR66.java
/*
* This file is part of Waarp Project (named also Waarp or GG).
*
* Copyright (c) 2019, Waarp SAS, and individual contributors by the @author
* tags. See the COPYRIGHT.txt in the distribution for a full listing of
* individual contributors.
*
* All Waarp Project 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 3 of the License, or (at your
* option) any later version.
*
* Waarp 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
* Waarp . If not, see <http://www.gnu.org/licenses/>.
*/
package org.waarp.openr66.proxy.protocol.http.adminssl;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.HttpMethod;
import io.netty.handler.codec.http.QueryStringDecoder;
import io.netty.handler.codec.http.cookie.DefaultCookie;
import io.netty.handler.traffic.TrafficCounter;
import org.waarp.common.exception.FileTransferException;
import org.waarp.common.logging.WaarpLogLevel;
import org.waarp.common.logging.WaarpLogger;
import org.waarp.common.logging.WaarpLoggerFactory;
import org.waarp.common.utility.ParametersChecker;
import org.waarp.common.utility.Version;
import org.waarp.common.utility.WaarpShutdownHook;
import org.waarp.common.utility.WaarpStringUtils;
import org.waarp.gateway.kernel.http.HttpWriteCacheEnable;
import org.waarp.openr66.context.R66Session;
import org.waarp.openr66.protocol.configuration.Messages;
import org.waarp.openr66.protocol.http.adminssl.HttpSslHandler;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import static org.waarp.openr66.protocol.configuration.Configuration.*;
/**
*
*/
public class HttpSslHandlerProxyR66 extends HttpSslHandler {
private static final String XXXLEVEL4XXX2 = "XXXLEVEL4XXX";
private static final String XXXLEVEL3XXX2 = "XXXLEVEL3XXX";
private static final String XXXLEVEL2XXX2 = "XXXLEVEL2XXX";
private static final String XXXLEVEL1XXX2 = "XXXLEVEL1XXX";
private static final String CHECKED2 = "checked";
/**
* Internal Logger
*/
private static final WaarpLogger logger =
WaarpLoggerFactory.getLogger(HttpSslHandlerProxyR66.class);
private enum REQUEST {
Logon("Logon.html"), index("index.html"), error("error.html"),
System("System.html");
private final String header;
/**
* Constructor for a unique file
*
* @param uniquefile
*/
REQUEST(final String uniquefile) {
header = uniquefile;
}
/**
* Reader for a unique file
*
* @return the content of the unique file
*/
public final String readFileUnique(final HttpSslHandlerProxyR66 handler) {
return handler.readFileHeaderInternal(
configuration.getHttpBasePath() + header);
}
}
private String readFileHeaderInternal(final String filename) {
final String value;
try {
value = WaarpStringUtils.readFileException(filename);
} catch (final FileTransferException e) {
logger.error("Error while trying to read: " + filename, e);
return "";
}
final StringBuilder builder = new StringBuilder(value);
WaarpStringUtils.replace(builder, REPLACEMENT.XXXLOCALXXX.toString(),
configuration.getLocalTransaction()
.getNumberLocalChannel() + " " +
Thread.activeCount());
WaarpStringUtils.replace(builder, REPLACEMENT.XXXNETWORKXXX.toString(),
Integer.toString(
configuration.getLocalTransaction()
.getNumberLocalChannel()));
WaarpStringUtils.replace(builder, REPLACEMENT.XXXHOSTIDXXX.toString(),
configuration.getHostId());
if (authentHttp.isAuthenticated()) {
WaarpStringUtils.replace(builder, REPLACEMENT.XXXADMINXXX.toString(),
Messages.getString(
"HttpSslHandler.1")); //$NON-NLS-1$
} else {
WaarpStringUtils.replace(builder, REPLACEMENT.XXXADMINXXX.toString(),
Messages.getString(
"HttpSslHandler.0")); //$NON-NLS-1$
}
final TrafficCounter trafficCounter =
configuration.getGlobalTrafficShapingHandler().trafficCounter();
WaarpStringUtils.replace(builder, REPLACEMENT.XXXBANDWIDTHXXX.toString(),
Messages.getString("HttpSslHandler.IN") +
(trafficCounter.lastReadThroughput() >> 20) +
//$NON-NLS-1$
Messages.getString("HttpSslHandler.MOPS") +
//$NON-NLS-1$
Messages.getString("HttpSslHandler.OUT") +
//$NON-NLS-1$
(trafficCounter.lastWriteThroughput() >> 20) +
Messages.getString(
"HttpSslHandler.MOPS")); //$NON-NLS-1$
WaarpStringUtils.replace(builder, REPLACEMENT.XXXLANGXXX.toString(), lang);
return builder.toString();
}
private String indexProxy() {
final String index = REQUEST.index.readFileUnique(this);
final StringBuilder builder = new StringBuilder(index);
WaarpStringUtils.replaceAll(builder, REPLACEMENT.XXXHOSTIDXXX.toString(),
configuration.getHostId());
WaarpStringUtils.replaceAll(builder, REPLACEMENT.XXXADMINXXX.toString(),
"Administrator Connected");
WaarpStringUtils.replace(builder, REPLACEMENT.XXXVERSIONXXX.toString(),
Version.fullIdentifier());
return builder.toString();
}
/**
* @param builder
*/
private void replaceStringSystem(final StringBuilder builder) {
WaarpStringUtils.replace(builder,
REPLACEMENT.XXXXSESSIONLIMITWXXX.toString(),
Long.toString(
configuration.getServerChannelWriteLimit()));
WaarpStringUtils.replace(builder,
REPLACEMENT.XXXXSESSIONLIMITRXXX.toString(),
Long.toString(
configuration.getServerChannelReadLimit()));
WaarpStringUtils.replace(builder, REPLACEMENT.XXXXDELAYCOMMDXXX.toString(),
Long.toString(configuration.getDelayCommander()));
WaarpStringUtils.replace(builder, REPLACEMENT.XXXXDELAYRETRYXXX.toString(),
Long.toString(configuration.getDelayRetry()));
WaarpStringUtils.replace(builder,
REPLACEMENT.XXXXCHANNELLIMITWXXX.toString(),
Long.toString(
configuration.getServerGlobalWriteLimit()));
WaarpStringUtils.replace(builder,
REPLACEMENT.XXXXCHANNELLIMITRXXX.toString(),
Long.toString(
configuration.getServerGlobalReadLimit()));
WaarpStringUtils.replace(builder, "XXXBLOCKXXX",
configuration.isShutdown()? CHECKED2 : "");
switch (WaarpLoggerFactory.getLogLevel()) {
case DEBUG:
WaarpStringUtils.replace(builder, XXXLEVEL1XXX2, CHECKED2);
WaarpStringUtils.replace(builder, XXXLEVEL2XXX2, "");
WaarpStringUtils.replace(builder, XXXLEVEL3XXX2, "");
WaarpStringUtils.replace(builder, XXXLEVEL4XXX2, "");
break;
case INFO:
WaarpStringUtils.replace(builder, XXXLEVEL1XXX2, "");
WaarpStringUtils.replace(builder, XXXLEVEL2XXX2, CHECKED2);
WaarpStringUtils.replace(builder, XXXLEVEL3XXX2, "");
WaarpStringUtils.replace(builder, XXXLEVEL4XXX2, "");
break;
case WARN:
WaarpStringUtils.replace(builder, XXXLEVEL1XXX2, "");
WaarpStringUtils.replace(builder, XXXLEVEL2XXX2, "");
WaarpStringUtils.replace(builder, XXXLEVEL3XXX2, CHECKED2);
WaarpStringUtils.replace(builder, XXXLEVEL4XXX2, "");
break;
case ERROR:
WaarpStringUtils.replace(builder, XXXLEVEL1XXX2, "");
WaarpStringUtils.replace(builder, XXXLEVEL2XXX2, "");
WaarpStringUtils.replace(builder, XXXLEVEL3XXX2, "");
WaarpStringUtils.replace(builder, XXXLEVEL4XXX2, CHECKED2);
break;
default:
WaarpStringUtils.replace(builder, XXXLEVEL1XXX2, "");
WaarpStringUtils.replace(builder, XXXLEVEL2XXX2, "");
WaarpStringUtils.replace(builder, XXXLEVEL3XXX2, "");
WaarpStringUtils.replace(builder, XXXLEVEL4XXX2, "");
break;
}
}
private String System() {
getParamsProxy();
if (params == null) {
final String system = REQUEST.System.readFileUnique(this);
final StringBuilder builder = new StringBuilder(system);
replaceStringSystem(builder);
langHandle(builder);
return builder.toString();
}
String extraInformation = null;
if (params.containsKey("ACTION")) {
final List<String> action = params.get("ACTION");
for (final String act : action) {
if ("Language".equalsIgnoreCase(act)) {
lang = getTrimValue("change");
final String sys = getTrimValue("changesys");
Messages.init(new Locale(sys));
extraInformation =
Messages.getString("HttpSslHandler.LangIs") + "Web: " + lang +
" OpenR66: " //$NON-NLS-1$
+ Messages.getSlocale();
} else if ("Level".equalsIgnoreCase(act)) {
final String loglevel = getTrimValue("loglevel");
WaarpLogLevel level = WaarpLogLevel.WARN;
if ("debug".equalsIgnoreCase(loglevel)) {
level = WaarpLogLevel.DEBUG;
} else if ("info".equalsIgnoreCase(loglevel)) {
level = WaarpLogLevel.INFO;
} else if ("warn".equalsIgnoreCase(loglevel)) {
level = WaarpLogLevel.WARN;
} else if ("error".equalsIgnoreCase(loglevel)) {
level = WaarpLogLevel.ERROR;
}
WaarpLoggerFactory.setLogLevel(level);
extraInformation = Messages.getString("HttpSslHandler.LangIs") +
level.name(); //$NON-NLS-1$
} else if ("Disconnect".equalsIgnoreCase(act)) {
String logon = logon();
logon = logon.replaceAll(REPLACEMENT.XXXERRORMESGXXX.toString(),
Messages.getString(
"HttpSslHandler.DisActive"));
newSession = true;
clearSession();
forceClose = true;
return logon;
} else if ("Shutdown".equalsIgnoreCase(act)) {
final String error;
if (configuration.getShutdownConfiguration().serviceFuture != null) {
error =
error(Messages.getString("HttpSslHandler.38")); //$NON-NLS-1$
} else {
error =
error(Messages.getString("HttpSslHandler.37")); //$NON-NLS-1$
}
WaarpShutdownHook.setRestart(false);
newSession = true;
clearSession();
forceClose = true;
shutdown = true;
return error;
} else if ("Restart".equalsIgnoreCase(act)) {
String error;
if (configuration.getShutdownConfiguration().serviceFuture != null) {
error =
error(Messages.getString("HttpSslHandler.38")); //$NON-NLS-1$
} else {
error = error(Messages.getString("HttpSslHandler.39")
//$NON-NLS-1$
+ configuration.getTimeoutCon() * 2 / 1000 +
Messages.getString(
"HttpSslHandler.40")); //$NON-NLS-1$
}
error = error.replace("XXXRELOADHTTPXXX",
"HTTP-EQUIV=\"refresh\" CONTENT=\"" +
configuration.getTimeoutCon() * 2 / 1000 + '"');
WaarpShutdownHook.setRestart(true);
newSession = true;
clearSession();
forceClose = true;
shutdown = true;
return error;
} else if ("Validate".equalsIgnoreCase(act)) {
final String bsessionr = getTrimValue("BSESSR");
long lsessionr = configuration.getServerChannelReadLimit();
long lglobalr;
long lsessionw;
long lglobalw;
try {
if (bsessionr != null) {
lsessionr = (Long.parseLong(bsessionr) / 10) * 10;
}
final String bglobalr = getTrimValue("BGLOBR");
lglobalr = configuration.getServerGlobalReadLimit();
if (bglobalr != null) {
lglobalr = (Long.parseLong(bglobalr) / 10) * 10;
}
final String bsessionw = getTrimValue("BSESSW");
lsessionw = configuration.getServerChannelWriteLimit();
if (bsessionw != null) {
lsessionw = (Long.parseLong(bsessionw) / 10) * 10;
}
final String bglobalw = getTrimValue("BGLOBW");
lglobalw = configuration.getServerGlobalWriteLimit();
if (bglobalw != null) {
lglobalw = (Long.parseLong(bglobalw) / 10) * 10;
}
configuration.changeNetworkLimit(lglobalw, lglobalr, lsessionw,
lsessionr,
configuration.getDelayLimit());
final String dcomm = getTrimValue("DCOM");
if (dcomm != null) {
configuration.setDelayCommander(Long.parseLong(dcomm));
if (configuration.getDelayCommander() <= 100) {
configuration.setDelayCommander(100);
}
configuration.reloadCommanderDelay();
}
final String dret = getTrimValue("DRET");
if (dret != null) {
configuration.setDelayRetry(Long.parseLong(dret));
if (configuration.getDelayRetry() <= 1000) {
configuration.setDelayRetry(1000);
}
}
extraInformation =
Messages.getString("HttpSslHandler.41"); //$NON-NLS-1$
} catch (final NumberFormatException e) {
extraInformation =
Messages.getString("HttpSslHandler.42"); //$NON-NLS-1$
}
}
}
}
final String system = REQUEST.System.readFileUnique(this);
final StringBuilder builder = new StringBuilder(system);
replaceStringSystem(builder);
langHandle(builder);
if (extraInformation != null) {
builder.append(extraInformation);
}
return builder.toString();
}
private void getParamsProxy() {
if (request.method() == HttpMethod.GET) {
params = null;
} else if (request.method() == HttpMethod.POST) {
final ByteBuf content = request.content();
if (content.isReadable()) {
final String param = content.toString(WaarpStringUtils.UTF8);
final QueryStringDecoder queryStringDecoder2 =
new QueryStringDecoder("/?" + param);
params = queryStringDecoder2.parameters();
} else {
params = null;
}
}
}
@Override
protected final void clearSession() {
if (admin != null) {
final R66Session lsession = sessions.remove(admin.value());
admin = null;
if (lsession != null) {
lsession.setStatus(75);
lsession.clear();
}
}
}
private void checkAuthentProxy(final ChannelHandlerContext ctx) {
newSession = true;
if (request.method() == HttpMethod.GET) {
String logon = logon();
logon = logon.replaceAll(REPLACEMENT.XXXERRORMESGXXX.toString(), "");
responseContent.append(logon);
clearSession();
writeResponse(ctx);
return;
} else if (request.method() == HttpMethod.POST) {
getParamsProxy();
if (params == null) {
String logon = logon();
logon = logon.replaceAll(REPLACEMENT.XXXERRORMESGXXX.toString(),
Messages.getString(
"HttpSslHandler.EmptyLogin"));
responseContent.append(logon);
clearSession();
writeResponse(ctx);
return;
}
}
boolean getMenu = false;
if (params != null && params.containsKey("Logon")) {
String name = null;
String password = null;
List<String> values;
if (!params.isEmpty()) {
// get values
if (params.containsKey("name")) {
values = params.get("name");
if (values != null) {
name = values.get(0);
if (ParametersChecker.isEmpty(name)) {
getMenu = true;
}
}
} else {
getMenu = true;
}
// search the nb param
if (!getMenu && params.containsKey("passwd")) {
values = params.get("passwd");
if (values != null) {
password = values.get(0);
getMenu = ParametersChecker.isEmpty(password);
} else {
getMenu = true;
}
} else {
getMenu = true;
}
} else {
getMenu = true;
}
if (!getMenu && name != null) {
if (logger.isDebugEnabled()) {
logger.debug("Name={} vs {} Passwd vs ", name,
name.equals(configuration.getAdminName()),
Arrays.equals(password.getBytes(WaarpStringUtils.UTF8),
configuration.getServerAdminKey()));
}
if (name.equals(configuration.getAdminName()) &&
Arrays.equals(password.getBytes(WaarpStringUtils.UTF8),
configuration.getServerAdminKey())) {
authentHttp.getAuth()
.specialNoSessionAuth(true, configuration.getHostId());
authentHttp.setStatus(70);
} else {
getMenu = true;
}
if (!authentHttp.isAuthenticated()) {
authentHttp.setStatus(71);
logger.info("Still not authenticated: {}", authentHttp);
getMenu = true;
}
}
} else {
getMenu = true;
}
if (getMenu) {
String logon = logon();
logon = logon.replaceAll(REPLACEMENT.XXXERRORMESGXXX.toString(),
Messages.getString("HttpSslHandler.BadLogin"));
responseContent.append(logon);
clearSession();
} else {
final String index = indexProxy();
responseContent.append(index);
clearSession();
admin = new DefaultCookie(R66SESSION + configuration.getHostId(),
configuration.getHostId() +
Long.toHexString(RANDOM.nextLong()));
sessions.put(admin.value(), authentHttp);
authentHttp.setStatus(72);
logger.debug("CreateSession: {}:{}", uriRequest, admin);
}
writeResponse(ctx);
}
@Override
protected void channelRead0(final ChannelHandlerContext ctx,
final FullHttpRequest msg) {
final FullHttpRequest request = this.request = msg;
final QueryStringDecoder queryStringDecoder =
new QueryStringDecoder(request.uri());
uriRequest = queryStringDecoder.path();
logger.debug("Msg: {}", uriRequest);
if (uriRequest.contains("gre/") || uriRequest.contains("img/") ||
uriRequest.contains("res/") || uriRequest.contains("favicon.ico")) {
HttpWriteCacheEnable.writeFile(request, ctx,
configuration.getHttpBasePath() +
uriRequest,
R66SESSION + configuration.getHostId());
ctx.flush();
return;
}
checkSession(ctx.channel());
try {
if (!authentHttp.isAuthenticated()) {
logger.debug("Not Authent: {}:{}", uriRequest, authentHttp);
checkAuthentProxy(ctx);
return;
}
String find = uriRequest;
if (uriRequest.charAt(0) == '/') {
find = uriRequest.substring(1);
}
REQUEST req = REQUEST.index;
if (find.length() != 0) {
find = find.substring(0, find.indexOf('.'));
try {
req = REQUEST.valueOf(find);
} catch (final IllegalArgumentException e1) {
req = REQUEST.index;
logger.info("NotFound: {}:{}", find, uriRequest);
}
}
if (req == REQUEST.System) {
responseContent.append(System());
} else {
responseContent.append(indexProxy());
}
writeResponse(ctx);
} finally {
closeConnection();
}
}
}