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