Added support for passing authentication tokens over ssl.
JSONRPC2 request (other than the authentication message) now require a valid token to be provided.
This commit is contained in:
@ -20,6 +20,7 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.util.Calendar;
|
||||
import java.util.logging.LogManager;
|
||||
|
||||
import net.i2p.I2PAppContext;
|
||||
import net.i2p.i2pcontrol.security.KeyStoreInitializer;
|
||||
@ -59,24 +60,14 @@ public class I2PControlController{
|
||||
stop();
|
||||
else
|
||||
throw new IllegalArgumentException("Usage: PluginController -d $PLUGIN [start|stop]");
|
||||
}
|
||||
|
||||
public static String getTestString(){
|
||||
Calendar cal = Calendar.getInstance();
|
||||
int hour = cal.get(Calendar.HOUR_OF_DAY);
|
||||
int minute = cal.get(Calendar.MINUTE);
|
||||
int second = cal.get(Calendar.SECOND);
|
||||
int ms = cal.get(Calendar.MILLISECOND);
|
||||
return hour+":"+minute+":"+second+":"+ms;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
private static void start(String args[]) {
|
||||
//File pluginDir = new File(args[1]);
|
||||
//if (!pluginDir.exists())
|
||||
// throw new IllegalArgumentException("Plugin directory " + pluginDir.getAbsolutePath() + " does not exist");
|
||||
|
||||
I2PAppContext.getGlobalContext().logManager().setDefaultLimit(Log.STR_DEBUG);
|
||||
|
||||
_server = new Server();
|
||||
try {
|
||||
@ -96,7 +87,7 @@ public class I2PControlController{
|
||||
ServletHttpContext context = (ServletHttpContext) _server.getContext("/");
|
||||
context.addServlet("/", "net.i2p.i2pcontrol.servlets.SettingsServlet");
|
||||
context.addServlet("/jsonrpc", "net.i2p.i2pcontrol.servlets.JSONRPC2Servlet");
|
||||
context.addServlet("/history", "net.i2p.i2pcontrol.servlets.HistoryServlet");
|
||||
context.addServlet("/logs", "net.i2p.i2pcontrol.servlets.LogServlet");
|
||||
_server.start();
|
||||
} catch (IOException e) {
|
||||
_log.error("Unable to add listener " + Settings.getListenIP()+":"+Settings.getListenPort() + " - " + e.getMessage());
|
||||
@ -109,8 +100,6 @@ public class I2PControlController{
|
||||
} catch (Exception e) {
|
||||
_log.error("Unable to start jetty server: " + e.getMessage());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,64 +0,0 @@
|
||||
package net.i2p.i2pcontrol;
|
||||
/*
|
||||
* Copyright 2010 hottuna (dev@robertfoss.se)
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
import java.lang.reflect.*;
|
||||
|
||||
/**
|
||||
* There can be only one - ie. even if the class is loaded in several different classloaders,
|
||||
* there will be only one instance of the object.
|
||||
*/
|
||||
public class I2PControlManager{
|
||||
|
||||
private static StringBuilder _history;
|
||||
public static I2PControlManager instance = null;
|
||||
|
||||
public synchronized static I2PControlManager getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new I2PControlManager();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
private I2PControlManager() {
|
||||
_history = new StringBuilder();
|
||||
}
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see net.i2p.i2pcontrol.SingletonInterface#prependHistory(java.lang.String)
|
||||
*/
|
||||
public void prependHistory(String str){
|
||||
_history.insert(0,str + "<br>\n");
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see net.i2p.i2pcontrol.SingletonInterface#appendHistory(java.lang.String)
|
||||
*/
|
||||
public void appendHistory(String str){
|
||||
_history.append("<br>\n" + str);
|
||||
}
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see net.i2p.i2pcontrol.SingletonInterface#getHistory()
|
||||
*/
|
||||
public String getHistory(){
|
||||
|
||||
return _history.toString();
|
||||
}
|
||||
}
|
@ -1,8 +1,11 @@
|
||||
package net.i2p.i2pcontrol.security;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.text.DateFormat;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
|
||||
|
||||
public class AuthToken {
|
||||
private static final int VALIDITY_TIME = 1; // Measured in days
|
||||
private String id;
|
||||
@ -25,7 +28,13 @@ public class AuthToken {
|
||||
* @return True if AuthToken hasn't expired. False in any other case.
|
||||
*/
|
||||
public boolean isValid(){
|
||||
return Calendar.getInstance().before(expiry);
|
||||
return Calendar.getInstance().getTime().before(expiry);
|
||||
}
|
||||
|
||||
public String getExpiryTime(){
|
||||
SimpleDateFormat sdf = new SimpleDateFormat();
|
||||
sdf.applyPattern("yyyy-MM-dd HH:mm:ss");
|
||||
return sdf.format(expiry);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -4,7 +4,15 @@ public class ExpiredAuthTokenException extends Exception{
|
||||
|
||||
private static final long serialVersionUID = 2279019346592900289L;
|
||||
|
||||
public ExpiredAuthTokenException(String str){
|
||||
private String expiryTime;
|
||||
|
||||
public ExpiredAuthTokenException(String str, String expiryTime){
|
||||
super(str);
|
||||
this.expiryTime = expiryTime;
|
||||
}
|
||||
|
||||
public String getExpirytime(){
|
||||
return expiryTime;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -19,8 +19,11 @@ package net.i2p.i2pcontrol.security;
|
||||
import java.security.KeyStore;
|
||||
import java.security.cert.CertificateEncodingException;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
||||
import javax.net.SocketFactory;
|
||||
import javax.net.ssl.SSLSocket;
|
||||
@ -45,7 +48,8 @@ public class SecurityManager {
|
||||
private final static String SSL_PROVIDER = "SunJSSE";
|
||||
private final static String DEFAULT_AUTH_BCRYPT_SALT = "$2a$11$5aOLx2x/8i4fNaitoCSSWu";
|
||||
private final static String DEFAULT_AUTH_PASSWORD = "$2a$11$5aOLx2x/8i4fNaitoCSSWuut2wEl3Hupuca8DCT.NXzvH9fq1pBU.";
|
||||
private static HashMap<String,AuthToken> authTokens;
|
||||
private final static HashMap<String,AuthToken> authTokens;
|
||||
private final static Timer timer;
|
||||
private static String[] SSL_CIPHER_SUITES;
|
||||
private static KeyStore _ks;
|
||||
private static Log _log;
|
||||
@ -53,12 +57,20 @@ public class SecurityManager {
|
||||
static {
|
||||
_log = I2PAppContext.getGlobalContext().logManager().getLog(SecurityManager.class);
|
||||
authTokens = new HashMap<String,AuthToken>();
|
||||
|
||||
timer = new Timer();
|
||||
// Start running periodic task after 20 minutes, run periodically every 10th minute.
|
||||
timer.scheduleAtFixedRate(new Sweeper(), 1000*60*20, 1000*60*10);
|
||||
|
||||
// Get supported SSL copher suites.
|
||||
SocketFactory SSLF = SSLSocketFactory.getDefault();
|
||||
try{
|
||||
SSL_CIPHER_SUITES = ((SSLSocket)SSLF.createSocket()).getSupportedCipherSuites();
|
||||
SSL_CIPHER_SUITES = ((SSLSocket)SSLF.createSocket()).getSupportedCipherSuites();
|
||||
} catch (Exception e){
|
||||
_log.log(Log.CRIT, "Unable to create SSLSocket used for fetching supported ssl cipher suites.", e);
|
||||
}
|
||||
|
||||
// Initialize keystore (if needed)
|
||||
_ks = KeyStoreInitializer.getKeyStore();
|
||||
}
|
||||
|
||||
@ -82,7 +94,10 @@ public class SecurityManager {
|
||||
return KeyStoreFactory.DEFAULT_KEYSTORE_TYPE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the X509Certificate of the server as a Base64 encoded string.
|
||||
* @return base64 encode of X509Certificate
|
||||
*/
|
||||
public static String getBase64Cert(){
|
||||
X509Certificate caCert = KeyStoreFactory.readCert(_ks,
|
||||
CERT_ALIAS,
|
||||
@ -90,6 +105,11 @@ public class SecurityManager {
|
||||
return getBase64FromCert(caCert);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the X509Certificate as a base64 encoded string.
|
||||
* @param cert
|
||||
* @return base64 encode of X509Certificate
|
||||
*/
|
||||
private static String getBase64FromCert(X509Certificate cert){
|
||||
BASE64Encoder encoder = new BASE64Encoder();
|
||||
try {
|
||||
@ -103,8 +123,9 @@ public class SecurityManager {
|
||||
|
||||
|
||||
/**
|
||||
* Hash input HASH_ITERATIONS times
|
||||
* @return input hashed HASH_ITERATIONS times
|
||||
* Hash pwd with using BCrypt with the default salt.
|
||||
* @param pwd
|
||||
* @return BCrypt hash of salt and input string
|
||||
*/
|
||||
public static String getPasswdHash(String pwd){
|
||||
return BCrypt.hashpw(pwd, ConfigurationManager.getInstance().getConf("auth.salt", DEFAULT_AUTH_BCRYPT_SALT));
|
||||
@ -151,11 +172,36 @@ public class SecurityManager {
|
||||
if (token == null){
|
||||
throw new InvalidAuthTokenException("AuthToken with ID: " + tokenID + " couldn't be found.");
|
||||
} else if (!token.isValid()){
|
||||
System.out.println("token.isValid: " + token.isValid()); // Delete me
|
||||
authTokens.remove(token.getId());
|
||||
throw new ExpiredAuthTokenException("AuthToken with ID: " + tokenID + " has expired.");
|
||||
throw new ExpiredAuthTokenException("AuthToken with ID: " + tokenID + " expired " + token.getExpiryTime(), token.getExpiryTime());
|
||||
} else {
|
||||
return; // Everything is fine. :)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean up old authorization tokens to keep the token store slim and fit.
|
||||
* @author hottuna
|
||||
*
|
||||
*/
|
||||
private static class Sweeper extends TimerTask{
|
||||
@Override
|
||||
public void run(){
|
||||
_log.debug("Starting cleanup job..");
|
||||
ArrayList<String> arr = new ArrayList<String>();
|
||||
for (Map.Entry<String,AuthToken> e : authTokens.entrySet()){
|
||||
AuthToken token = e.getValue();
|
||||
if (!token.isValid()){
|
||||
arr.add(e.getKey());
|
||||
}
|
||||
}
|
||||
for (String s : arr){
|
||||
authTokens.remove(s);
|
||||
}
|
||||
_log.debug("Cleanup job done.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -22,27 +22,16 @@ import java.io.InputStreamReader;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.io.Writer;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletInputStream;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
import net.i2p.I2PAppContext;
|
||||
import net.i2p.i2pcontrol.I2PControlManager;
|
||||
import net.i2p.stat.RateStat;
|
||||
import net.i2p.util.Log;
|
||||
|
||||
import net.i2p.i2pcontrol.security.AuthToken;
|
||||
import net.i2p.i2pcontrol.security.SecurityManager;
|
||||
import net.i2p.i2pcontrol.servlets.jsonrpc2handlers.AuthHandler;
|
||||
import net.i2p.i2pcontrol.servlets.jsonrpc2handlers.EchoHandler;
|
||||
import net.i2p.i2pcontrol.servlets.jsonrpc2handlers.JSONRPC2ExtendedError;
|
||||
import net.i2p.i2pcontrol.servlets.jsonrpc2handlers.StatHandler;
|
||||
|
||||
import com.thetransactioncompany.jsonrpc2.*;
|
||||
@ -58,15 +47,14 @@ public class JSONRPC2Servlet extends HttpServlet{
|
||||
private static final int BUFFER_LENGTH = 2048;
|
||||
private static Dispatcher disp;
|
||||
private static char[] readBuffer;
|
||||
private static I2PControlManager _manager;
|
||||
private static Log _log;
|
||||
|
||||
|
||||
@Override
|
||||
public void init(){
|
||||
_log = I2PAppContext.getGlobalContext().logManager().getLog(JSONRPC2Servlet.class);
|
||||
_log.setMinimumPriority(Log.INFO);
|
||||
readBuffer = new char[BUFFER_LENGTH];
|
||||
_manager = I2PControlManager.getInstance();
|
||||
|
||||
disp = new Dispatcher();
|
||||
disp.register(new EchoHandler());
|
||||
@ -94,12 +82,12 @@ public class JSONRPC2Servlet extends HttpServlet{
|
||||
|
||||
if (msg instanceof JSONRPC2Request) {
|
||||
jsonResp = disp.dispatch((JSONRPC2Request)msg, null);
|
||||
_manager.prependHistory("Request: " + msg);
|
||||
_manager.prependHistory("Response: " + jsonResp);
|
||||
_log.debug("Request: " + msg);
|
||||
_log.debug("Response: " + jsonResp);
|
||||
}
|
||||
else if (msg instanceof JSONRPC2Notification) {
|
||||
disp.dispatch((JSONRPC2Notification)msg, null);
|
||||
_manager.prependHistory("Notification: " + msg);
|
||||
_log.debug("Notification: " + msg);
|
||||
}
|
||||
|
||||
out.println(jsonResp);
|
||||
@ -119,11 +107,4 @@ public class JSONRPC2Servlet extends HttpServlet{
|
||||
}
|
||||
return writer.toString();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package net.i2p.i2pcontrol.servlets;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
@ -9,23 +10,20 @@ import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import net.i2p.I2PAppContext;
|
||||
import net.i2p.i2pcontrol.I2PControlManager;
|
||||
import net.i2p.util.Log;
|
||||
|
||||
public class HistoryServlet extends HttpServlet {
|
||||
public class LogServlet extends HttpServlet {
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = -4018705582081424641L;
|
||||
private static I2PControlManager _manager;
|
||||
private static Log _log;
|
||||
|
||||
|
||||
@Override
|
||||
public void init(){
|
||||
_log = I2PAppContext.getGlobalContext().logManager().getLog(HistoryServlet.class);
|
||||
_manager = I2PControlManager.getInstance();
|
||||
_log = I2PAppContext.getGlobalContext().logManager().getLog(LogServlet.class);
|
||||
}
|
||||
|
||||
protected void doGet(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws ServletException, IOException
|
||||
@ -33,7 +31,17 @@ public class HistoryServlet extends HttpServlet {
|
||||
httpServletResponse.setContentType("text/html");
|
||||
PrintWriter out = httpServletResponse.getWriter();
|
||||
out.println("<html>\n<body>");
|
||||
out.println(_manager.getHistory());
|
||||
out.println("<h2>Logs</h2>");
|
||||
out.println("<h3>Most recent: </h3>");
|
||||
List<String> strs = I2PAppContext.getGlobalContext().logManager().getBuffer().getMostRecentMessages();
|
||||
for (String s : strs){
|
||||
out.println(s + "<br>");
|
||||
}
|
||||
out.println("<br>\r\n<h3>Recent critical: </h3>");
|
||||
strs = I2PAppContext.getGlobalContext().logManager().getBuffer().getMostRecentCriticalMessages();
|
||||
for (String s : strs){
|
||||
out.println(s + "<br>");
|
||||
}
|
||||
out.println("</body>\n</html>");
|
||||
out.close();
|
||||
}
|
@ -9,7 +9,6 @@ import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import net.i2p.I2PAppContext;
|
||||
import net.i2p.i2pcontrol.I2PControlManager;
|
||||
import net.i2p.util.Log;
|
||||
|
||||
public class SettingsServlet extends HttpServlet {
|
||||
@ -18,14 +17,12 @@ public class SettingsServlet extends HttpServlet {
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = -4018705582081424641L;
|
||||
private static I2PControlManager _manager;
|
||||
private static Log _log;
|
||||
|
||||
|
||||
@Override
|
||||
public void init(){
|
||||
_log = I2PAppContext.getGlobalContext().logManager().getLog(SettingsServlet.class);
|
||||
_manager = I2PControlManager.getInstance();
|
||||
}
|
||||
|
||||
protected void doGet(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws ServletException, IOException
|
||||
|
@ -24,7 +24,7 @@ public class AuthHandler implements RequestHandler {
|
||||
// Processes the requests
|
||||
public JSONRPC2Response process(JSONRPC2Request req, MessageContext ctx) {
|
||||
if (req.getMethod().equals("authenticate")) {
|
||||
JSONRPC2Error err = JSONRPC2Helper.validateParams(requiredArgs, req);
|
||||
JSONRPC2Error err = JSONRPC2Helper.validateParams(requiredArgs, req, JSONRPC2Helper.USE_NO_AUTH);
|
||||
if (err != null)
|
||||
return new JSONRPC2Response(err, req.getID());
|
||||
|
||||
@ -39,7 +39,7 @@ public class AuthHandler implements RequestHandler {
|
||||
}
|
||||
|
||||
Map outParams = new HashMap();
|
||||
outParams.put("tokenID", token.getId());
|
||||
outParams.put("token", token.getId());
|
||||
return new JSONRPC2Response(outParams, req.getID());
|
||||
} else {
|
||||
// Method name not supported
|
||||
|
@ -61,16 +61,23 @@ public class JSONRPC2ExtendedError extends JSONRPC2Error {
|
||||
private static final long serialVersionUID = -6574632977222371077L;
|
||||
|
||||
/** Invalid JSON-RPC 2.0, implementation defined error (-32099 .. -32000) */
|
||||
public static final JSONRPC2Error INVALID_PASSWORD = new JSONRPC2ExtendedError(-32001, "Invalid password provided");
|
||||
public static final int CODE_INVALID_PASSWORD = -32001;
|
||||
public static final JSONRPC2Error INVALID_PASSWORD = new JSONRPC2ExtendedError(CODE_INVALID_PASSWORD, "Invalid password provided.");
|
||||
|
||||
/** Invalid JSON-RPC 2.0, implementation defined error (-32099 .. -32000) */
|
||||
public static final JSONRPC2Error INVALID_TOKEN = new JSONRPC2ExtendedError(-32002, "Token doesn't exist");
|
||||
public static final int CODE_NO_TOKEN = -32002;
|
||||
public static final JSONRPC2Error NO_TOKEN = new JSONRPC2ExtendedError(CODE_NO_TOKEN, "No authentication token presented.");
|
||||
|
||||
/** Invalid JSON-RPC 2.0, implementation defined error (-32099 .. -32000) */
|
||||
public static final JSONRPC2Error TOKEN_EXPIRED = new JSONRPC2ExtendedError(-32003, "Provided token was expired, will be removed.");
|
||||
public static final int CODE_INVALID_TOKEN = -32003;
|
||||
public static final JSONRPC2Error INVALID_TOKEN = new JSONRPC2ExtendedError(CODE_INVALID_TOKEN, "Authentication token doesn't exist.");
|
||||
|
||||
/** Invalid JSON-RPC 2.0, implementation defined error (-32099 .. -32000) */
|
||||
public static final int CODE_TOKEN_EXPIRED = -32004;
|
||||
public static final JSONRPC2Error TOKEN_EXPIRED = new JSONRPC2ExtendedError(CODE_TOKEN_EXPIRED, "Provided authentication token was expired, will be removed.");
|
||||
|
||||
/** Code used for invalid JSON-RPC 2.0, implementation defined error. Error describes missing parameter/parameters */
|
||||
public static final int CODE_MISSING_PARAMETER = -32004;
|
||||
public static final int CODE_MISSING_PARAMETER = -32005;
|
||||
|
||||
/**
|
||||
* Creates a new JSON-RPC 2.0 error with the specified code and
|
||||
|
@ -1,29 +1,88 @@
|
||||
package net.i2p.i2pcontrol.servlets.jsonrpc2handlers;
|
||||
|
||||
import net.i2p.i2pcontrol.security.*;
|
||||
import net.i2p.i2pcontrol.security.SecurityManager;
|
||||
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import com.thetransactioncompany.jsonrpc2.JSONRPC2Error;
|
||||
import com.thetransactioncompany.jsonrpc2.JSONRPC2ParamsType;
|
||||
import com.thetransactioncompany.jsonrpc2.JSONRPC2Request;
|
||||
import com.thetransactioncompany.jsonrpc2.JSONRPC2Response;
|
||||
|
||||
public class JSONRPC2Helper {
|
||||
|
||||
public static JSONRPC2Error validateParams(String[] requiredArgs, JSONRPC2Request req){
|
||||
public final static Boolean USE_NO_AUTH = false;
|
||||
public final static Boolean USE_AUTH = true;
|
||||
|
||||
/**
|
||||
* Check incoming request for required arguments, to make sure they are valid.
|
||||
* @param requiredArgs - Array of names of required arguments. If null don't check for any parameters.
|
||||
* @param req - Incoming JSONRPC2 request
|
||||
* @param useAuth - If true, will validate authentication token.
|
||||
* @return - null if no errors were found. Corresponding JSONRPC2Error if error is found.
|
||||
*/
|
||||
public static JSONRPC2Error validateParams(String[] requiredArgs, JSONRPC2Request req, Boolean useAuth){
|
||||
|
||||
// Error on unnamed parameters
|
||||
if (req.getParamsType() != JSONRPC2ParamsType.OBJECT){
|
||||
return JSONRPC2Error.INVALID_PARAMS;
|
||||
}
|
||||
HashMap params = (HashMap) req.getParams();
|
||||
String missingArgs = "";
|
||||
for (int i = 0; i < requiredArgs.length; i++){
|
||||
if (!params.containsKey(requiredArgs[i])){
|
||||
missingArgs = missingArgs.concat(requiredArgs[i] + ",");
|
||||
|
||||
// Validate authentication token.
|
||||
if (useAuth){
|
||||
JSONRPC2Error err = validateToken(params);
|
||||
if (err != null){
|
||||
return err;
|
||||
}
|
||||
}
|
||||
if (missingArgs.length() > 0){
|
||||
missingArgs = missingArgs.substring(0, missingArgs.length()-1);
|
||||
return new JSONRPC2ExtendedError(JSONRPC2ExtendedError.CODE_MISSING_PARAMETER, "Missing parameter(s): " + missingArgs);
|
||||
|
||||
// If there exist any required arguments
|
||||
if (requiredArgs != null && requiredArgs.length > 0){
|
||||
String missingArgs = "";
|
||||
for (int i = 0; i < requiredArgs.length; i++){
|
||||
if (!params.containsKey(requiredArgs[i])){
|
||||
missingArgs = missingArgs.concat(requiredArgs[i] + ",");
|
||||
}
|
||||
}
|
||||
if (missingArgs.length() > 0){
|
||||
missingArgs = missingArgs.substring(0, missingArgs.length()-1);
|
||||
return new JSONRPC2ExtendedError(JSONRPC2ExtendedError.CODE_MISSING_PARAMETER, "Missing parameter(s): " + missingArgs);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check incoming request for required arguments, to make sure they are valid. Will authenticate req.
|
||||
* @param requiredArgs - Array of names of required arguments. If null don't check for any parameters.
|
||||
* @param req - Incoming JSONRPC2 request
|
||||
* @return - null if no errors were found. Corresponding JSONRPC2Error if error is found.
|
||||
*/
|
||||
public static JSONRPC2Error validateParams(String[] requiredArgs, JSONRPC2Request req){
|
||||
return validateParams(requiredArgs, req, JSONRPC2Helper.USE_AUTH);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Will check incoming parameters to make sure they contain a valid token.
|
||||
* @param req - Parameters of incoming request
|
||||
* @return null if everything is fine, JSONRPC2Error for any corresponding error.
|
||||
*/
|
||||
private static JSONRPC2Error validateToken(HashMap params){
|
||||
String tokenID = (String) params.get("token");
|
||||
if (tokenID == null){
|
||||
return JSONRPC2ExtendedError.NO_TOKEN;
|
||||
}
|
||||
try {
|
||||
SecurityManager.verifyToken(tokenID);
|
||||
} catch (InvalidAuthTokenException e){
|
||||
return JSONRPC2ExtendedError.INVALID_TOKEN;
|
||||
} catch (ExpiredAuthTokenException e){
|
||||
JSONRPC2Error err = new JSONRPC2ExtendedError(JSONRPC2ExtendedError.CODE_TOKEN_EXPIRED,
|
||||
"Provided authentication token expired "+e.getExpirytime()+", will be removed.");
|
||||
return err;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
Reference in New Issue
Block a user