5656import java .nio .file .Files ;
5757import java .nio .file .Path ;
5858import java .nio .file .Paths ;
59+ import java .nio .file .attribute .PosixFileAttributes ;
60+ import java .nio .file .attribute .PosixFilePermission ;
61+ import java .nio .file .attribute .PosixFilePermissions ;
5962import java .util .HashSet ;
6063import java .util .Properties ;
6164import java .util .Set ;
@@ -116,7 +119,7 @@ public class JMXServlet extends HttpServlet {
116119 }
117120
118121 private JMXtoXML client ;
119- private final Set <String > localhostAddresses = new HashSet <>();
122+ private final Set <String > serverAddresses = new HashSet <>();
120123
121124 private Path dataDir ;
122125 private Path tokenFile ;
@@ -128,11 +131,15 @@ protected void doGet(HttpServletRequest request, HttpServletResponse response) t
128131 // Verify if request is from localhost or if user has specific servlet/container managed role.
129132 if (isFromLocalHost (request )) {
130133 // Localhost is always authorized to access
131- LOG .debug ("Local access granted" );
134+ if (LOG .isDebugEnabled ()) {
135+ LOG .debug ("Local access granted" );
136+ }
132137
133138 } else if (hasSecretToken (request , getToken ())) {
134139 // Correct token is provided
135- LOG .debug ("Correct token provided by {}" , request .getRemoteHost ());
140+ if (LOG .isDebugEnabled ()) {
141+ LOG .debug ("Correct token provided by {}" , request .getRemoteHost ());
142+ }
136143
137144 } else {
138145 // Check if user is already authorized, e.g. via MONEX allow user too
@@ -218,7 +225,7 @@ public void init(ServletConfig config) throws ServletException {
218225 client .connect ();
219226
220227 // Register all known localhost addresses
221- registerLocalHostAddresses ();
228+ registerServerAddresses ();
222229
223230 // Get directory for token file
224231 final String jmxDataDir = client .getDataDir ();
@@ -232,34 +239,47 @@ public void init(ServletConfig config) throws ServletException {
232239 }
233240
234241 // Setup token and tokenfile
235- obtainTokenFileReference ();
236-
237- LOG .info ("JMXservlet token: {}" , getToken ());
242+ if (tokenFile == null ) {
243+ tokenFile = dataDir .resolve (TOKEN_FILE );
244+ LOG .info ("Token file: {}" , tokenFile .toAbsolutePath ().toAbsolutePath ());
245+ }
238246
247+ // NOTE(AR) make sure to create the token in init when the servlet is loaded at startup so that it is present for Monex
248+ final String token = getToken ();
249+ LOG .info ("JMXServlet token: {}" , token );
239250 }
240251
241252 /**
242- * Register all known IP-addresses for localhost .
253+ * Register all known IP-addresses for server .
243254 */
244- void registerLocalHostAddresses () {
245- // The external IP address of the server
255+ void registerServerAddresses () {
256+ // The IPv4 address of the loopback interface of the server - 127.0.0.1 on Windows/Linux/macOS, or 127.0.1.1 on Debian/Ubuntu
257+ try {
258+ serverAddresses .add (InetAddress .getLocalHost ().getHostAddress ());
259+ } catch (final UnknownHostException ex ) {
260+ LOG .warn ("Unable to get loopback IP address for localhost: {}" , ex .getMessage ());
261+ }
262+
263+ // Any additional IPv4 and IPv6 addresses associated with the loopback interface of the server
246264 try {
247- localhostAddresses .add (InetAddress .getLocalHost ().getHostAddress ());
248- } catch (UnknownHostException ex ) {
249- LOG .warn ("Unable to get HostAddress for localhost: {}" , ex .getMessage ());
265+ for (final InetAddress loopBackAddress : InetAddress .getAllByName ("localhost" )) {
266+ serverAddresses .add (loopBackAddress .getHostAddress ());
267+ }
268+ } catch (final UnknownHostException ex ) {
269+ LOG .warn ("Unable to retrieve additional loopback IP addresses for localhost: {}" , ex .getMessage ());
250270 }
251271
252- // The configured Localhost addresses
272+ // Any IPv4 and IPv6 addresses associated with other interfaces in the server
253273 try {
254- for (InetAddress address : InetAddress .getAllByName ("localhost" )) {
255- localhostAddresses .add (address .getHostAddress ());
274+ for (final InetAddress hostAddress : InetAddress .getAllByName (InetAddress . getLocalHost (). getHostName () )) {
275+ serverAddresses .add (hostAddress .getHostAddress ());
256276 }
257- } catch (UnknownHostException ex ) {
258- LOG .warn ("Unable to retrieve ipaddresses for localhost: {}" , ex .getMessage ());
277+ } catch (final UnknownHostException ex ) {
278+ LOG .warn ("Unable to retrieve additional interface IP addresses for localhost: {}" , ex .getMessage ());
259279 }
260280
261- if (localhostAddresses .isEmpty ()) {
262- LOG .error ("Unable to determine addresses for localhost, jmx servlet might be disfunctional ." );
281+ if (serverAddresses .isEmpty ()) {
282+ LOG .error ("Unable to determine IP addresses for localhost, JMXServlet might be dysfunctional ." );
263283 }
264284 }
265285
@@ -269,8 +289,13 @@ void registerLocalHostAddresses() {
269289 * @param request The HTTP request
270290 * @return TRUE if request is from LOCALHOST otherwise FALSE
271291 */
272- boolean isFromLocalHost (HttpServletRequest request ) {
273- return localhostAddresses .contains (request .getRemoteAddr ());
292+ boolean isFromLocalHost (final HttpServletRequest request ) {
293+ String remoteAddr = request .getRemoteAddr ();
294+ if (remoteAddr .charAt (0 ) == '[' ) {
295+ // Handle IPv6 addresses that are wrapped in []
296+ remoteAddr = remoteAddr .substring (1 , remoteAddr .length () - 1 );
297+ }
298+ return serverAddresses .contains (remoteAddr );
274299 }
275300
276301 /**
@@ -291,17 +316,6 @@ boolean hasSecretToken(HttpServletRequest request, String token) {
291316 return false ;
292317 }
293318
294- /**
295- * Obtain reference to token file
296- */
297- private void obtainTokenFileReference () {
298-
299- if (tokenFile == null ) {
300- tokenFile = dataDir .resolve (TOKEN_FILE );
301- LOG .info ("Token file: {}" , tokenFile .toAbsolutePath ().toAbsolutePath ());
302- }
303- }
304-
305319 /**
306320 * Get token from file, create if not existent. Data is read for each call so the file can be updated run-time.
307321 *
@@ -327,6 +341,13 @@ private String getToken() {
327341 // Create and write when needed
328342 if (!Files .exists (tokenFile ) || token == null ) {
329343
344+ final Set <PosixFilePermission > permissions = PosixFilePermissions .fromString ("rw-r-----" );
345+ try {
346+ tokenFile = Files .createFile (tokenFile , PosixFilePermissions .asFileAttribute (permissions ));
347+ } catch (final Throwable t ) {
348+ LOG .warn ("Unable to restrict permissions on: " + tokenFile );
349+ }
350+
330351 // Create random token
331352 token = UUIDGenerator .getUUIDversion4 ();
332353
0 commit comments