blob: 9b32bfb5c9e43cf8425be6b26f8332c929aed5ab [file] [log] [blame]
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml" lang="en"><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/><link rel="stylesheet" href="../jacoco-resources/report.css" type="text/css"/><link rel="shortcut icon" href="../jacoco-resources/report.gif" type="image/gif"/><title>AuthenticatedService.java</title><link rel="stylesheet" href="../jacoco-resources/prettify.css" type="text/css"/><script type="text/javascript" src="../jacoco-resources/prettify.js"></script></head><body onload="window['PR_TAB_WIDTH']=4;prettyPrint()"><div class="breadcrumb" id="breadcrumb"><span class="info"><a href="../jacoco-sessions.html" class="el_session">Sessions</a></span><a href="../index.html" class="el_report">jUDDI Core Services</a> &gt; <a href="index.source.html" class="el_package">org.apache.juddi.api.impl</a> &gt; <span class="el_source">AuthenticatedService.java</span></div><h1>AuthenticatedService.java</h1><pre class="source lang-java linenums">/*
* Copyright 2001-2008 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
* 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 &quot;AS IS&quot; 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.
*
*/
package org.apache.juddi.api.impl;
import java.util.Date;
import javax.annotation.Resource;
import javax.persistence.EntityManager;
import javax.servlet.http.HttpServletRequest;
import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.ws.WebServiceContext;
import javax.xml.ws.handler.MessageContext;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.juddi.config.AppConfig;
import org.apache.juddi.config.Property;
import org.apache.juddi.model.UddiEntityPublisher;
import org.apache.juddi.v3.auth.Authenticator;
import org.apache.juddi.v3.auth.AuthenticatorFactory;
import org.apache.juddi.v3.error.AuthTokenRequiredException;
import org.apache.juddi.v3.error.AuthTokenExpiredException;
import org.apache.juddi.v3.error.ErrorMessage;
import org.uddi.v3_service.DispositionReportFaultMessage;
/**
* Although this class is abstract, it provides token validation
*
* @author &lt;a href=&quot;mailto:jfaath@apache.org&quot;&gt;Jeff Faath&lt;/a&gt;
*
* @author &lt;a href=&quot;mailto:alexoree@apache.org&quot;&gt;Alex O'Ree&lt;/a&gt; - modified to
* include token expiration validation
*/
public abstract class AuthenticatedService {
/**
* @return the node
*/
public String getNode() {
<span class="fc" id="L56"> return node;</span>
}
public static final String UTF8 = &quot;UTF-8&quot;;
public static final int AUTHTOKEN_ACTIVE = 1;
public static final int AUTHTOKEN_RETIRED = 0;
<span class="fc" id="L62"> static final Log logger = LogFactory.getLog(AuthenticatedService.class);</span>
/**
* the node id of this server instance, as loaded from the config file
*/
<span class="fc" id="L66"> private String node = &quot;UNDEFINED_NODE_NAME&quot;;</span>
<span class="fc" id="L67"> protected String baseUrlSSL = &quot;UNDEFINED&quot;;</span>
<span class="fc" id="L68"> protected String baseUrl = &quot;UNDEFINED&quot;;</span>
<span class="fc" id="L69"> protected DatatypeFactory df = null;</span>
<span class="fc" id="L71"> public AuthenticatedService() {</span>
try {
<span class="fc" id="L73"> node = AppConfig.getConfiguration().getString(Property.JUDDI_NODE_ID, &quot;UNDEFINED_NODE_NAME&quot;);</span>
<span class="fc" id="L74"> node = node.trim();</span>
<span class="fc" id="L75"> baseUrlSSL = AppConfig.getConfiguration().getString(Property.JUDDI_BASE_URL_SECURE, Property.DEFAULT_BASE_URL_SECURE);</span>
<span class="fc" id="L76"> baseUrlSSL = baseUrlSSL.trim();</span>
<span class="nc" id="L77"> } catch (ConfigurationException ex) {</span>
<span class="nc" id="L78"> logger.fatal(null, ex);</span>
<span class="fc" id="L79"> }</span>
<span class="fc" id="L80"> init();</span>
<span class="fc" id="L81"> }</span>
/**
* this method can be used to explicitly set a request context. this is useful
* in unit tests, embedded and in-vm scenarios only
* @param ctx
* @since 3.3.8
*/
public void setContext(WebServiceContext ctx) {
<span class="nc" id="L90"> this.ctx = ctx;</span>
<span class="nc" id="L91"> }</span>
private synchronized void init() {
try {
<span class="fc" id="L95"> df = DatatypeFactory.newInstance();</span>
<span class="nc" id="L96"> } catch (DatatypeConfigurationException ex) {</span>
<span class="nc" id="L97"> logger.fatal(null, ex);</span>
<span class="fc" id="L98"> }</span>
<span class="fc" id="L99"> }</span>
@Resource
protected WebServiceContext ctx;
public UddiEntityPublisher getEntityPublisher(EntityManager em, String authInfo) throws DispositionReportFaultMessage {
<span class="fc" id="L105"> boolean useAuthInfo = true;</span>
try {
<span class="fc" id="L107"> useAuthInfo = AppConfig.getConfiguration().getBoolean(Property.JUDDI_AUTHENTICATOR_USE_TOKEN, true);</span>
<span class="nc" id="L108"> } catch (ConfigurationException ex) {</span>
<span class="fc" id="L110"> }</span>
<span class="pc bpc" id="L111" title="1 of 2 branches missed."> if (useAuthInfo) {</span>
<span class="pc bpc" id="L113" title="1 of 4 branches missed."> if (authInfo == null || authInfo.length() == 0) {</span>
<span class="fc" id="L114"> throw new AuthTokenRequiredException(new ErrorMessage(&quot;errors.auth.AuthRequired&quot;));</span>
}
<span class="fc" id="L117"> org.apache.juddi.model.AuthToken modelAuthToken = em.find(org.apache.juddi.model.AuthToken.class, authInfo);</span>
<span class="pc bpc" id="L118" title="1 of 2 branches missed."> if (modelAuthToken == null) {</span>
<span class="nc" id="L119"> throw new AuthTokenRequiredException(new ErrorMessage(&quot;errors.auth.AuthInvalid&quot;));</span>
}
<span class="fc" id="L122"> int allowedMinutesOfInactivity = 0;</span>
try {
<span class="fc" id="L124"> allowedMinutesOfInactivity = AppConfig.getConfiguration().getInt(Property.JUDDI_AUTH_TOKEN_TIMEOUT, 0);</span>
<span class="nc" id="L125"> } catch (ConfigurationException ce) {</span>
<span class="nc" id="L126"> logger.error(&quot;Error reading property &quot; + Property.JUDDI_AUTH_TOKEN_EXPIRATION + &quot; from &quot;</span>
+ &quot;the application's configuration. No automatic timeout token invalidation will occur. &quot;
<span class="nc" id="L128"> + ce.getMessage(), ce);</span>
<span class="fc" id="L129"> }</span>
<span class="fc" id="L130"> int maxMinutesOfAge = 0;</span>
try {
<span class="fc" id="L132"> maxMinutesOfAge = AppConfig.getConfiguration().getInt(Property.JUDDI_AUTH_TOKEN_EXPIRATION, 0);</span>
<span class="nc" id="L133"> } catch (ConfigurationException ce) {</span>
<span class="nc" id="L134"> logger.error(&quot;Error reading property &quot; + Property.JUDDI_AUTH_TOKEN_EXPIRATION + &quot; from &quot;</span>
+ &quot;the application's configuration. No automatic timeout token invalidation will occur. &quot;
<span class="nc" id="L136"> + ce.getMessage(), ce);</span>
<span class="fc" id="L137"> }</span>
<span class="fc" id="L138"> Date now = new Date();</span>
// 0 or negative means token does not expire
<span class="pc bpc" id="L140" title="1 of 2 branches missed."> if (allowedMinutesOfInactivity &gt; 0) {</span>
// expire tokens after # minutes of inactivity
// compare the time in milli-seconds
<span class="pc bpc" id="L143" title="1 of 2 branches missed."> if (now.getTime() &gt; modelAuthToken.getLastUsed().getTime() + allowedMinutesOfInactivity * 60000l) {</span>
<span class="nc" id="L144"> logger.info(&quot;AUDIT: FAILTURE Token &quot; + modelAuthToken.getAuthToken() + &quot; expired due to inactivity &quot; + getRequestorsIPAddress());</span>
<span class="nc" id="L145"> modelAuthToken.setTokenState(AUTHTOKEN_RETIRED);</span>
}
}
<span class="pc bpc" id="L148" title="1 of 2 branches missed."> if (maxMinutesOfAge &gt; 0) {</span>
// expire tokens when max age is reached
// compare the time in milli-seconds
<span class="pc bpc" id="L151" title="1 of 2 branches missed."> if (now.getTime() &gt; modelAuthToken.getCreated().getTime() + maxMinutesOfAge * 60000l) {</span>
<span class="nc" id="L153"> logger.info(&quot;AUDIT: FAILURE - Token &quot; + modelAuthToken.getAuthorizedName() + &quot; expired due to old age &quot; + getRequestorsIPAddress());</span>
<span class="nc" id="L154"> modelAuthToken.setTokenState(AUTHTOKEN_RETIRED);</span>
}
}
<span class="pc bpc" id="L158" title="1 of 2 branches missed."> if (modelAuthToken.getTokenState() == AUTHTOKEN_RETIRED) {</span>
<span class="nc" id="L160"> throw new AuthTokenExpiredException(new ErrorMessage(&quot;errors.auth.AuthTokenExpired&quot;));</span>
}
<span class="fc bfc" id="L162" title="All 2 branches covered."> if (ctx != null) {</span>
try {
<span class="fc" id="L164"> boolean check = true;</span>
try {
<span class="fc" id="L166"> check = AppConfig.getConfiguration().getBoolean(Property.JUDDI_AUTH_TOKEN_ENFORCE_SAME_IP, true);</span>
<span class="nc" id="L167"> } catch (ConfigurationException ex) {</span>
<span class="nc" id="L168"> logger.warn(&quot;Error loading config property &quot; + Property.JUDDI_AUTH_TOKEN_ENFORCE_SAME_IP</span>
+ &quot; Enforcing Same IP for Auth Tokens will be enabled by default&quot;, ex);
<span class="fc" id="L170"> }</span>
<span class="pc bpc" id="L171" title="1 of 2 branches missed."> if (check) {</span>
<span class="fc" id="L172"> MessageContext mc = ctx.getMessageContext();</span>
<span class="fc" id="L173"> HttpServletRequest req = null;</span>
<span class="pc bpc" id="L174" title="1 of 2 branches missed."> if (mc != null) {</span>
<span class="fc" id="L175"> req = (HttpServletRequest) mc.get(MessageContext.SERVLET_REQUEST);</span>
}
<span class="pc bpc" id="L177" title="1 of 2 branches missed."> if (req != null</span>
<span class="fc bfc" id="L178" title="All 2 branches covered."> &amp;&amp; req.getRemoteAddr() != null</span>
<span class="fc bfc" id="L179" title="All 2 branches covered."> &amp;&amp; modelAuthToken.getIPAddress() != null</span>
<span class="fc bfc" id="L180" title="All 2 branches covered."> &amp;&amp; !modelAuthToken.getIPAddress().equalsIgnoreCase(req.getRemoteAddr())) {</span>
<span class="fc" id="L181"> modelAuthToken.setTokenState(AUTHTOKEN_RETIRED);</span>
<span class="fc" id="L182"> logger.error(&quot;AUDIT FAILURE - Security Alert - Attempt to use issued auth token from a different IP address, user &quot;</span>
<span class="fc" id="L183"> + modelAuthToken.getAuthorizedName() + &quot;, issued IP &quot; + modelAuthToken.getIPAddress()</span>
<span class="fc" id="L184"> + &quot;, attempted use from &quot; + req.getRemoteAddr() + &quot;, forcing reauthentication.&quot;);</span>
<span class="fc" id="L185"> throw new AuthTokenRequiredException(new ErrorMessage(&quot;errors.auth.AuthInvalid&quot;));</span>
//invalidate the token, someone's intercepted it or it was reused on another ip
}
}
<span class="fc" id="L189"> } catch (Exception ex) {</span>
<span class="pc bpc" id="L190" title="1 of 2 branches missed."> if (ex instanceof AuthTokenRequiredException) {</span>
<span class="fc" id="L191"> throw (AuthTokenRequiredException) ex;</span>
}
<span class="nc" id="L193"> logger.error(&quot;unexpected error caught looking up requestor's ip address&quot;, ex);</span>
<span class="fc" id="L194"> }</span>
}
<span class="fc" id="L197"> Authenticator authenticator = AuthenticatorFactory.getAuthenticator();</span>
<span class="fc" id="L198"> UddiEntityPublisher entityPublisher = authenticator.identify(authInfo, modelAuthToken.getAuthorizedName(), ctx);</span>
// Must make sure the returned publisher has all the necessary fields filled
<span class="pc bpc" id="L201" title="1 of 2 branches missed."> if (entityPublisher == null) {</span>
<span class="nc" id="L202"> logger.warn(&quot;AUDIT FAILURE - Auth token invalid, publisher does not exist &quot; + getRequestorsIPAddress());</span>
<span class="nc" id="L203"> throw new AuthTokenRequiredException(new ErrorMessage(&quot;errors.auth.AuthInvalid&quot;));</span>
}
<span class="pc bpc" id="L205" title="1 of 2 branches missed."> if (entityPublisher.getAuthorizedName() == null) {</span>
<span class="nc" id="L206"> logger.warn(&quot;AUDIT FAILURE - Auth token invalid, username does exist&quot; + getRequestorsIPAddress());</span>
<span class="nc" id="L207"> throw new AuthTokenRequiredException(new ErrorMessage(&quot;errors.auth.AuthInvalid&quot;));</span>
}
// Auth token is being used. Adjust appropriate values so that it's internal 'expiration clock' is reset.
<span class="fc" id="L210"> modelAuthToken.setLastUsed(new Date());</span>
<span class="fc" id="L211"> modelAuthToken.setNumberOfUses(modelAuthToken.getNumberOfUses() + 1);</span>
<span class="fc" id="L212"> return entityPublisher;</span>
} else {
//use non-token based authentication
<span class="nc" id="L215"> Authenticator authenticator = AuthenticatorFactory.getAuthenticator();</span>
<span class="nc" id="L216"> UddiEntityPublisher entityPublisher = authenticator.identify(null, null, ctx);</span>
// Must make sure the returned publisher has all the necessary fields filled
<span class="nc bnc" id="L218" title="All 2 branches missed."> if (entityPublisher == null) {</span>
<span class="nc" id="L219"> logger.warn(&quot;AUDIT FAILURE - Auth token invalid, publisher does not exist &quot; + getRequestorsIPAddress());</span>
<span class="nc" id="L220"> throw new AuthTokenRequiredException(new ErrorMessage(&quot;errors.auth.AuthInvalid&quot;));</span>
}
<span class="nc bnc" id="L222" title="All 2 branches missed."> if (entityPublisher.getAuthorizedName() == null) {</span>
<span class="nc" id="L223"> logger.warn(&quot;AUDIT FAILURE - Auth token invalid, username does exist&quot; + getRequestorsIPAddress());</span>
<span class="nc" id="L224"> throw new AuthTokenRequiredException(new ErrorMessage(&quot;errors.auth.AuthInvalid&quot;));</span>
}
<span class="nc" id="L226"> return entityPublisher;</span>
}
}
/**
* Attempts to get the requestor's ip address from the servlet context,
* defaults to null it it can't be retrieved
*
* @return requestor's ip address or null if it's not available
*/
public String getRequestorsIPAddress() {
try {
<span class="fc" id="L240"> MessageContext mc = ctx.getMessageContext();</span>
<span class="fc" id="L241"> HttpServletRequest req = null;</span>
<span class="pc bpc" id="L242" title="1 of 2 branches missed."> if (mc != null) {</span>
<span class="fc" id="L243"> req = (HttpServletRequest) mc.get(MessageContext.SERVLET_REQUEST);</span>
}
<span class="pc bpc" id="L245" title="1 of 2 branches missed."> if (req != null) {</span>
<span class="fc" id="L246"> return req.getRemoteAddr();</span>
}
<span class="fc" id="L248"> } catch (Exception ex) {</span>
<span class="fc" id="L249"> logger.debug(&quot;Error caught looking up the requestor's ip address&quot;, ex);</span>
<span class="nc" id="L250"> }</span>
<span class="fc" id="L251"> return null;</span>
}
}
</pre><div class="footer"><span class="right">Created with <a href="http://www.jacoco.org/jacoco">JaCoCo</a> 0.7.9.201702052155</span></div></body></html>