- Fixes for Jetty 9
- Convert I2PControlController to RouterApp - Remove all static references - Don't stop all running threads on shutdown - Set restrictive permissions on configuration file - Disable changing host/port/password via RPC - Use I2P lib for setting supported ciphers - Update makeplugin.sh - Change signer and update URLs in plugin.config - Don't include license, readme, and clients.config in the update - Bundle i2pcontrol.py test script - Make constants static and final - Comment out unused methods - Remove tabs in build.xml - Remove unused dependencies in build.xml - Clean up imports
This commit is contained in:
22
build.xml
22
build.xml
@ -4,12 +4,12 @@
|
||||
<target name="all" depends="clean,plugin,release" />
|
||||
|
||||
<target name="local" depends="clean,plugin">
|
||||
<property name="i2p.plugindir" value="${user.home}/.i2p/plugins/I2PControl" />
|
||||
<delete dir="${i2p.plugindir}"/>
|
||||
<mkdir dir="${i2p.plugindir}"/>
|
||||
<mkdir dir="${i2p.plugindir}/lib"/>
|
||||
<property name="i2p.plugindir" value="${user.home}/.i2p/plugins/I2PControl" />
|
||||
<delete dir="${i2p.plugindir}"/>
|
||||
<mkdir dir="${i2p.plugindir}"/>
|
||||
<mkdir dir="${i2p.plugindir}/lib"/>
|
||||
<copy file="src/build/I2PControl.jar" todir="${i2p.plugindir}/lib" overwrite="true" />
|
||||
<copy todir="${i2p.plugindir}" >
|
||||
<copy todir="${i2p.plugindir}" >
|
||||
<fileset dir="plugin" includes="**"/>
|
||||
</copy>
|
||||
</target>
|
||||
@ -24,10 +24,7 @@
|
||||
<property name="release.number" value="0.11" />
|
||||
|
||||
<!-- make the update xpi2p -->
|
||||
<mkdir dir="plugin/lib"/>
|
||||
<copy file="LICENSE.txt" todir="plugin/" overwrite="true" />
|
||||
<copy file="README.txt" todir="plugin/" overwrite="true" />
|
||||
<copy file="scripts/clients.config" todir="plugin/" overwrite="true" />
|
||||
<mkdir dir="plugin/lib"/>
|
||||
<copy file="scripts/plugin.config" todir="plugin/" overwrite="true" />
|
||||
|
||||
<exec executable="pack200" failonerror="true">
|
||||
@ -46,14 +43,17 @@
|
||||
</exec>
|
||||
|
||||
<!-- make the install xpi2p -->
|
||||
<copy file="LICENSE.txt" todir="plugin/" overwrite="true" />
|
||||
<copy file="README.txt" todir="plugin/" overwrite="true" />
|
||||
<copy file="scripts/clients.config" todir="plugin/" overwrite="true" />
|
||||
<copy file="scripts/plugin.config" todir="plugin/" overwrite="true" />
|
||||
<copy file="scripts/i2pcontrol.py" todir="plugin/" overwrite="true" />
|
||||
<exec executable="echo" osfamily="unix" failonerror="true" output="plugin/plugin.config" append="true">
|
||||
<arg value="version=${release.number}-b${build.number}" />
|
||||
</exec>
|
||||
</target>
|
||||
|
||||
<target name="release" depends="plugin">
|
||||
|
||||
<input message="Enter su3 signing key password:" addproperty="release.password.su3" />
|
||||
<fail message="You must enter a password." >
|
||||
<condition>
|
||||
@ -84,7 +84,7 @@
|
||||
<ant dir="src" target="clean" />
|
||||
<delete file="plugin/clients.config" />
|
||||
<delete file="plugin/plugin.config" />
|
||||
<delete file="plugin/console/webapp.config" />
|
||||
<delete file="plugin/console/webapp.config" />
|
||||
<delete file="plugin/lib/I2PControl.jar.pack" />
|
||||
<delete file="plugin/console/webapps/I2PControl.war.pack" />
|
||||
<delete file="plugin/LICENSE.txt" />
|
||||
|
209
scripts/i2pcontrol.py
Executable file
209
scripts/i2pcontrol.py
Executable file
@ -0,0 +1,209 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
#
|
||||
# If it fails "No module named yaml"
|
||||
# then sudo apt install python-yaml
|
||||
#
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import urllib2
|
||||
import httplib
|
||||
import socket
|
||||
import ssl
|
||||
import sys
|
||||
import yaml
|
||||
from urllib2 import HTTPError, URLError
|
||||
from string import whitespace
|
||||
|
||||
# Info about requestable data can be found at https://geti2p.net/i2pcontrol.html & https://geti2p.net/ratestats.html
|
||||
|
||||
address = "127.0.0.1" # Default I2PControl Address
|
||||
port = 7650 # Default I2PControl Port
|
||||
apiPassword = "itoopie" # Default I2PControl password
|
||||
|
||||
|
||||
## Do not edit below
|
||||
apiVersion = 1 # Default API Version
|
||||
msgId = 1
|
||||
token = None
|
||||
|
||||
def checkToken():
|
||||
global token
|
||||
if (token == None):
|
||||
token = getToken()
|
||||
if (token == None):
|
||||
print("Unable to login. Quitting..")
|
||||
sys.exit()
|
||||
|
||||
def getToken():
|
||||
loginStr = "{\"id\":" + str(msgId) + ", \"method\":\"Authenticate\",\"params\":{\"API\":" + str(apiVersion) + ", \"Password\":\"" + apiPassword + "\"}, \"jsonrpc\":\"2.0\"}"
|
||||
|
||||
try:
|
||||
jsonResp = sendMsg(loginStr)
|
||||
return jsonResp.get("result").get("Token")
|
||||
|
||||
except HTTPError, e:
|
||||
print("HTTPError: %s" % e.reason)
|
||||
except URLError, e:
|
||||
print("URLError: %s" % e.reason)
|
||||
|
||||
def getRate(rateName, ratePeriod):
|
||||
checkToken()
|
||||
msgStr = "{\"id\":" + str(msgId) + ", \"method\":\"GetRate\",\"params\":{\"Stat\":\"" + rateName + "\", \"Period\":" + str(ratePeriod) + ", \"Token\":\"" + token +"\" }, \"jsonrpc\":\"2.0\"}"
|
||||
jsonResp = sendMsg(msgStr)
|
||||
return jsonResp.get("result").get("Result")
|
||||
|
||||
def getRouterInfo(infoName):
|
||||
checkToken()
|
||||
## The parameter names in 'params' defines which answers are requested
|
||||
msgStr = "{\"id\":" + str(msgId) + ", \"method\":\"RouterInfo\",\"params\":{\""+infoName+"\":\"\", \"Token\":\"" + token +"\" }, \"jsonrpc\":\"2.0\"}"
|
||||
jsonResp = sendMsg(msgStr)
|
||||
return jsonResp.get("result").get(infoName)
|
||||
|
||||
def sendMsg(jsonStr):
|
||||
global msgId
|
||||
https_handler = UnauthenticatedHTTPSHandler()
|
||||
url_opener = urllib2.build_opener(https_handler)
|
||||
handle = url_opener.open("https://"+address+":"+ str(port) + "/jsonrpc", jsonStr)
|
||||
response = handle.read()
|
||||
handle.close()
|
||||
msgId = msgId + 1;
|
||||
|
||||
jsonResp = json.loads(response)
|
||||
if (jsonResp.has_key("error")):
|
||||
print ("Remote server: I2PControl Error: " + str(jsonResp.get("error").get("code")) + ", " + jsonResp.get("error").get("message"))
|
||||
sys.exit()
|
||||
return jsonResp
|
||||
|
||||
###
|
||||
# Overrides the version in httplib so that we can ignore server certificate authenticity
|
||||
###
|
||||
class UnauthenticatedHTTPSConnection(httplib.HTTPSConnection):
|
||||
def connect(self):
|
||||
#
|
||||
sock = socket.create_connection((self.host, self.port), self.timeout)
|
||||
if self._tunnel_host:
|
||||
self.sock = sock
|
||||
self._tunnel()
|
||||
self.sock = ssl.wrap_socket(sock,
|
||||
cert_reqs=ssl.CERT_NONE)
|
||||
|
||||
###
|
||||
# HTTPS handler which uses SSLv3 and ignores server cert authenticity
|
||||
###
|
||||
class UnauthenticatedHTTPSHandler(urllib2.HTTPSHandler):
|
||||
def __init__(self, connection_class = UnauthenticatedHTTPSConnection):
|
||||
self.specialized_conn_class = connection_class
|
||||
urllib2.HTTPSHandler.__init__(self)
|
||||
def https_open(self, req):
|
||||
return self.do_open(self.specialized_conn_class, req)
|
||||
|
||||
def zabbix_config(fileName, outfile):
|
||||
yamlDict = dict()
|
||||
for line in open(fileName):
|
||||
li=line.strip()
|
||||
if li.startswith("UserParameter"):
|
||||
i2pCtrlOpt = li.strip("UserParameter=").split(",")
|
||||
i2pCtrlOpt[1] = i2pCtrlOpt[1].split()
|
||||
i2pCtrlOpt[1].pop(0) # Remove path of this script (i2pcontrol)
|
||||
i2pCtrlParams = i2pCtrlOpt[1]
|
||||
#print i2pCtrlOpt #Delete me!
|
||||
result = ""
|
||||
if (i2pCtrlParams[0] == "-i" or i2pCtrlParams[0] == "--router-info"):
|
||||
result = getRouterInfo(i2pCtrlParams[1])
|
||||
elif (i2pCtrlParams[0] == "-s" or i2pCtrlParams[0] == "--rate-stat"):
|
||||
result = getRate(i2pCtrlParams[1], i2pCtrlParams[2])
|
||||
else:
|
||||
result = "Bad query syntax."
|
||||
yamlDict[i2pCtrlParams[1]] = result
|
||||
#print yaml.dump(yamlDict)
|
||||
yaml.dump(yamlDict, open(outfile,'w'))
|
||||
|
||||
def from_file(infile, parameter):
|
||||
try:
|
||||
yamlDict = yaml.load(open(infile,'r'))
|
||||
print yamlDict[parameter]
|
||||
except IOError, e:
|
||||
print "File \""+ infile +"\" couldn't be read."
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description='Fetch I2P info via the I2PControl API.')
|
||||
parser.add_argument("-i",
|
||||
"--router-info",
|
||||
nargs=1,
|
||||
metavar="router-info-id",
|
||||
dest="router_info",
|
||||
action="store",
|
||||
help="Request info such as I2P version and uptime. Returned info can be of any type. Full list of options at https://geti2p.net/i2pcontrol.html. Usage: \"-i i2p.router.version\"")
|
||||
|
||||
parser.add_argument("-s",
|
||||
"--rate-stat",
|
||||
nargs=2,
|
||||
metavar=("rateStatName", "period"),
|
||||
dest="rate_stat",
|
||||
action="store",
|
||||
help="Request info such as bandwidth, number active peers, clock skew, etc.. The period is measured in ms and must be longer than 60s. Full list at https://geti2p.net/ratestats.html. Usage: \"-s bw.receiveBps 3600000\"")
|
||||
|
||||
parser.add_argument("-z",
|
||||
"--zabbix",
|
||||
nargs=2,
|
||||
metavar=("\"path to zabbix_agent.conf\"", "\"path to output file\""),
|
||||
dest="zabbix",
|
||||
action="store",
|
||||
help="Parse options to request, by reading a zabbix config file for \"UserParameter\"s relating to I2P. Usage: \"-z /etc/zabbix/zabbix_agent.conf\"")
|
||||
|
||||
parser.add_argument("-f",
|
||||
"--from-file",
|
||||
nargs=1,
|
||||
metavar=("\"path to input file\""),
|
||||
dest="from_file",
|
||||
action="store",
|
||||
help="Parse options to request, by reading a zabbix config file for \"UserParameter\"s relating to I2P. Usage: \"-z /etc/zabbix/zabbix_agent.conf\"")
|
||||
|
||||
if (len(sys.argv) == 1):
|
||||
parser.parse_args(["-h"])
|
||||
options = parser.parse_args()
|
||||
|
||||
if ((options.rate_stat != None) and (options.router_info != None)):
|
||||
print("Error: Choose _one_ option. \n\n")
|
||||
parser.parse_args(["-h"])
|
||||
|
||||
if ((options.zabbix != None) and ((options.rate_stat != None) or (options.router_info != None) or (options.from_file != None))):
|
||||
print("Error: Don't combine option --zabbix with other options.\n")
|
||||
parser.parse_args(["-h"])
|
||||
|
||||
# From-file can only be used when either router-info or rate-stat is enabled.
|
||||
if ((options.from_file != None) and (options.rate_stat == None) and (options.router_info == None)):
|
||||
print("Error: --from-file must be used with either --router-info or --rate-stat.\n")
|
||||
parser.parse_args(["-h"])
|
||||
|
||||
if (options.from_file != None):
|
||||
if (options.router_info != None):
|
||||
from_file(options.from_file[0], options.router_info[0])
|
||||
if (options.rate_stat != None):
|
||||
from_file(options.from_file[0], options.rate_stat[0])
|
||||
sys.exit()
|
||||
|
||||
if (options.rate_stat != None):
|
||||
try:
|
||||
period = int(options.rate_stat[1])
|
||||
if (period < 60000):
|
||||
raise ValueError
|
||||
print getRate(options.rate_stat[0], period)
|
||||
except ValueError, e:
|
||||
print("Error: \""+options.rate_stat[1]+"\" is not an integer > 60000 \n\n")
|
||||
parser.parse_args(["-h"])
|
||||
sys.exit()
|
||||
|
||||
if (options.router_info != None):
|
||||
print getRouterInfo(options.router_info[0])
|
||||
sys.exit()
|
||||
|
||||
if (options.zabbix != None):
|
||||
zabbix_config(options.zabbix[0], options.zabbix[1])
|
||||
sys.exit()
|
||||
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
@ -7,6 +7,18 @@
|
||||
# zzz 2010-02
|
||||
# zzz 2014-08 added support for su3 files
|
||||
#
|
||||
|
||||
if [ -z "$I2P" -a -d "$PWD/../i2p/pkg-temp" ]; then
|
||||
export I2P=$PWD/../i2p/pkg-temp
|
||||
fi
|
||||
|
||||
if [ ! -d "$I2P" ]; then
|
||||
echo "Can't locate your I2P installation. Please add a environment variable named I2P with the path to the folder as value"
|
||||
echo "On OSX this solved with running: export I2P=/Applications/i2p if default install directory is used."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
CPATH=$I2P/lib/i2p.jar:/usr/share/java/gnu-getopt.jar
|
||||
PUBKEYDIR=$HOME/.i2p-plugin-keys
|
||||
PUBKEYFILE=$PUBKEYDIR/plugin-public-signing.key
|
||||
PRIVKEYFILE=$PUBKEYDIR/plugin-private-signing.key
|
||||
@ -15,60 +27,59 @@ PUBKEYSTORE=$PUBKEYDIR/plugin-su3-public-signing.crt
|
||||
PRIVKEYSTORE=$PUBKEYDIR/plugin-su3-keystore.ks
|
||||
KEYTYPE=RSA_SHA512_4096
|
||||
|
||||
export I2P=../i2p.i2p/pkg-temp
|
||||
|
||||
# put your files in here
|
||||
PLUGINDIR=${1:-plugin}
|
||||
|
||||
PC=plugin.config
|
||||
PCT=${PC}.tmp
|
||||
|
||||
if [ ! -d $PLUGINDIR ]
|
||||
if [ ! -d "$PLUGINDIR" ]
|
||||
then
|
||||
echo "You must have a $PLUGINDIR directory"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -f $PLUGINDIR/$PC ]
|
||||
if [ ! -f "$PLUGINDIR/$PC" ]
|
||||
then
|
||||
echo "You must have a $PLUGINDIR/$PC file"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
SIGNER=`grep '^signer=' $PLUGINDIR/$PC`
|
||||
SIGNER=`grep '^signer=' "$PLUGINDIR/$PC"`
|
||||
if [ "$?" -ne "0" ]
|
||||
then
|
||||
echo "You must have a plugin name in $PC"
|
||||
echo "You must have a signer name in $PC"
|
||||
echo 'For example name=foo'
|
||||
exit 1
|
||||
fi
|
||||
SIGNER=`echo $SIGNER | cut -f 2 -d '='`
|
||||
|
||||
if [ ! -f $PRIVKEYFILE ]
|
||||
if [ ! -f "$PRIVKEYFILE" ]
|
||||
then
|
||||
echo "Creating new XPI2P DSA keys"
|
||||
mkdir -p $PUBKEYDIR || exit 1
|
||||
java -cp $I2P/lib/i2p.jar net.i2p.crypto.TrustedUpdate keygen $PUBKEYFILE $PRIVKEYFILE || exit 1
|
||||
java -cp $I2P/lib/i2p.jar net.i2p.data.Base64 encode $PUBKEYFILE $B64KEYFILE || exit 1
|
||||
mkdir -p "$PUBKEYDIR" || exit 1
|
||||
java -cp "$CPATH" net.i2p.crypto.TrustedUpdate keygen "$PUBKEYFILE" "$PRIVKEYFILE" || exit 1
|
||||
java -cp "$CPATH" net.i2p.data.Base64 encode "$PUBKEYFILE" "$B64KEYFILE" || exit 1
|
||||
rm -rf logs/
|
||||
chmod 444 $PUBKEYFILE $B64KEYFILE
|
||||
chmod 400 $PRIVKEYFILE
|
||||
chmod 444 "$PUBKEYFILE" "$B64KEYFILE"
|
||||
chmod 400 "$PRIVKEYFILE"
|
||||
echo "Created new XPI2P keys: $PUBKEYFILE $PRIVKEYFILE"
|
||||
fi
|
||||
|
||||
if [ ! -f $PRIVKEYSTORE ]
|
||||
if [ ! -f "$PRIVKEYSTORE" ]
|
||||
then
|
||||
echo "Creating new SU3 $KEYTYPE keys for $SIGNER"
|
||||
java -cp $I2P/lib/i2p.jar net.i2p.crypto.SU3File keygen -t $KEYTYPE $PUBKEYSTORE $PRIVKEYSTORE $SIGNER || exit 1
|
||||
java -cp "$CPATH" net.i2p.crypto.SU3File keygen -t $KEYTYPE "$PUBKEYSTORE" "$PRIVKEYSTORE" $SIGNER || exit 1
|
||||
echo '*** Save your password in a safe place!!! ***'
|
||||
rm -rf logs/
|
||||
# copy to the router dir so verify will work
|
||||
CDIR=$I2P/certificates/plugin
|
||||
mkdir -p $CDIR || exit 1
|
||||
mkdir -p "$CDIR" || exit 1
|
||||
CFILE=$CDIR/`echo $SIGNER | sed s/@/_at_/`.crt
|
||||
cp $PUBKEYSTORE $CFILE
|
||||
chmod 444 $PUBKEYSTORE
|
||||
chmod 400 $PRIVKEYSTORE
|
||||
chmod 644 $CFILE
|
||||
cp "$PUBKEYSTORE" "$CFILE"
|
||||
chmod 444 "$PUBKEYSTORE"
|
||||
chmod 400 "$PRIVKEYSTORE"
|
||||
chmod 644 "$CFILE"
|
||||
echo "Created new SU3 keys: $PUBKEYSTORE $PRIVKEYSTORE"
|
||||
echo "Copied public key to $CFILE for testing"
|
||||
fi
|
||||
@ -76,7 +87,7 @@ fi
|
||||
rm -f plugin.zip
|
||||
|
||||
OPWD=$PWD
|
||||
cd $PLUGINDIR
|
||||
cd "$PLUGINDIR"
|
||||
|
||||
grep -q '^name=' $PC
|
||||
if [ "$?" -ne "0" ]
|
||||
@ -97,17 +108,17 @@ fi
|
||||
# update the date
|
||||
grep -v '^date=' $PC > $PCT
|
||||
DATE=`date '+%s000'`
|
||||
echo "date=$DATE" >> $PCT
|
||||
echo "date=$DATE" >> $PCT || exit 1
|
||||
mv $PCT $PC || exit 1
|
||||
|
||||
# add our Base64 key
|
||||
grep -v '^key=' $PC > $PCT
|
||||
B64KEY=`cat $B64KEYFILE`
|
||||
B64KEY=`cat "$B64KEYFILE"`
|
||||
echo "key=$B64KEY" >> $PCT || exit 1
|
||||
mv $PCT $PC || exit 1
|
||||
|
||||
# zip it
|
||||
zip -r $OPWD/plugin.zip * || exit 1
|
||||
zip -r "$OPWD/plugin.zip" * || exit 1
|
||||
|
||||
# get the version and use it for the sud header
|
||||
VERSION=`grep '^version=' $PC | cut -f 2 -d '='`
|
||||
@ -115,24 +126,24 @@ VERSION=`grep '^version=' $PC | cut -f 2 -d '='`
|
||||
NAME=`grep '^name=' $PC | cut -f 2 -d '='`
|
||||
XPI2P=${NAME}.xpi2p
|
||||
SU3=${NAME}.su3
|
||||
cd $OPWD
|
||||
cd "$OPWD"
|
||||
|
||||
# sign it
|
||||
echo 'Signing. ...'
|
||||
java -cp $I2P/lib/i2p.jar net.i2p.crypto.TrustedUpdate sign plugin.zip $XPI2P $PRIVKEYFILE $VERSION || exit 1
|
||||
java -cp $I2P/lib/i2p.jar net.i2p.crypto.SU3File sign -c PLUGIN -t $KEYTYPE plugin.zip $SU3 $PRIVKEYSTORE $VERSION $SIGNER || exit 1
|
||||
java -cp "$CPATH" net.i2p.crypto.TrustedUpdate sign plugin.zip "$XPI2P" "$PRIVKEYFILE" "$VERSION" || exit 1
|
||||
java -cp "$CPATH" net.i2p.crypto.SU3File sign -c PLUGIN -t $KEYTYPE plugin.zip "$SU3" "$PRIVKEYSTORE" "$VERSION" "$SIGNER" || exit 1
|
||||
rm -f plugin.zip
|
||||
|
||||
# verify
|
||||
echo 'Verifying. ...'
|
||||
java -cp $I2P/lib/i2p.jar net.i2p.crypto.TrustedUpdate showversion $XPI2P || exit 1
|
||||
java -cp $I2P/lib/i2p.jar -Drouter.trustedUpdateKeys=$B64KEY net.i2p.crypto.TrustedUpdate verifysig $XPI2P || exit 1
|
||||
java -cp $I2P/lib/i2p.jar net.i2p.crypto.SU3File showversion $SU3 || exit 1
|
||||
java -cp $I2P/lib/i2p.jar net.i2p.crypto.SU3File verifysig -k $PUBKEYSTORE $SU3 || exit 1
|
||||
java -cp "$CPATH" net.i2p.crypto.TrustedUpdate showversion "$XPI2P" || exit 1
|
||||
java -cp "$CPATH" -Drouter.trustedUpdateKeys=$B64KEY net.i2p.crypto.TrustedUpdate verifysig "$XPI2P" || exit 1
|
||||
java -cp "$CPATH" net.i2p.crypto.SU3File showversion "$SU3" || exit 1
|
||||
java -cp "$CPATH" net.i2p.crypto.SU3File verifysig -k "$PUBKEYSTORE" "$SU3" || exit 1
|
||||
rm -rf logs/
|
||||
|
||||
echo 'Plugin files created: '
|
||||
wc -c $XPI2P
|
||||
wc -c $SU3
|
||||
wc -c "$XPI2P"
|
||||
wc -c "$SU3"
|
||||
|
||||
exit 0
|
||||
|
@ -1,11 +1,11 @@
|
||||
name=I2PControl
|
||||
signer=dev@robertfoss.se
|
||||
signer=zzz-plugin@mail.i2p
|
||||
consoleLinkName=I2PControl
|
||||
description=Remote Control Service
|
||||
author=hottuna
|
||||
websiteURL=http://itoopie.i2p/
|
||||
updateURL=http://itoopie.i2p/files/I2PControl-update.xpi2p
|
||||
websiteURL=http://zzz.i2p/forums/16
|
||||
updateURL=http://zzz.i2p/i2p/plugins/I2PControl-update.xpi2p
|
||||
updateURL.su3=http://zzz.i2p/i2p/plugins/I2PControl-update.su3
|
||||
license=Apache 2.0
|
||||
min-jetty-version=7
|
||||
max-jetty-version=8.9999
|
||||
min-i2p-version=0.9.20
|
||||
min-jetty-version=9
|
||||
min-i2p-version=0.9.30
|
||||
|
@ -3,24 +3,15 @@
|
||||
<property name="i2pbase" value="../../i2p.i2p"/>
|
||||
<property name="i2plib" value="${i2pbase}/build"/>
|
||||
<property name="jettylib" value="${i2pbase}/apps/jetty/jettylib"/>
|
||||
<property name="wrapperlib" value="${i2pbase}/installer/lib/wrapper/all"/>
|
||||
<property name="wrapperlib" value="${i2pbase}/installer/lib/wrapper/all"/>
|
||||
|
||||
<path id="cp">
|
||||
<pathelement path="${java.class.path}" />
|
||||
<pathelement location="${i2plib}/i2p.jar" />
|
||||
<pathelement location="${i2plib}/router.jar" />
|
||||
<pathelement location="${i2plib}/i2ptunnel.jar" />
|
||||
<pathelement location="${i2plib}/org.mortbay.jetty.jar" />
|
||||
<pathelement location="${i2plib}/javax.servlet.jar" />
|
||||
<pathelement location="${ant.home}/lib/ant.jar"/>
|
||||
<pathelement location="${jettylib}/jetty-http.jar" />
|
||||
<pathelement location="${jettylib}/jetty-server.jar"/>
|
||||
<pathelement location="${jettylib}/jetty-servlet.jar" />
|
||||
<pathelement location="${jettylib}/jetty-servlets.jar" />
|
||||
<pathelement location="${jettylib}/jetty-util.jar" />
|
||||
<pathelement location="${jettylib}/jasper-compiler.jar" />
|
||||
<pathelement location="${jettylib}/jasper-runtime.jar" />
|
||||
<pathelement location="${jettylib}/commons-logging.jar" />
|
||||
<pathelement location="${wrapperlib}/wrapper.jar" />
|
||||
</path>
|
||||
|
||||
@ -41,7 +32,7 @@
|
||||
destdir="./build/obj"
|
||||
classpath="${cp}">
|
||||
<compilerarg line="${javac.compilerargs}" />
|
||||
<classpath refid="cp"/>
|
||||
<classpath refid="cp"/>
|
||||
</javac>
|
||||
</target>
|
||||
|
||||
|
@ -18,13 +18,13 @@ public class JSONRPC2ParseException extends Exception {
|
||||
* Indicates a parse exception caused by a JSON message not conforming
|
||||
* to the JSON-RPC 2.0 protocol.
|
||||
*/
|
||||
public static int PROTOCOL = 0;
|
||||
public static final int PROTOCOL = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Indicates a parse exception caused by invalid JSON.
|
||||
*/
|
||||
public static int JSON = 1;
|
||||
public static final int JSON = 1;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -17,16 +17,29 @@ package net.i2p.i2pcontrol;
|
||||
*/
|
||||
|
||||
import net.i2p.I2PAppContext;
|
||||
import net.i2p.app.ClientAppManager;
|
||||
import net.i2p.app.ClientAppState;
|
||||
import static net.i2p.app.ClientAppState.*;
|
||||
import net.i2p.router.RouterContext;
|
||||
import net.i2p.router.app.RouterApp;
|
||||
import net.i2p.util.I2PSSLSocketFactory;
|
||||
import net.i2p.util.Log;
|
||||
|
||||
import net.i2p.i2pcontrol.security.KeyStoreProvider;
|
||||
import net.i2p.i2pcontrol.security.SecurityManager;
|
||||
import net.i2p.i2pcontrol.servlets.JSONRPC2Servlet;
|
||||
import net.i2p.i2pcontrol.servlets.configuration.ConfigurationManager;
|
||||
import net.i2p.util.Log;
|
||||
|
||||
import org.eclipse.jetty.server.Connector;
|
||||
import org.eclipse.jetty.server.HttpConfiguration;
|
||||
import org.eclipse.jetty.server.HttpConnectionFactory;
|
||||
import org.eclipse.jetty.server.SecureRequestCustomizer;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.server.ssl.SslSocketConnector;
|
||||
import org.eclipse.jetty.server.ServerConnector;
|
||||
import org.eclipse.jetty.server.SslConnectionFactory;
|
||||
import org.eclipse.jetty.servlet.ServletHandler;
|
||||
import org.eclipse.jetty.servlet.ServletHolder;
|
||||
import org.eclipse.jetty.util.ssl.SslContextFactory;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
@ -45,14 +58,109 @@ import java.security.KeyStore;
|
||||
*
|
||||
* @author hottuna
|
||||
*/
|
||||
public class I2PControlController {
|
||||
private static final Log _log = I2PAppContext.getGlobalContext().logManager().getLog(I2PControlController.class);
|
||||
private static String _pluginDir = "";
|
||||
private static ConfigurationManager _conf;
|
||||
private static SecurityManager _secMan;
|
||||
private static Server _server;
|
||||
public class I2PControlController implements RouterApp {
|
||||
// non-null
|
||||
private final I2PAppContext _appContext;
|
||||
// warning, null in app context
|
||||
private final RouterContext _context;
|
||||
private final ClientAppManager _mgr;
|
||||
private final Log _log;
|
||||
private final String _pluginDir;
|
||||
private final ConfigurationManager _conf;
|
||||
private final KeyStoreProvider _ksp;
|
||||
private final SecurityManager _secMan;
|
||||
private final Server _server;
|
||||
private ClientAppState _state = UNINITIALIZED;
|
||||
// only for main()
|
||||
private static I2PControlController _instance;
|
||||
|
||||
public I2PControlController(RouterContext ctx, ClientAppManager mgr, String args[]) {
|
||||
_appContext = _context = ctx;
|
||||
_mgr = mgr;
|
||||
_log = _appContext.logManager().getLog(I2PControlController.class);
|
||||
File pluginDir = new File(_context.getAppDir(), "plugins/I2PControl");
|
||||
_pluginDir = pluginDir.getAbsolutePath();
|
||||
_conf = new ConfigurationManager(_pluginDir);
|
||||
_ksp = new KeyStoreProvider(_pluginDir);
|
||||
_secMan = new SecurityManager(_ksp, _conf);
|
||||
_server = buildServer();
|
||||
_state = INITIALIZED;
|
||||
}
|
||||
|
||||
/**
|
||||
* From main()
|
||||
*/
|
||||
public I2PControlController(File pluginDir) {
|
||||
_appContext = I2PAppContext.getGlobalContext();
|
||||
if (_appContext instanceof RouterContext)
|
||||
_context = (RouterContext) _appContext;
|
||||
else
|
||||
_context = null;
|
||||
_mgr = null;
|
||||
_log = _appContext.logManager().getLog(I2PControlController.class);
|
||||
_pluginDir = pluginDir.getAbsolutePath();
|
||||
_conf = new ConfigurationManager(_pluginDir);
|
||||
_ksp = new KeyStoreProvider(_pluginDir);
|
||||
_secMan = new SecurityManager(_ksp, _conf);
|
||||
_server = buildServer();
|
||||
_state = INITIALIZED;
|
||||
}
|
||||
|
||||
/////// ClientApp methods
|
||||
|
||||
public synchronized void startup() {
|
||||
changeState(STARTING);
|
||||
try {
|
||||
start(null);
|
||||
changeState(RUNNING);
|
||||
} catch (Exception e) {
|
||||
changeState(START_FAILED, "Failed to start", e);
|
||||
_log.error("Unable to start jetty server", e);
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void shutdown(String[] args) {
|
||||
if (_state == STOPPED)
|
||||
return;
|
||||
changeState(STOPPING);
|
||||
stop();
|
||||
changeState(STOPPED);
|
||||
}
|
||||
|
||||
public synchronized ClientAppState getState() {
|
||||
return _state;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return "I2PControl";
|
||||
}
|
||||
|
||||
public String getDisplayName() {
|
||||
return "I2PControl";
|
||||
}
|
||||
|
||||
/////// end ClientApp methods
|
||||
|
||||
private void changeState(ClientAppState state) {
|
||||
changeState(state, null, null);
|
||||
}
|
||||
|
||||
private synchronized void changeState(ClientAppState state, String msg, Exception e) {
|
||||
_state = state;
|
||||
if (_mgr != null)
|
||||
_mgr.notify(this, state, msg, e);
|
||||
if (_context == null) {
|
||||
if (msg != null)
|
||||
System.out.println(state + ": " + msg);
|
||||
if (e != null)
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Deprecated, use constructor
|
||||
*/
|
||||
public static void main(String args[]) {
|
||||
if (args.length != 3 || (!"-d".equals(args[0])))
|
||||
throw new IllegalArgumentException("Usage: PluginController -d $PLUGINDIR [start|stop]");
|
||||
@ -61,37 +169,33 @@ public class I2PControlController {
|
||||
File pluginDir = new File(args[1]);
|
||||
if (!pluginDir.exists())
|
||||
throw new IllegalArgumentException("Plugin directory " + pluginDir.getAbsolutePath() + " does not exist");
|
||||
_pluginDir = pluginDir.getAbsolutePath();
|
||||
ConfigurationManager.setConfDir(pluginDir.getAbsolutePath());
|
||||
_conf = ConfigurationManager.getInstance();
|
||||
_secMan = SecurityManager.getInstance();
|
||||
start(args);
|
||||
//stop(); // Delete Me
|
||||
|
||||
} else if ("stop".equals(args[2]))
|
||||
stop();
|
||||
else
|
||||
synchronized(I2PControlController.class) {
|
||||
if (_instance != null)
|
||||
throw new IllegalStateException();
|
||||
I2PControlController i2pcc = new I2PControlController(pluginDir);
|
||||
try {
|
||||
i2pcc.startup();
|
||||
_instance = i2pcc;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
} else if ("stop".equals(args[2])) {
|
||||
synchronized(I2PControlController.class) {
|
||||
if (_instance != null) {
|
||||
_instance.shutdown(null);
|
||||
_instance = null;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw new IllegalArgumentException("Usage: PluginController -d $PLUGINDIR [start|stop]");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void start(String args[]) {
|
||||
I2PAppContext.getGlobalContext().logManager().getLog(JSONRPC2Servlet.class).setMinimumPriority(Log.DEBUG);
|
||||
|
||||
try {
|
||||
Connector ssl = buildDefaultListenter();
|
||||
_server = buildServer(ssl);
|
||||
} catch (IOException e) {
|
||||
_log.error("Unable to add listener " + _conf.getConf("i2pcontrol.listen.address", "127.0.0.1") + ":" + _conf.getConf("i2pcontrol.listen.port", 7560) + " - " + e.getMessage());
|
||||
} catch (ClassNotFoundException e) {
|
||||
_log.error("Unable to find class net.i2p.i2pcontrol.JSONRPCServlet: " + e.getMessage());
|
||||
} catch (InstantiationException e) {
|
||||
_log.error("Unable to instantiate class net.i2p.i2pcontrol.JSONRPCServlet: " + e.getMessage());
|
||||
} catch (IllegalAccessException e) {
|
||||
_log.error("Illegal access: " + e.getMessage());
|
||||
} catch (Exception e) {
|
||||
_log.error("Unable to start jetty server: " + e.getMessage());
|
||||
}
|
||||
private synchronized void start(String args[]) throws Exception {
|
||||
_appContext.logManager().getLog(JSONRPC2Servlet.class).setMinimumPriority(Log.DEBUG);
|
||||
_server.start();
|
||||
}
|
||||
|
||||
|
||||
@ -99,10 +203,9 @@ public class I2PControlController {
|
||||
/**
|
||||
* Builds a new server. Used for changing ports during operation and such.
|
||||
* @return Server - A new server built from current configuration.
|
||||
* @throws UnknownHostException
|
||||
*/
|
||||
public static Connector buildDefaultListenter() throws UnknownHostException {
|
||||
SslSocketConnector ssl = buildSslListener(_conf.getConf("i2pcontrol.listen.address", "127.0.0.1"),
|
||||
private Connector buildDefaultListener(Server server) {
|
||||
Connector ssl = buildSslListener(server, _conf.getConf("i2pcontrol.listen.address", "127.0.0.1"),
|
||||
_conf.getConf("i2pcontrol.listen.port", 7650));
|
||||
return ssl;
|
||||
}
|
||||
@ -110,20 +213,19 @@ public class I2PControlController {
|
||||
|
||||
/**
|
||||
* Builds a new server. Used for changing ports during operation and such.
|
||||
*
|
||||
* Does NOT start the server. Must call start() on the returned server.
|
||||
*
|
||||
* @return Server - A new server built from current configuration.
|
||||
* @throws UnknownHostException
|
||||
* @throws Exception
|
||||
* @throws InstantiationException
|
||||
* @throws IllegalAccessException
|
||||
*/
|
||||
public static Server buildServer(Connector ssl) throws UnknownHostException, Exception, InstantiationException, IllegalAccessException {
|
||||
public Server buildServer() {
|
||||
Server server = new Server();
|
||||
Connector ssl = buildDefaultListener(server);
|
||||
server.addConnector(ssl);
|
||||
|
||||
ServletHandler sh = new ServletHandler();
|
||||
sh.addServletWithMapping(net.i2p.i2pcontrol.servlets.JSONRPC2Servlet.class, "/");
|
||||
sh.addServletWithMapping(new ServletHolder(new JSONRPC2Servlet(_context, _secMan)), "/");
|
||||
server.getServer().setHandler(sh);
|
||||
server.start();
|
||||
|
||||
return server;
|
||||
}
|
||||
@ -134,24 +236,38 @@ public class I2PControlController {
|
||||
* @param address - The address the listener will listen to.
|
||||
* @param port - The port the listener will listen to.
|
||||
* @return - Newly created listener
|
||||
* @throws UnknownHostException
|
||||
*/
|
||||
public static SslSocketConnector buildSslListener(String address, int port) throws UnknownHostException {
|
||||
private Connector buildSslListener(Server server, String address, int port) {
|
||||
int listeners = 0;
|
||||
if (_server != null) {
|
||||
listeners = _server.getConnectors().length;
|
||||
if (server != null) {
|
||||
listeners = server.getConnectors().length;
|
||||
}
|
||||
|
||||
SslSocketConnector ssl = new SslSocketConnector();
|
||||
ssl.setProvider(_secMan.getSecurityProvider());
|
||||
//ssl.setCipherSuites(_secMan.getSupprtedSSLCipherSuites()); Removed in Jetty 5->6 port.
|
||||
// the keystore path and password
|
||||
SslContextFactory sslFactory = new SslContextFactory(_ksp.getKeyStoreLocation());
|
||||
sslFactory.setKeyStorePassword(KeyStoreProvider.DEFAULT_KEYSTORE_PASSWORD);
|
||||
// the X.509 cert password (if not present, verifyKeyStore() returned false)
|
||||
sslFactory.setKeyManagerPassword(KeyStoreProvider.DEFAULT_KEYSTORE_PASSWORD);
|
||||
sslFactory.addExcludeProtocols(I2PSSLSocketFactory.EXCLUDE_PROTOCOLS.toArray(
|
||||
new String[I2PSSLSocketFactory.EXCLUDE_PROTOCOLS.size()]));
|
||||
sslFactory.addExcludeCipherSuites(I2PSSLSocketFactory.EXCLUDE_CIPHERS.toArray(
|
||||
new String[I2PSSLSocketFactory.EXCLUDE_CIPHERS.size()]));
|
||||
|
||||
HttpConfiguration httpConfig = new HttpConfiguration();
|
||||
httpConfig.setSecureScheme("https");
|
||||
httpConfig.setSecurePort(port);
|
||||
httpConfig.addCustomizer(new SecureRequestCustomizer());
|
||||
// number of acceptors, (default) number of selectors
|
||||
ServerConnector ssl = new ServerConnector(server, 1, 0,
|
||||
new SslConnectionFactory(sslFactory, "http/1.1"),
|
||||
new HttpConnectionFactory(httpConfig));
|
||||
ssl.setHost(address);
|
||||
ssl.setPort(port);
|
||||
ssl.setWantClientAuth(false); // Don't care about client authentication.
|
||||
ssl.setPassword(KeyStoreProvider.DEFAULT_KEYSTORE_PASSWORD);
|
||||
ssl.setKeyPassword(KeyStoreProvider.DEFAULT_KEYSTORE_PASSWORD);
|
||||
ssl.setKeystoreType(KeyStore.getDefaultType());
|
||||
ssl.setKeystore(KeyStoreProvider.getKeyStoreLocation());
|
||||
ssl.setIdleTimeout(90*1000); // default 10 sec
|
||||
// all with same name will use the same thread pool
|
||||
//ssll.setName("ConsoleSocket");
|
||||
ssl.setName("I2PControl");
|
||||
|
||||
ssl.setName("SSL Listener-" + ++listeners);
|
||||
|
||||
return ssl;
|
||||
@ -166,36 +282,45 @@ public class I2PControlController {
|
||||
* @param listener
|
||||
* @throws Exception
|
||||
*/
|
||||
public static void replaceListener(Connector listener) throws Exception {
|
||||
/****
|
||||
public synchronized void replaceListener(Connector listener) throws Exception {
|
||||
if (_server != null) {
|
||||
stopServer();
|
||||
}
|
||||
_server = buildServer(listener);
|
||||
}
|
||||
****/
|
||||
|
||||
/**
|
||||
* Get all listeners of the server.
|
||||
* @return
|
||||
*/
|
||||
public static Connector[] getListeners() {
|
||||
/****
|
||||
public synchronized Connector[] getListeners() {
|
||||
if (_server != null) {
|
||||
return _server.getConnectors();
|
||||
}
|
||||
return new Connector[0];
|
||||
}
|
||||
****/
|
||||
|
||||
/**
|
||||
* Removes all listeners
|
||||
*/
|
||||
public static void clearListeners() {
|
||||
/****
|
||||
public synchronized void clearListeners() {
|
||||
if (_server != null) {
|
||||
for (Connector listen : getListeners()) {
|
||||
_server.removeConnector(listen);
|
||||
}
|
||||
}
|
||||
}
|
||||
****/
|
||||
|
||||
private static void stopServer()
|
||||
/**
|
||||
* Stop it
|
||||
*/
|
||||
private synchronized void stopServer()
|
||||
{
|
||||
try {
|
||||
if (_server != null) {
|
||||
@ -204,21 +329,18 @@ public class I2PControlController {
|
||||
listener.stop();
|
||||
}
|
||||
_server.destroy();
|
||||
_server = null;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
_log.error("Stopping server" + e);
|
||||
_log.error("Stopping server", e);
|
||||
}
|
||||
}
|
||||
|
||||
private static void stop() {
|
||||
ConfigurationManager.writeConfFile();
|
||||
if (_secMan != null) {
|
||||
_secMan.stopTimedEvents();
|
||||
}
|
||||
|
||||
private synchronized void stop() {
|
||||
_conf.writeConfFile();
|
||||
_secMan.stopTimedEvents();
|
||||
stopServer();
|
||||
|
||||
/****
|
||||
// Get and stop all running threads
|
||||
ThreadGroup threadgroup = Thread.currentThread().getThreadGroup();
|
||||
Thread[] threads = new Thread[threadgroup.activeCount() + 3];
|
||||
@ -237,9 +359,10 @@ public class I2PControlController {
|
||||
threadgroup.interrupt();
|
||||
|
||||
//Thread.currentThread().getThreadGroup().destroy();
|
||||
****/
|
||||
}
|
||||
|
||||
public static String getPluginDir() {
|
||||
public String getPluginDir() {
|
||||
return _pluginDir;
|
||||
}
|
||||
}
|
||||
|
@ -1,33 +0,0 @@
|
||||
package net.i2p.i2pcontrol.router;
|
||||
|
||||
|
||||
import net.i2p.I2PAppContext;
|
||||
import net.i2p.router.RouterContext;
|
||||
import net.i2p.util.Log;
|
||||
|
||||
/**
|
||||
* Handle communications with the router instance.
|
||||
* @author mathias
|
||||
*
|
||||
*/
|
||||
public class RouterManager {
|
||||
private final static Log _log = new Log(RouterManager.class);
|
||||
private static I2PAppContext context = I2PAppContext.getCurrentContext();
|
||||
private static boolean startedTestRouter = false;
|
||||
private final static String I2P_DIR = "/home/hottuna/Apps/i2p/";
|
||||
private final static String I2P_CONFIG_FILE = "/home/hottuna/.i2p/router.config";
|
||||
|
||||
|
||||
public static I2PAppContext getAppContext() {
|
||||
return context;
|
||||
}
|
||||
|
||||
public static RouterContext getRouterContext() throws Exception {
|
||||
// If not running as a plugin from within I2P.
|
||||
if (context.isRouterContext()) {
|
||||
return (RouterContext) context;
|
||||
} else {
|
||||
throw new Exception("No RouterContext available!");
|
||||
}
|
||||
}
|
||||
}
|
@ -11,8 +11,8 @@ public class AuthToken {
|
||||
private String id;
|
||||
private Date expiry;
|
||||
|
||||
public AuthToken(String password) {
|
||||
_secMan = SecurityManager.getInstance();
|
||||
public AuthToken(SecurityManager secMan, String password) {
|
||||
_secMan = secMan;
|
||||
String hash = _secMan.getPasswdHash(password);
|
||||
this.id = _secMan.getHash(hash + Calendar.getInstance().getTimeInMillis());
|
||||
Calendar expiry = Calendar.getInstance();
|
||||
|
@ -1,9 +1,13 @@
|
||||
package net.i2p.i2pcontrol.security;
|
||||
|
||||
import net.i2p.crypto.KeyStoreUtil;
|
||||
import net.i2p.i2pcontrol.I2PControlController;
|
||||
import java.io.*;
|
||||
import java.security.*;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
import java.security.KeyStore;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.X509Certificate;
|
||||
|
||||
@ -15,10 +19,14 @@ public class KeyStoreProvider {
|
||||
public final static String DEFAULT_CERTIFICATE_ALIAS = "I2PControl CA";
|
||||
public static final String DEFAULT_KEYSTORE_NAME = "key.store";
|
||||
public static final String DEFAULT_KEYSTORE_PASSWORD = "nut'nfancy";
|
||||
private static KeyStore _keystore = null;
|
||||
private final String _pluginDir;
|
||||
private KeyStore _keystore;
|
||||
|
||||
public KeyStoreProvider(String pluginDir) {
|
||||
_pluginDir = pluginDir;
|
||||
}
|
||||
|
||||
public static void initialize() {
|
||||
public void initialize() {
|
||||
KeyStoreUtil.createKeys(new File(getKeyStoreLocation()),
|
||||
DEFAULT_KEYSTORE_PASSWORD,
|
||||
DEFAULT_CERTIFICATE_ALIAS,
|
||||
@ -30,6 +38,10 @@ public class KeyStoreProvider {
|
||||
DEFAULT_KEYSTORE_PASSWORD);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param password unused
|
||||
* @return null on failure
|
||||
*/
|
||||
public static X509Certificate readCert(KeyStore ks, String certAlias, String password) {
|
||||
try {
|
||||
X509Certificate cert = (X509Certificate) ks.getCertificate(certAlias);
|
||||
@ -51,6 +63,11 @@ public class KeyStoreProvider {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param password for the keystore
|
||||
* @return null on failure
|
||||
*/
|
||||
/****
|
||||
public static X509Certificate readCert(File keyStoreFile, String certAlias, String password) {
|
||||
try {
|
||||
KeyStore ks = getDefaultKeyStore();
|
||||
@ -81,7 +98,13 @@ public class KeyStoreProvider {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
****/
|
||||
|
||||
/**
|
||||
* @param password for the key
|
||||
* @return null on failure, or throws RuntimeException...
|
||||
*/
|
||||
/****
|
||||
public static PrivateKey readPrivateKey(KeyStore ks, String alias, String password) {
|
||||
try {
|
||||
// load the key entry from the keystore
|
||||
@ -102,7 +125,12 @@ public class KeyStoreProvider {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
****/
|
||||
|
||||
/**
|
||||
* @return null on failure
|
||||
*/
|
||||
/****
|
||||
public static PrivateKey readPrivateKey(String alias, File keyStoreFile, String keyStorePassword, String keyPassword) {
|
||||
try {
|
||||
KeyStore ks = getDefaultKeyStore();
|
||||
@ -120,7 +148,12 @@ public class KeyStoreProvider {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
****/
|
||||
|
||||
/**
|
||||
* @return null on failure
|
||||
*/
|
||||
/****
|
||||
public static KeyStore writeCACertToKeyStore(KeyStore keyStore, String keyPassword, String alias, PrivateKey caPrivKey, X509Certificate caCert) {
|
||||
try {
|
||||
X509Certificate[] chain = new X509Certificate[1];
|
||||
@ -143,8 +176,12 @@ public class KeyStoreProvider {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
****/
|
||||
|
||||
public static synchronized KeyStore getDefaultKeyStore() {
|
||||
/**
|
||||
* @return null on failure
|
||||
*/
|
||||
public synchronized KeyStore getDefaultKeyStore() {
|
||||
if (_keystore == null) {
|
||||
File keyStoreFile = new File(getKeyStoreLocation());
|
||||
|
||||
@ -157,7 +194,6 @@ public class KeyStoreProvider {
|
||||
}
|
||||
|
||||
initialize();
|
||||
_keystore = KeyStore.getInstance(KeyStore.getDefaultType());
|
||||
if (keyStoreFile.exists()) {
|
||||
InputStream is = new FileInputStream(keyStoreFile);
|
||||
_keystore.load(is, DEFAULT_KEYSTORE_PASSWORD.toCharArray());
|
||||
@ -174,8 +210,8 @@ public class KeyStoreProvider {
|
||||
}
|
||||
}
|
||||
|
||||
public static String getKeyStoreLocation() {
|
||||
File keyStoreFile = new File(I2PControlController.getPluginDir() + File.separator + DEFAULT_KEYSTORE_NAME);
|
||||
public String getKeyStoreLocation() {
|
||||
File keyStoreFile = new File(_pluginDir, DEFAULT_KEYSTORE_NAME);
|
||||
return keyStoreFile.getAbsolutePath();
|
||||
}
|
||||
}
|
||||
|
@ -35,24 +35,16 @@ import java.util.*;
|
||||
* Manage the password storing for I2PControl.
|
||||
*/
|
||||
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 HashMap<String, AuthToken> authTokens;
|
||||
private Timer timer;
|
||||
private String[] SSL_CIPHER_SUITES;
|
||||
private KeyStore _ks;
|
||||
private Log _log;
|
||||
private static SecurityManager _securityManager;
|
||||
private final HashMap<String, AuthToken> authTokens;
|
||||
private final Timer timer;
|
||||
private final KeyStore _ks;
|
||||
private final Log _log;
|
||||
private final ConfigurationManager _conf;
|
||||
|
||||
public static SecurityManager getInstance() {
|
||||
if (_securityManager == null) {
|
||||
_securityManager = new SecurityManager();
|
||||
}
|
||||
return _securityManager;
|
||||
}
|
||||
|
||||
private SecurityManager() {
|
||||
public SecurityManager(KeyStoreProvider ksp, ConfigurationManager conf) {
|
||||
_conf = conf;
|
||||
_log = I2PAppContext.getGlobalContext().logManager().getLog(SecurityManager.class);
|
||||
authTokens = new HashMap<String, AuthToken>();
|
||||
|
||||
@ -60,23 +52,7 @@ public class SecurityManager {
|
||||
// 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 cipher suites.
|
||||
SocketFactory SSLF = SSLSocketFactory.getDefault();
|
||||
try {
|
||||
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);
|
||||
}
|
||||
|
||||
_ks = KeyStoreProvider.getDefaultKeyStore();
|
||||
}
|
||||
|
||||
public String[] getSupprtedSSLCipherSuites() {
|
||||
return SSL_CIPHER_SUITES;
|
||||
}
|
||||
|
||||
public String getSecurityProvider() {
|
||||
return SSL_PROVIDER;
|
||||
_ks = ksp.getDefaultKeyStore();
|
||||
}
|
||||
|
||||
public void stopTimedEvents() {
|
||||
@ -116,7 +92,7 @@ public class SecurityManager {
|
||||
* @return BCrypt hash of salt and input string
|
||||
*/
|
||||
public String getPasswdHash(String pwd) {
|
||||
return BCrypt.hashpw(pwd, ConfigurationManager.getInstance().getConf("auth.salt", DEFAULT_AUTH_BCRYPT_SALT));
|
||||
return BCrypt.hashpw(pwd, _conf.getConf("auth.salt", DEFAULT_AUTH_BCRYPT_SALT));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -138,9 +114,9 @@ public class SecurityManager {
|
||||
* @return Returns AuthToken if password is valid. If password is invalid null will be returned.
|
||||
*/
|
||||
public AuthToken validatePasswd(String pwd) {
|
||||
String storedPass = ConfigurationManager.getInstance().getConf("auth.password", DEFAULT_AUTH_PASSWORD);
|
||||
String storedPass = _conf.getConf("auth.password", DEFAULT_AUTH_PASSWORD);
|
||||
if (getPasswdHash(pwd).equals(storedPass)) {
|
||||
AuthToken token = new AuthToken(pwd);
|
||||
AuthToken token = new AuthToken(this, pwd);
|
||||
synchronized (authTokens) {
|
||||
authTokens.put(token.getId(), token);
|
||||
}
|
||||
@ -157,10 +133,10 @@ public class SecurityManager {
|
||||
*/
|
||||
public boolean setPasswd(String newPasswd) {
|
||||
String newHash = getPasswdHash(newPasswd);
|
||||
String oldHash = ConfigurationManager.getInstance().getConf("auth.password", DEFAULT_AUTH_PASSWORD);
|
||||
String oldHash = _conf.getConf("auth.password", DEFAULT_AUTH_PASSWORD);
|
||||
|
||||
if (!newHash.equals(oldHash)) {
|
||||
ConfigurationManager.getInstance().setConf("auth.password", newHash);
|
||||
_conf.setConf("auth.password", newHash);
|
||||
synchronized (authTokens) {
|
||||
authTokens.clear();
|
||||
}
|
||||
|
@ -18,17 +18,27 @@ package net.i2p.i2pcontrol.servlets;
|
||||
|
||||
import com.thetransactioncompany.jsonrpc2.*;
|
||||
import com.thetransactioncompany.jsonrpc2.server.Dispatcher;
|
||||
|
||||
import net.i2p.I2PAppContext;
|
||||
import net.i2p.router.RouterContext;
|
||||
import net.i2p.util.Log;
|
||||
|
||||
import net.i2p.i2pcontrol.I2PControlVersion;
|
||||
import net.i2p.i2pcontrol.servlets.jsonrpc2handlers.*;
|
||||
import net.i2p.util.Log;
|
||||
import net.i2p.i2pcontrol.security.SecurityManager;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletInputStream;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.*;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.io.Writer;
|
||||
|
||||
|
||||
/**
|
||||
@ -38,25 +48,33 @@ public class JSONRPC2Servlet extends HttpServlet {
|
||||
|
||||
private static final long serialVersionUID = -45075606818515212L;
|
||||
private static final int BUFFER_LENGTH = 2048;
|
||||
private static Dispatcher disp;
|
||||
private static char[] readBuffer;
|
||||
private static Log _log;
|
||||
private Dispatcher disp;
|
||||
private Log _log;
|
||||
private final SecurityManager _secMan;
|
||||
private final JSONRPC2Helper _helper;
|
||||
private final RouterContext _context;
|
||||
|
||||
public JSONRPC2Servlet(RouterContext ctx, SecurityManager secMan) {
|
||||
_context = ctx;
|
||||
_secMan = secMan;
|
||||
_helper = new JSONRPC2Helper(_secMan);
|
||||
if (ctx != null)
|
||||
_log = ctx.logManager().getLog(JSONRPC2Servlet.class);
|
||||
else
|
||||
_log = I2PAppContext.getGlobalContext().logManager().getLog(JSONRPC2Servlet.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
_log = I2PAppContext.getGlobalContext().logManager().getLog(JSONRPC2Servlet.class);
|
||||
readBuffer = new char[BUFFER_LENGTH];
|
||||
|
||||
disp = new Dispatcher();
|
||||
disp.register(new EchoHandler());
|
||||
disp.register(new GetRateHandler());
|
||||
disp.register(new AuthenticateHandler());
|
||||
disp.register(new NetworkSettingHandler());
|
||||
disp.register(new RouterInfoHandler());
|
||||
disp.register(new RouterManagerHandler());
|
||||
disp.register(new I2PControlHandler());
|
||||
disp.register(new AdvancedSettingsHandler());
|
||||
disp.register(new EchoHandler(_helper));
|
||||
disp.register(new GetRateHandler(_helper));
|
||||
disp.register(new AuthenticateHandler(_helper, _secMan));
|
||||
disp.register(new NetworkSettingHandler(_context, _helper));
|
||||
disp.register(new RouterInfoHandler(_context, _helper));
|
||||
disp.register(new RouterManagerHandler(_context, _helper));
|
||||
disp.register(new I2PControlHandler(_context, _helper));
|
||||
disp.register(new AdvancedSettingsHandler(_context, _helper));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -80,12 +98,15 @@ public class JSONRPC2Servlet extends HttpServlet {
|
||||
if (msg instanceof JSONRPC2Request) {
|
||||
jsonResp = disp.dispatch((JSONRPC2Request)msg, null);
|
||||
jsonResp.toJSON().put("API", I2PControlVersion.API_VERSION);
|
||||
_log.debug("Request: " + msg);
|
||||
_log.debug("Response: " + jsonResp);
|
||||
if (_log.shouldDebug()) {
|
||||
_log.debug("Request: " + msg);
|
||||
_log.debug("Response: " + jsonResp);
|
||||
}
|
||||
}
|
||||
else if (msg instanceof JSONRPC2Notification) {
|
||||
disp.dispatch((JSONRPC2Notification)msg, null);
|
||||
_log.debug("Notification: " + msg);
|
||||
if (_log.shouldDebug())
|
||||
_log.debug("Notification: " + msg);
|
||||
}
|
||||
|
||||
out.println(jsonResp);
|
||||
@ -99,6 +120,7 @@ public class JSONRPC2Servlet extends HttpServlet {
|
||||
Writer writer = new StringWriter();
|
||||
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(sis, "UTF-8"));
|
||||
char[] readBuffer = new char[BUFFER_LENGTH];
|
||||
int n;
|
||||
while ((n = reader.read(readBuffer)) != -1) {
|
||||
writer.write(readBuffer, 0, n);
|
||||
|
@ -2,8 +2,15 @@ package net.i2p.i2pcontrol.servlets.configuration;
|
||||
|
||||
import net.i2p.I2PAppContext;
|
||||
import net.i2p.util.Log;
|
||||
import net.i2p.util.SecureFileOutputStream;
|
||||
|
||||
import java.io.*;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileReader;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
@ -16,44 +23,30 @@ import java.util.TreeMap;
|
||||
*
|
||||
*/
|
||||
public class ConfigurationManager {
|
||||
private static String configLocation = "I2PControl.conf";
|
||||
private static boolean configLocationModified = false;
|
||||
private static final Log _log = I2PAppContext.getGlobalContext().logManager().getLog(ConfigurationManager.class);
|
||||
private final String CONFIG_FILE = "I2PControl.conf";
|
||||
private final String configLocation;
|
||||
private final Log _log;
|
||||
|
||||
private static ConfigurationManager instance;
|
||||
private ConfigurationManager instance;
|
||||
//Configurations with a String as value
|
||||
private static Map<String, String> stringConfigurations = new HashMap<String, String>();
|
||||
private final Map<String, String> stringConfigurations = new HashMap<String, String>();
|
||||
//Configurations with a Boolean as value
|
||||
private static Map<String, Boolean> booleanConfigurations = new HashMap<String, Boolean>();
|
||||
private final Map<String, Boolean> booleanConfigurations = new HashMap<String, Boolean>();
|
||||
//Configurations with an Integer as value
|
||||
private static Map<String, Integer> integerConfigurations = new HashMap<String, Integer>();
|
||||
private final Map<String, Integer> integerConfigurations = new HashMap<String, Integer>();
|
||||
|
||||
|
||||
/**
|
||||
* Should only be set before getInstance is first called.
|
||||
* @param dir
|
||||
*/
|
||||
public static void setConfDir(String dir) {
|
||||
if (!configLocationModified) {
|
||||
if (dir.endsWith("/")) {
|
||||
configLocation = dir + configLocation;
|
||||
} else {
|
||||
configLocation = dir + "/" + configLocation;
|
||||
}
|
||||
|
||||
public ConfigurationManager(String dir) {
|
||||
_log = I2PAppContext.getGlobalContext().logManager().getLog(ConfigurationManager.class);
|
||||
if (dir.endsWith("/")) {
|
||||
configLocation = dir + CONFIG_FILE;
|
||||
} else {
|
||||
configLocation = dir + "/" + CONFIG_FILE;
|
||||
}
|
||||
}
|
||||
|
||||
private ConfigurationManager() {
|
||||
readConfFile();
|
||||
}
|
||||
|
||||
public synchronized static ConfigurationManager getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new ConfigurationManager();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Collects settingNameuments of the form --word, --word=otherword and -blah
|
||||
* to determine user parameters.
|
||||
@ -71,7 +64,7 @@ public class ConfigurationManager {
|
||||
/**
|
||||
* Reads configuration from file itoopie.conf, every line is parsed as key=value.
|
||||
*/
|
||||
public static void readConfFile() {
|
||||
public void readConfFile() {
|
||||
try {
|
||||
BufferedReader br = new BufferedReader(new FileReader(configLocation));
|
||||
String input;
|
||||
@ -89,7 +82,7 @@ public class ConfigurationManager {
|
||||
/**
|
||||
* Write configuration into default config file.
|
||||
*/
|
||||
public static void writeConfFile() {
|
||||
public void writeConfFile() {
|
||||
TreeMap<String, String> tree = new TreeMap<String, String>();
|
||||
for (Entry<String, String> e : stringConfigurations.entrySet()) {
|
||||
tree.put(e.getKey(), e.getValue());
|
||||
@ -101,7 +94,7 @@ public class ConfigurationManager {
|
||||
tree.put(e.getKey(), e.getValue().toString());
|
||||
}
|
||||
try {
|
||||
BufferedWriter bw = new BufferedWriter(new FileWriter(configLocation));
|
||||
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new SecureFileOutputStream(configLocation)));
|
||||
for (Entry<String, String> e : tree.entrySet()) {
|
||||
bw.write(e.getKey() + "=" + e.getValue() + "\r\n");
|
||||
}
|
||||
@ -116,7 +109,7 @@ public class ConfigurationManager {
|
||||
* where value will (in order) be parsed as integer/boolean/string.
|
||||
* @param str
|
||||
*/
|
||||
public static void parseConfigStr(String str) {
|
||||
public void parseConfigStr(String str) {
|
||||
int eqIndex = str.indexOf('=');
|
||||
if (eqIndex != -1) {
|
||||
String key = str.substring(0, eqIndex).trim().toLowerCase();
|
||||
|
@ -7,7 +7,6 @@ import com.thetransactioncompany.jsonrpc2.server.MessageContext;
|
||||
import com.thetransactioncompany.jsonrpc2.server.RequestHandler;
|
||||
|
||||
import net.i2p.I2PAppContext;
|
||||
import net.i2p.i2pcontrol.router.RouterManager;
|
||||
import net.i2p.router.RouterContext;
|
||||
import net.i2p.util.Log;
|
||||
|
||||
@ -18,18 +17,20 @@ import java.util.Set;
|
||||
|
||||
public class AdvancedSettingsHandler implements RequestHandler {
|
||||
|
||||
private static RouterContext _context;
|
||||
private static final Log _log = I2PAppContext.getGlobalContext().logManager().getLog(AdvancedSettingsHandler.class);
|
||||
private final RouterContext _context;
|
||||
private final Log _log;
|
||||
private final JSONRPC2Helper _helper;
|
||||
private static final String[] requiredArgs = {};
|
||||
|
||||
static {
|
||||
try {
|
||||
_context = RouterManager.getRouterContext();
|
||||
} catch (Exception e) {
|
||||
_log.error("Unable to initialize RouterContext.", e);
|
||||
}
|
||||
public AdvancedSettingsHandler(RouterContext ctx, JSONRPC2Helper helper) {
|
||||
_helper = helper;
|
||||
_context = ctx;
|
||||
if (ctx != null)
|
||||
_log = ctx.logManager().getLog(AdvancedSettingsHandler.class);
|
||||
else
|
||||
_log = I2PAppContext.getGlobalContext().logManager().getLog(AdvancedSettingsHandler.class);
|
||||
}
|
||||
|
||||
private String[] requiredArgs = {};
|
||||
// Reports the method names of the handled requests
|
||||
public String[] handledRequests() {
|
||||
return new String[] {"AdvancedSettings"};
|
||||
@ -39,11 +40,18 @@ public class AdvancedSettingsHandler implements RequestHandler {
|
||||
@SuppressWarnings("unchecked")
|
||||
public JSONRPC2Response process(JSONRPC2Request req, MessageContext ctx) {
|
||||
if (req.getMethod().equals("AdvancedSettings")) {
|
||||
JSONRPC2Error err = JSONRPC2Helper.validateParams(requiredArgs, req);
|
||||
JSONRPC2Error err = _helper.validateParams(requiredArgs, req);
|
||||
if (err != null) {
|
||||
return new JSONRPC2Response(err, req.getID());
|
||||
}
|
||||
|
||||
if (_context == null) {
|
||||
return new JSONRPC2Response(new JSONRPC2Error(
|
||||
JSONRPC2Error.INTERNAL_ERROR.getCode(),
|
||||
"RouterContext was not initialized. Query failed"),
|
||||
req.getID());
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
HashMap inParams = (HashMap) req.getParams();
|
||||
Map outParams = new HashMap();
|
||||
|
@ -31,7 +31,15 @@ import java.util.Map;
|
||||
|
||||
public class AuthenticateHandler implements RequestHandler {
|
||||
|
||||
private String[] requiredArgs = {"Password", "API"};
|
||||
private static final String[] requiredArgs = {"Password", "API"};
|
||||
private final JSONRPC2Helper _helper;
|
||||
private final SecurityManager _secMan;
|
||||
|
||||
public AuthenticateHandler(JSONRPC2Helper helper, SecurityManager secMan) {
|
||||
_helper = helper;
|
||||
_secMan = secMan;
|
||||
}
|
||||
|
||||
// Reports the method names of the handled requests
|
||||
public String[] handledRequests() {
|
||||
return new String[] {"Authenticate"};
|
||||
@ -40,7 +48,7 @@ public class AuthenticateHandler implements RequestHandler {
|
||||
// Processes the requests
|
||||
public JSONRPC2Response process(JSONRPC2Request req, MessageContext ctx) {
|
||||
if (req.getMethod().equals("Authenticate")) {
|
||||
JSONRPC2Error err = JSONRPC2Helper.validateParams(requiredArgs, req, JSONRPC2Helper.USE_NO_AUTH);
|
||||
JSONRPC2Error err = _helper.validateParams(requiredArgs, req, JSONRPC2Helper.USE_NO_AUTH);
|
||||
if (err != null)
|
||||
return new JSONRPC2Response(err, req.getID());
|
||||
|
||||
@ -50,7 +58,7 @@ public class AuthenticateHandler implements RequestHandler {
|
||||
|
||||
// Try get an AuthToken
|
||||
|
||||
AuthToken token = SecurityManager.getInstance().validatePasswd(pwd);
|
||||
AuthToken token = _secMan.validatePasswd(pwd);
|
||||
if (token == null) {
|
||||
return new JSONRPC2Response(JSONRPC2ExtendedError.INVALID_PASSWORD, req.getID());
|
||||
}
|
||||
|
@ -11,7 +11,13 @@ import java.util.Map;
|
||||
|
||||
public class EchoHandler implements RequestHandler {
|
||||
|
||||
private String[] requiredArgs = {"Echo"};
|
||||
private static final String[] requiredArgs = {"Echo"};
|
||||
private final JSONRPC2Helper _helper;
|
||||
|
||||
public EchoHandler(JSONRPC2Helper helper) {
|
||||
_helper = helper;
|
||||
}
|
||||
|
||||
// Reports the method names of the handled requests
|
||||
public String[] handledRequests() {
|
||||
return new String[] {"Echo"};
|
||||
@ -20,7 +26,7 @@ public class EchoHandler implements RequestHandler {
|
||||
// Processes the requests
|
||||
public JSONRPC2Response process(JSONRPC2Request req, MessageContext ctx) {
|
||||
if (req.getMethod().equals("Echo")) {
|
||||
JSONRPC2Error err = JSONRPC2Helper.validateParams(requiredArgs, req);
|
||||
JSONRPC2Error err = _helper.validateParams(requiredArgs, req);
|
||||
if (err != null)
|
||||
return new JSONRPC2Response(err, req.getID());
|
||||
|
||||
|
@ -31,7 +31,13 @@ import java.util.Map;
|
||||
|
||||
public class GetRateHandler implements RequestHandler {
|
||||
|
||||
private String[] requiredArgs = {"Stat", "Period"};
|
||||
private static final String[] requiredArgs = {"Stat", "Period"};
|
||||
private final JSONRPC2Helper _helper;
|
||||
|
||||
public GetRateHandler(JSONRPC2Helper helper) {
|
||||
_helper = helper;
|
||||
}
|
||||
|
||||
// Reports the method names of the handled requests
|
||||
public String[] handledRequests() {
|
||||
return new String[] {"GetRate"};
|
||||
@ -40,7 +46,7 @@ public class GetRateHandler implements RequestHandler {
|
||||
// Processes the requests
|
||||
public JSONRPC2Response process(JSONRPC2Request req, MessageContext ctx) {
|
||||
if (req.getMethod().equals("GetRate")) {
|
||||
JSONRPC2Error err = JSONRPC2Helper.validateParams(requiredArgs, req);
|
||||
JSONRPC2Error err = _helper.validateParams(requiredArgs, req);
|
||||
if (err != null)
|
||||
return new JSONRPC2Response(err, req.getID());
|
||||
|
||||
|
@ -5,14 +5,13 @@ import com.thetransactioncompany.jsonrpc2.JSONRPC2Request;
|
||||
import com.thetransactioncompany.jsonrpc2.JSONRPC2Response;
|
||||
import com.thetransactioncompany.jsonrpc2.server.MessageContext;
|
||||
import com.thetransactioncompany.jsonrpc2.server.RequestHandler;
|
||||
|
||||
import net.i2p.I2PAppContext;
|
||||
import net.i2p.i2pcontrol.I2PControlController;
|
||||
import net.i2p.i2pcontrol.router.RouterManager;
|
||||
import net.i2p.i2pcontrol.security.SecurityManager;
|
||||
import net.i2p.i2pcontrol.servlets.configuration.ConfigurationManager;
|
||||
import net.i2p.router.RouterContext;
|
||||
import net.i2p.util.Log;
|
||||
import org.eclipse.jetty.server.ssl.SslSocketConnector;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
@ -37,20 +36,24 @@ import java.util.Map;
|
||||
*/
|
||||
|
||||
public class I2PControlHandler implements RequestHandler {
|
||||
|
||||
private static final int BW_BURST_PCT = 110;
|
||||
private static final int BW_BURST_TIME = 20;
|
||||
private static RouterContext _context;
|
||||
private static final Log _log = I2PAppContext.getGlobalContext().logManager().getLog(I2PControlHandler.class);
|
||||
private static final ConfigurationManager _conf = ConfigurationManager.getInstance();
|
||||
private final RouterContext _context;
|
||||
private final Log _log;
|
||||
//private final ConfigurationManager _conf;
|
||||
private final JSONRPC2Helper _helper;
|
||||
|
||||
static {
|
||||
try {
|
||||
_context = RouterManager.getRouterContext();
|
||||
} catch (Exception e) {
|
||||
_log.error("Unable to initialize RouterContext.", e);
|
||||
}
|
||||
public I2PControlHandler(RouterContext ctx, JSONRPC2Helper helper) {
|
||||
_helper = helper;
|
||||
_context = ctx;
|
||||
if (ctx != null)
|
||||
_log = ctx.logManager().getLog(I2PControlHandler.class);
|
||||
else
|
||||
_log = I2PAppContext.getGlobalContext().logManager().getLog(I2PControlHandler.class);
|
||||
}
|
||||
|
||||
|
||||
// Reports the method names of the handled requests
|
||||
public String[] handledRequests() {
|
||||
return new String[] {"I2PControl"};
|
||||
@ -59,7 +62,8 @@ public class I2PControlHandler implements RequestHandler {
|
||||
// Processes the requests
|
||||
public JSONRPC2Response process(JSONRPC2Request req, MessageContext ctx) {
|
||||
if (req.getMethod().equals("I2PControl")) {
|
||||
return process(req);
|
||||
//return process(req);
|
||||
return new JSONRPC2Response(JSONRPC2Error.METHOD_NOT_FOUND, req.getID());
|
||||
} else {
|
||||
// Method name not supported
|
||||
return new JSONRPC2Response(JSONRPC2Error.METHOD_NOT_FOUND, req.getID());
|
||||
@ -67,8 +71,9 @@ public class I2PControlHandler implements RequestHandler {
|
||||
}
|
||||
|
||||
|
||||
/****
|
||||
private JSONRPC2Response process(JSONRPC2Request req) {
|
||||
JSONRPC2Error err = JSONRPC2Helper.validateParams(null, req);
|
||||
JSONRPC2Error err = _helper.validateParams(null, req);
|
||||
if (err != null)
|
||||
return new JSONRPC2Response(err, req.getID());
|
||||
|
||||
@ -191,4 +196,5 @@ public class I2PControlHandler implements RequestHandler {
|
||||
outParams.put("RestartNeeded", restartNeeded);
|
||||
return new JSONRPC2Response(outParams, req.getID());
|
||||
}
|
||||
****/
|
||||
}
|
||||
|
@ -30,6 +30,12 @@ public class JSONRPC2Helper {
|
||||
public final static Boolean USE_NO_AUTH = false;
|
||||
public final static Boolean USE_AUTH = true;
|
||||
|
||||
private final SecurityManager _secMan;
|
||||
|
||||
public JSONRPC2Helper(SecurityManager secMan) {
|
||||
_secMan = secMan;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
@ -37,7 +43,7 @@ public class JSONRPC2Helper {
|
||||
* @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) {
|
||||
public JSONRPC2Error validateParams(String[] requiredArgs, JSONRPC2Request req, Boolean useAuth) {
|
||||
|
||||
// Error on unnamed parameters
|
||||
if (req.getParamsType() != JSONRPC2ParamsType.OBJECT) {
|
||||
@ -75,7 +81,7 @@ public class JSONRPC2Helper {
|
||||
* @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) {
|
||||
public JSONRPC2Error validateParams(String[] requiredArgs, JSONRPC2Request req) {
|
||||
return validateParams(requiredArgs, req, JSONRPC2Helper.USE_AUTH);
|
||||
}
|
||||
|
||||
@ -86,13 +92,13 @@ public class JSONRPC2Helper {
|
||||
* @param req - Parameters of incoming request
|
||||
* @return null if everything is fine, JSONRPC2Error for any corresponding error.
|
||||
*/
|
||||
private static JSONRPC2Error validateToken(HashMap params) {
|
||||
private JSONRPC2Error validateToken(HashMap params) {
|
||||
String tokenID = (String) params.get("Token");
|
||||
if (tokenID == null) {
|
||||
return JSONRPC2ExtendedError.NO_TOKEN;
|
||||
}
|
||||
try {
|
||||
SecurityManager.getInstance().verifyToken(tokenID);
|
||||
_secMan.verifyToken(tokenID);
|
||||
} catch (InvalidAuthTokenException e) {
|
||||
return JSONRPC2ExtendedError.INVALID_TOKEN;
|
||||
} catch (ExpiredAuthTokenException e) {
|
||||
|
@ -7,7 +7,6 @@ import com.thetransactioncompany.jsonrpc2.server.MessageContext;
|
||||
import com.thetransactioncompany.jsonrpc2.server.RequestHandler;
|
||||
|
||||
import net.i2p.I2PAppContext;
|
||||
import net.i2p.i2pcontrol.router.RouterManager;
|
||||
import net.i2p.router.Router;
|
||||
import net.i2p.router.RouterContext;
|
||||
import net.i2p.router.transport.FIFOBandwidthRefiller;
|
||||
@ -41,15 +40,12 @@ import java.util.Map;
|
||||
public class NetworkSettingHandler implements RequestHandler {
|
||||
private static final int BW_BURST_PCT = 110;
|
||||
private static final int BW_BURST_TIME = 20;
|
||||
private static RouterContext _context;
|
||||
private static final Log _log = I2PAppContext.getGlobalContext().logManager().getLog(NetworkSettingHandler.class);
|
||||
private final JSONRPC2Helper _helper;
|
||||
private final RouterContext _context;
|
||||
|
||||
static {
|
||||
try {
|
||||
_context = RouterManager.getRouterContext();
|
||||
} catch (Exception e) {
|
||||
_log.error("Unable to initialize RouterContext.", e);
|
||||
}
|
||||
public NetworkSettingHandler(RouterContext ctx, JSONRPC2Helper helper) {
|
||||
_helper = helper;
|
||||
_context = ctx;
|
||||
}
|
||||
|
||||
// Reports the method names of the handled requests
|
||||
@ -69,7 +65,7 @@ public class NetworkSettingHandler implements RequestHandler {
|
||||
|
||||
|
||||
private JSONRPC2Response process(JSONRPC2Request req) {
|
||||
JSONRPC2Error err = JSONRPC2Helper.validateParams(null, req);
|
||||
JSONRPC2Error err = _helper.validateParams(null, req);
|
||||
if (err != null)
|
||||
return new JSONRPC2Response(err, req.getID());
|
||||
|
||||
|
@ -5,9 +5,9 @@ import com.thetransactioncompany.jsonrpc2.JSONRPC2Request;
|
||||
import com.thetransactioncompany.jsonrpc2.JSONRPC2Response;
|
||||
import com.thetransactioncompany.jsonrpc2.server.MessageContext;
|
||||
import com.thetransactioncompany.jsonrpc2.server.RequestHandler;
|
||||
|
||||
import net.i2p.I2PAppContext;
|
||||
import net.i2p.data.router.RouterAddress;
|
||||
import net.i2p.i2pcontrol.router.RouterManager;
|
||||
import net.i2p.router.CommSystemFacade;
|
||||
import net.i2p.router.Router;
|
||||
import net.i2p.router.RouterContext;
|
||||
@ -15,7 +15,6 @@ import net.i2p.router.RouterVersion;
|
||||
import net.i2p.router.networkdb.kademlia.FloodfillNetworkDatabaseFacade;
|
||||
import net.i2p.router.transport.TransportUtil;
|
||||
import net.i2p.router.transport.ntcp.NTCPTransport;
|
||||
import net.i2p.util.Log;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
@ -38,17 +37,15 @@ import java.util.Map;
|
||||
*/
|
||||
|
||||
public class RouterInfoHandler implements RequestHandler {
|
||||
private static RouterContext _context;
|
||||
private static final Log _log = I2PAppContext.getGlobalContext().logManager().getLog(RouterInfoHandler.class);
|
||||
private final JSONRPC2Helper _helper;
|
||||
private final RouterContext _context;
|
||||
|
||||
static {
|
||||
try {
|
||||
_context = RouterManager.getRouterContext();
|
||||
} catch (Exception e) {
|
||||
_log.error("Unable to initialize RouterContext.", e);
|
||||
}
|
||||
public RouterInfoHandler(RouterContext ctx, JSONRPC2Helper helper) {
|
||||
_helper = helper;
|
||||
_context = ctx;
|
||||
}
|
||||
|
||||
|
||||
// Reports the method names of the handled requests
|
||||
public String[] handledRequests() {
|
||||
return new String[] { "RouterInfo" };
|
||||
@ -67,7 +64,7 @@ public class RouterInfoHandler implements RequestHandler {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private JSONRPC2Response process(JSONRPC2Request req) {
|
||||
JSONRPC2Error err = JSONRPC2Helper.validateParams(null, req);
|
||||
JSONRPC2Error err = _helper.validateParams(null, req);
|
||||
if (err != null)
|
||||
return new JSONRPC2Response(err, req.getID());
|
||||
|
||||
|
@ -5,6 +5,7 @@ import com.thetransactioncompany.jsonrpc2.JSONRPC2Request;
|
||||
import com.thetransactioncompany.jsonrpc2.JSONRPC2Response;
|
||||
import com.thetransactioncompany.jsonrpc2.server.MessageContext;
|
||||
import com.thetransactioncompany.jsonrpc2.server.RequestHandler;
|
||||
|
||||
import net.i2p.I2PAppContext;
|
||||
import net.i2p.app.ClientAppManager;
|
||||
import net.i2p.i2pcontrol.router.RouterManager;
|
||||
@ -14,6 +15,7 @@ import net.i2p.router.networkdb.reseed.ReseedChecker;
|
||||
import net.i2p.update.UpdateManager;
|
||||
import net.i2p.update.UpdateType;
|
||||
import net.i2p.util.Log;
|
||||
|
||||
import org.tanukisoftware.wrapper.WrapperManager;
|
||||
|
||||
import java.util.HashMap;
|
||||
@ -37,17 +39,15 @@ import java.util.Map;
|
||||
*/
|
||||
|
||||
public class RouterManagerHandler implements RequestHandler {
|
||||
private static RouterContext _context;
|
||||
private static final Log _log = I2PAppContext.getGlobalContext().logManager().getLog(RouterManagerHandler.class);
|
||||
private final JSONRPC2Helper _helper;
|
||||
private final RouterContext _context;
|
||||
|
||||
private final static int SHUTDOWN_WAIT = 1500;
|
||||
|
||||
static {
|
||||
try {
|
||||
_context = RouterManager.getRouterContext();
|
||||
} catch (Exception e) {
|
||||
_log.error("Unable to initialize RouterContext.", e);
|
||||
}
|
||||
|
||||
public RouterManagerHandler(RouterContext ctx, JSONRPC2Helper helper) {
|
||||
_helper = helper;
|
||||
_context = ctx;
|
||||
}
|
||||
|
||||
// Reports the method names of the handled requests
|
||||
@ -67,7 +67,7 @@ public class RouterManagerHandler implements RequestHandler {
|
||||
}
|
||||
|
||||
private JSONRPC2Response process(JSONRPC2Request req) {
|
||||
JSONRPC2Error err = JSONRPC2Helper.validateParams(null, req);
|
||||
JSONRPC2Error err = _helper.validateParams(null, req);
|
||||
if (err != null)
|
||||
return new JSONRPC2Response(err, req.getID());
|
||||
|
||||
|
Reference in New Issue
Block a user