001 //$HeadURL: svn+ssh://jwilden@svn.wald.intevation.org/deegree/base/branches/2.5_testing/src/org/deegree/security/owsrequestvalidator/PolicyDocument.java $ 002 /*---------------------------------------------------------------------------- 003 This file is part of deegree, http://deegree.org/ 004 Copyright (C) 2001-2009 by: 005 Department of Geography, University of Bonn 006 and 007 lat/lon GmbH 008 009 This library is free software; you can redistribute it and/or modify it under 010 the terms of the GNU Lesser General Public License as published by the Free 011 Software Foundation; either version 2.1 of the License, or (at your option) 012 any later version. 013 This library is distributed in the hope that it will be useful, but WITHOUT 014 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 015 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 016 details. 017 You should have received a copy of the GNU Lesser General Public License 018 along with this library; if not, write to the Free Software Foundation, Inc., 019 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 020 021 Contact information: 022 023 lat/lon GmbH 024 Aennchenstr. 19, 53177 Bonn 025 Germany 026 http://lat-lon.de/ 027 028 Department of Geography, University of Bonn 029 Prof. Dr. Klaus Greve 030 Postfach 1147, 53001 Bonn 031 Germany 032 http://www.geographie.uni-bonn.de/deegree/ 033 034 e-mail: info@deegree.org 035 ----------------------------------------------------------------------------*/ 036 package org.deegree.security.owsrequestvalidator; 037 038 import java.io.InputStreamReader; 039 import java.io.Reader; 040 import java.net.MalformedURLException; 041 import java.net.URL; 042 import java.util.ArrayList; 043 import java.util.List; 044 045 import org.deegree.framework.log.ILogger; 046 import org.deegree.framework.log.LoggerFactory; 047 import org.deegree.framework.util.StringTools; 048 import org.deegree.framework.xml.NamespaceContext; 049 import org.deegree.framework.xml.XMLParsingException; 050 import org.deegree.framework.xml.XMLTools; 051 import org.deegree.ogcbase.BaseURL; 052 import org.deegree.ogcbase.CommonNamespaces; 053 import org.deegree.security.SecurityConfigurationException; 054 import org.deegree.security.owsproxy.AuthentificationSettings; 055 import org.deegree.security.owsproxy.Condition; 056 import org.deegree.security.owsproxy.DefaultDBConnection; 057 import org.deegree.security.owsproxy.OperationParameter; 058 import org.deegree.security.owsproxy.RegistryConfig; 059 import org.deegree.security.owsproxy.Request; 060 import org.deegree.security.owsproxy.SecurityConfig; 061 import org.w3c.dom.Document; 062 import org.w3c.dom.Element; 063 import org.w3c.dom.Node; 064 065 /** 066 * 067 * @author <a href="mailto:poth@lat-lon.de">Andreas Poth </a> 068 * @author last edited by: $Author: mschneider $ 069 * 070 * @version $Revision: 18195 $, $Date: 2009-06-18 17:55:39 +0200 (Do, 18 Jun 2009) $ 071 */ 072 public class PolicyDocument { 073 074 private ILogger LOG = LoggerFactory.getLogger( PolicyDocument.class ); 075 076 private static final NamespaceContext nsContext = CommonNamespaces.getNamespaceContext(); 077 078 private Document doc = null; 079 080 private String service = null; 081 082 /** 083 * @param url 084 * @throws SecurityConfigurationException 085 */ 086 public PolicyDocument( URL url ) throws SecurityConfigurationException { 087 try { 088 Reader reader = new InputStreamReader( url.openStream() ); 089 doc = XMLTools.parse( reader ); 090 service = XMLTools.getRequiredAttrValue( "service", null, doc.getDocumentElement() ); 091 } catch ( Exception e ) { 092 LOG.logError( e.getMessage(), e ); 093 throw new SecurityConfigurationException( StringTools.stackTraceToString( e ) ); 094 } 095 } 096 097 /** 098 * @param doc 099 * document containing a policy document 100 * @throws SecurityConfigurationException 101 */ 102 public PolicyDocument( Document doc ) throws SecurityConfigurationException { 103 this.doc = doc; 104 try { 105 service = XMLTools.getRequiredAttrValue( "service", null, doc.getDocumentElement() ); 106 } catch ( XMLParsingException e ) { 107 LOG.logError( e.getMessage(), e ); 108 throw new SecurityConfigurationException( e.getMessage() ); 109 } 110 } 111 112 /** 113 * returns the <tt>Policy</tt> created from the encapsulated DOM abject. 114 * 115 * @return the <tt>Policy</tt> created from the encapsulated DOM abject. 116 * @throws SecurityConfigurationException 117 * @throws XMLParsingException 118 */ 119 public Policy getPolicy() 120 throws SecurityConfigurationException, XMLParsingException { 121 Condition general = getGeneralCondition(); 122 SecurityConfig sc = null; 123 String dgSecPrefix = CommonNamespaces.DGSEC_PREFIX; 124 List<Node> nl = XMLTools.getNodes( doc, "/" + dgSecPrefix + ":OWSPolicy/" + dgSecPrefix + ":Security", 125 nsContext ); 126 if ( nl.size() > 0 ) { 127 sc = getSecuityConfig(); 128 } 129 Request[] requests = getRequests(); 130 return new Policy( sc, general, requests ); 131 } 132 133 /** 134 * @return Returns the generalCondition. 135 */ 136 private Condition getGeneralCondition() 137 throws SecurityConfigurationException { 138 Condition condition = null; 139 OperationParameter[] op = new OperationParameter[4]; 140 String xpath = "/dgsec:OWSPolicy/dgsec:GeneralConditions/dgsec:Conditions/dgsec:Parameter[@name = 'getContentLength']"; 141 op[0] = getOperationParameter( "getContentLength", xpath ); 142 xpath = "/dgsec:OWSPolicy/dgsec:GeneralConditions/dgsec:Conditions/dgsec:Parameter[@name = 'postContentLength']"; 143 op[1] = getOperationParameter( "postContentLength", xpath ); 144 xpath = "/dgsec:OWSPolicy/dgsec:GeneralConditions/dgsec:Conditions/dgsec:Parameter[@name = 'httpHeader']"; 145 op[2] = getOperationParameter( "httpHeader", xpath ); 146 xpath = "/dgsec:OWSPolicy/dgsec:GeneralConditions/dgsec:Conditions/dgsec:Parameter[@name = 'requestMethod']"; 147 op[3] = getOperationParameter( "requestType", xpath ); 148 condition = new Condition( op ); 149 // } catch ( Exception e ) { 150 // LOG.logError( e.getMessage(), e ); 151 // throw new SecurityConfigurationException( StringTools.stackTraceToString( e ) ); 152 // } 153 return condition; 154 } 155 156 /** 157 * @return the secuityConfig. 158 */ 159 private SecurityConfig getSecuityConfig() 160 throws SecurityConfigurationException { 161 SecurityConfig securityConfig = null; 162 163 String xpath = null; 164 xpath = "/dgsec:OWSPolicy/dgsec:Security/dgsec:RegistryClass"; 165 166 try { 167 String regClass = XMLTools.getNodeAsString( doc, xpath, nsContext, "org.deegree.security.drm.SQLRegistry" ); 168 xpath = "/dgsec:OWSPolicy/dgsec:Security/dgsec:ReadWriteTimeout"; 169 String tmp = XMLTools.getNodeAsString( doc, xpath, nsContext, "300" ); 170 int readWriteTimeout = Integer.parseInt( tmp ); 171 RegistryConfig registryConfig = getRegistryConfig(); 172 AuthentificationSettings authSet = getAuthentificationSettings(); 173 securityConfig = new SecurityConfig( regClass, readWriteTimeout, registryConfig, authSet ); 174 175 } catch ( XMLParsingException e ) { 176 throw new SecurityConfigurationException( e.getMessage() ); 177 } 178 // 179 // } catch ( Exception e ) { 180 // LOG.logError( e.getMessage(), e ); 181 // throw new SecurityConfigurationException( StringTools.stackTraceToString( e ) ); 182 // } 183 184 return securityConfig; 185 } 186 187 /** 188 * returns the configuration of the used rights management registry 189 * 190 * @return the configuration of the used rights management registry 191 * @throws SecurityConfigurationException 192 */ 193 private RegistryConfig getRegistryConfig() 194 throws SecurityConfigurationException { 195 RegistryConfig registryConfig = null; 196 String xpath = "/dgsec:OWSPolicy/dgsec:Security/dgsec:RegistryConfig/dgjdbc:JDBCConnection/dgjdbc:Driver"; 197 198 try { 199 String driver = XMLTools.getNodeAsString( doc, xpath, nsContext, null ); 200 xpath = "/dgsec:OWSPolicy/dgsec:Security/dgsec:RegistryConfig/dgjdbc:JDBCConnection/dgjdbc:Url"; 201 String logon = XMLTools.getNodeAsString( doc, xpath, nsContext, null ); 202 xpath = "/dgsec:OWSPolicy/dgsec:Security/dgsec:RegistryConfig/dgjdbc:JDBCConnection/dgjdbc:User"; 203 String user = XMLTools.getNodeAsString( doc, xpath, nsContext, null ); 204 xpath = "/dgsec:OWSPolicy/dgsec:Security/dgsec:RegistryConfig/dgjdbc:JDBCConnection/dgjdbc:Password"; 205 String password = XMLTools.getNodeAsString( doc, xpath, nsContext, null ); 206 if ( driver != null && logon != null ) { 207 DefaultDBConnection con = new DefaultDBConnection( driver, logon, user, password ); 208 registryConfig = new RegistryConfig( con ); 209 } else if ( ( driver != null && logon == null ) || ( driver == null && logon != null ) ) { 210 throw new SecurityConfigurationException( Messages.getString( "PolicyDocument.DatabaseConnection" ) ); 211 } 212 } catch ( XMLParsingException e ) { 213 throw new SecurityConfigurationException( e.getMessage() ); 214 } 215 216 // } catch ( Exception e ) { 217 // LOG.logError( e.getMessage(), e ); 218 // throw new SecurityConfigurationException( StringTools.stackTraceToString( e ) ); 219 // } 220 return registryConfig; 221 } 222 223 /** 224 * returns the settings for accessing the authentification authority 225 * 226 * @return the settings for accessing the authentification authority 227 * @throws SecurityConfigurationException 228 */ 229 private AuthentificationSettings getAuthentificationSettings() 230 throws SecurityConfigurationException { 231 AuthentificationSettings authSet = null; 232 233 StringBuffer xpath = new StringBuffer( "/dgsec:OWSPolicy/dgsec:Security/" ); 234 xpath.append( "dgsec:AuthentificationSettings/dgsec:AuthentificationService" ); 235 xpath.append( "/dgsec:OnlineResource/@xlink:href" ); 236 try { 237 String onlineRes = XMLTools.getNodeAsString( doc, xpath.toString(), nsContext, null ); 238 if ( onlineRes != null ) { 239 BaseURL baseURL = new BaseURL( null, new URL( onlineRes ) ); 240 authSet = new AuthentificationSettings( baseURL ); 241 } 242 } catch ( XMLParsingException e ) { 243 throw new SecurityConfigurationException( e.getMessage() ); 244 } catch ( MalformedURLException e ) { 245 throw new SecurityConfigurationException( e.getMessage() ); 246 } 247 248 // } catch ( Exception e ) { 249 // LOG.logError( e.getMessage(), e ); 250 // throw new SecurityConfigurationException( StringTools.stackTraceToString( e ) ); 251 // } 252 253 return authSet; 254 } 255 256 /** 257 * @return returns the requests described by the policy document 258 */ 259 private Request[] getRequests() 260 throws SecurityConfigurationException { 261 Request[] requests = null; 262 // try { 263 List<Node> nl = null; 264 try { 265 nl = XMLTools.getNodes( doc, "/dgsec:OWSPolicy/dgsec:Requests/*", nsContext ); 266 } catch ( XMLParsingException e ) { 267 throw new SecurityConfigurationException( e.getMessage() ); 268 } 269 if ( nl != null ) { 270 requests = new Request[nl.size()]; 271 for ( int i = 0; i < requests.length; i++ ) { 272 requests[i] = getRequest( (Element) nl.get( i ) ); 273 } 274 } 275 // } catch ( Exception e ) { 276 // LOG.logError( e.getMessage(), e ); 277 // throw new SecurityConfigurationException( StringTools.stackTraceToString( e ) ); 278 // } 279 return requests; 280 } 281 282 /** 283 * returns the requests described by the passed <tt>Element</tt> 284 * 285 * @param element 286 * @return created <tt>Request</tt> 287 * @throws SecurityConfigurationException 288 */ 289 private Request getRequest( Element element ) 290 throws SecurityConfigurationException { 291 String name = element.getLocalName(); 292 Request request = null; 293 Condition preCon = null; 294 Condition postCon = null; 295 296 try { 297 boolean any = XMLTools.getNode( element, "./dgsec:PreConditions/dgsec:Any", nsContext ) != null; 298 if ( any ) { 299 preCon = new Condition( true ); 300 } else { 301 List<Node> nl = XMLTools.getNodes( element, "./dgsec:PreConditions/dgsec:Parameter", nsContext ); 302 OperationParameter[] op = new OperationParameter[nl.size()]; 303 for ( int i = 0; i < nl.size(); i++ ) { 304 op[i] = getOperationParameter( (Element) nl.get( i ) ); 305 } 306 preCon = new Condition( op ); 307 } 308 309 any = XMLTools.getNode( element, "./dgsec:PostConditions/dgsec:Any", nsContext ) != null; 310 if ( any ) { 311 postCon = new Condition( true ); 312 } else { 313 List<Node> nl = XMLTools.getNodes( element, "./dgsec:PostConditions/dgsec:Parameter", nsContext ); 314 OperationParameter[] op = new OperationParameter[nl.size()]; 315 for ( int i = 0; i < nl.size(); i++ ) { 316 op[i] = getOperationParameter( (Element) nl.get( i ) ); 317 } 318 postCon = new Condition( op ); 319 } 320 request = new Request( service, name, preCon, postCon ); 321 } catch ( XMLParsingException e ) { 322 LOG.logError( e.getMessage(), e ); 323 throw new SecurityConfigurationException( e.getMessage() ); 324 } 325 326 // } catch ( Exception e ) { 327 // LOG.logError( e.getMessage(), e ); 328 // throw new SecurityConfigurationException( StringTools.stackTraceToString( e ) ); 329 // } 330 331 return request; 332 } 333 334 /** 335 * creates an <tt>OperationParameter</tt> with the passed name from the also passed root 336 * XPath. A root XPath is an expression to the desired parameter node. 337 * 338 * @param name 339 * name of the OperationParameter 340 * @param xpathRoot 341 * @return the parameter 342 * @throws SecurityConfigurationException 343 */ 344 private OperationParameter getOperationParameter( String name, String xpathRoot ) 345 throws SecurityConfigurationException { 346 OperationParameter op = null; 347 // try { 348 try { 349 if ( XMLTools.getNodes( doc, xpathRoot, nsContext ).size() == 0 ) { 350 // return OperationParameter that denies any access 351 return new OperationParameter( name, false ); 352 } 353 // is parameter coupled to user specific rights 354 String tmp = XMLTools.getRequiredNodeAsString( doc, xpathRoot + "/@userCoupled", nsContext ).toLowerCase(); 355 boolean userCoupled = tmp.equals( "true" ) || tmp.equals( "1" ); 356 357 // is any? -> no restrictions 358 tmp = XMLTools.getNodeAsString( doc, xpathRoot + "/dgsec:Any", nsContext, "false" ); 359 boolean any = !tmp.equals( "false" ); 360 361 if ( !any ) { 362 // get values if not 'any' 363 List<Element> list = XMLTools.getElements( doc, xpathRoot + "/dgsec:Value", nsContext ); 364 List<String> valueList = null; 365 if ( list != null ) { 366 valueList = new ArrayList<String>( list.size() ); 367 for ( int j = 0; j < list.size(); j++ ) { 368 valueList.add( XMLTools.getStringValue( list.get( j ) ) ); 369 } 370 } 371 list = XMLTools.getElements( doc, xpathRoot + "/dgsec:ComplexValue/*", nsContext ); 372 op = new OperationParameter( name, valueList, list, userCoupled ); 373 } else { 374 op = new OperationParameter( name, any ); 375 } 376 } catch ( XMLParsingException e ) { 377 LOG.logError( e.getMessage(), e ); 378 throw new SecurityConfigurationException( e.getMessage() ); 379 } 380 381 // } catch ( Exception e ) { 382 // LOG.logError( e.getMessage(), e ); 383 // throw new SecurityConfigurationException( StringTools.stackTraceToString( e ) ); 384 // } 385 return op; 386 } 387 388 /** 389 * creates an <tt>OperationParameter</tt> from the passed element. 390 * 391 * @param element 392 * encapsulating a parameter 393 * @return created <tt>OperationParameter</tt> 394 * @throws XMLParsingException 395 */ 396 private OperationParameter getOperationParameter( Element element ) 397 throws XMLParsingException { 398 OperationParameter op = null; 399 String name = XMLTools.getRequiredAttrValue( "name", null, element ); 400 String uc = XMLTools.getAttrValue( element, null, "userCoupled", "false" ); 401 boolean userCoupled = uc.equals( "true" ) || uc.equals( "1" ); 402 boolean any = XMLTools.getNode( element, "dgsec:Any", nsContext ) != null; 403 if ( !any ) { 404 List<Element> list = XMLTools.getElements( element, "dgsec:Value", nsContext ); 405 List<String> valueList = null; 406 if ( list != null ) { 407 valueList = new ArrayList<String>( list.size() ); 408 for ( int j = 0; j < list.size(); j++ ) { 409 valueList.add( XMLTools.getStringValue( list.get( j ) ) ); 410 } 411 } 412 list = XMLTools.getElements( element, "dgsec:ComplexValue/*", nsContext ); 413 op = new OperationParameter( name, valueList, list, userCoupled ); 414 } else { 415 op = new OperationParameter( name, any ); 416 } 417 418 return op; 419 } 420 421 }