001    //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.3_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    }