001    //$HeadURL: http://svn.wald.intevation.org/svn/deegree/base/trunk/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: aschmitz $
069     * 
070     * @version $Revision: 31356 $, $Date: 2011-07-26 09:19:13 +0200 (Di, 26 Jul 2011) $
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        public List<String> getWhitelist()
113                                throws SecurityConfigurationException {
114            try {
115                List<String> list = XMLTools.getNodesAsStringList( doc,
116                                                                   "/dgsec:OWSPolicy/dgsec:Whitelist/dgsec:PassedParameter",
117                                                                   nsContext );
118                return list;
119            } catch ( XMLParsingException e ) {
120                LOG.logError( e.getMessage(), e );
121                throw new SecurityConfigurationException( e.getMessage() );
122            }
123        }
124    
125        /**
126         * returns the <tt>Policy</tt> created from the encapsulated DOM abject.
127         * 
128         * @return the <tt>Policy</tt> created from the encapsulated DOM abject.
129         * @throws SecurityConfigurationException
130         * @throws XMLParsingException
131         */
132        public Policy getPolicy()
133                                throws SecurityConfigurationException, XMLParsingException {
134            Condition general = getGeneralCondition();
135            SecurityConfig sc = null;
136            String dgSecPrefix = CommonNamespaces.DGSEC_PREFIX;
137            List<Node> nl = XMLTools.getNodes( doc, "/" + dgSecPrefix + ":OWSPolicy/" + dgSecPrefix + ":Security",
138                                               nsContext );
139            if ( nl.size() > 0 ) {
140                sc = getSecuityConfig();
141            }
142            Request[] requests = getRequests();
143            List<String> whitelist = getWhitelist();
144            return new Policy( sc, general, requests, whitelist );
145        }
146    
147        /**
148         * @return Returns the generalCondition.
149         */
150        private Condition getGeneralCondition()
151                                throws SecurityConfigurationException {
152            Condition condition = null;
153            OperationParameter[] op = new OperationParameter[4];
154            String xpath = "/dgsec:OWSPolicy/dgsec:GeneralConditions/dgsec:Conditions/dgsec:Parameter[@name = 'getContentLength']";
155            op[0] = getOperationParameter( "getContentLength", xpath );
156            xpath = "/dgsec:OWSPolicy/dgsec:GeneralConditions/dgsec:Conditions/dgsec:Parameter[@name = 'postContentLength']";
157            op[1] = getOperationParameter( "postContentLength", xpath );
158            xpath = "/dgsec:OWSPolicy/dgsec:GeneralConditions/dgsec:Conditions/dgsec:Parameter[@name = 'httpHeader']";
159            op[2] = getOperationParameter( "httpHeader", xpath );
160            xpath = "/dgsec:OWSPolicy/dgsec:GeneralConditions/dgsec:Conditions/dgsec:Parameter[@name = 'requestMethod']";
161            op[3] = getOperationParameter( "requestType", xpath );
162            condition = new Condition( op );
163            // } catch ( Exception e ) {
164            // LOG.logError( e.getMessage(), e );
165            // throw new SecurityConfigurationException( StringTools.stackTraceToString( e ) );
166            // }
167            return condition;
168        }
169    
170        /**
171         * @return the secuityConfig.
172         */
173        private SecurityConfig getSecuityConfig()
174                                throws SecurityConfigurationException {
175            SecurityConfig securityConfig = null;
176    
177            String xpath = null;
178            xpath = "/dgsec:OWSPolicy/dgsec:Security/dgsec:RegistryClass";
179    
180            try {
181                String regClass = XMLTools.getNodeAsString( doc, xpath, nsContext, "org.deegree.security.drm.SQLRegistry" );
182                xpath = "/dgsec:OWSPolicy/dgsec:Security/dgsec:ReadWriteTimeout";
183                String tmp = XMLTools.getNodeAsString( doc, xpath, nsContext, "300" );
184                int readWriteTimeout = Integer.parseInt( tmp );
185                RegistryConfig registryConfig = getRegistryConfig();
186                AuthentificationSettings authSet = getAuthentificationSettings();
187                securityConfig = new SecurityConfig( regClass, readWriteTimeout, registryConfig, authSet );
188    
189            } catch ( XMLParsingException e ) {
190                throw new SecurityConfigurationException( e.getMessage() );
191            }
192            //
193            // } catch ( Exception e ) {
194            // LOG.logError( e.getMessage(), e );
195            // throw new SecurityConfigurationException( StringTools.stackTraceToString( e ) );
196            // }
197    
198            return securityConfig;
199        }
200    
201        /**
202         * returns the configuration of the used rights management registry
203         * 
204         * @return the configuration of the used rights management registry
205         * @throws SecurityConfigurationException
206         */
207        private RegistryConfig getRegistryConfig()
208                                throws SecurityConfigurationException {
209            RegistryConfig registryConfig = null;
210            String xpath = "/dgsec:OWSPolicy/dgsec:Security/dgsec:RegistryConfig/dgjdbc:JDBCConnection/dgjdbc:Driver";
211    
212            try {
213                String driver = XMLTools.getNodeAsString( doc, xpath, nsContext, null );
214                xpath = "/dgsec:OWSPolicy/dgsec:Security/dgsec:RegistryConfig/dgjdbc:JDBCConnection/dgjdbc:Url";
215                String logon = XMLTools.getNodeAsString( doc, xpath, nsContext, null );
216                xpath = "/dgsec:OWSPolicy/dgsec:Security/dgsec:RegistryConfig/dgjdbc:JDBCConnection/dgjdbc:User";
217                String user = XMLTools.getNodeAsString( doc, xpath, nsContext, null );
218                xpath = "/dgsec:OWSPolicy/dgsec:Security/dgsec:RegistryConfig/dgjdbc:JDBCConnection/dgjdbc:Password";
219                String password = XMLTools.getNodeAsString( doc, xpath, nsContext, null );
220                if ( driver != null && logon != null ) {
221                    DefaultDBConnection con = new DefaultDBConnection( driver, logon, user, password );
222                    registryConfig = new RegistryConfig( con );
223                } else if ( ( driver != null && logon == null ) || ( driver == null && logon != null ) ) {
224                    throw new SecurityConfigurationException( Messages.getString( "PolicyDocument.DatabaseConnection" ) );
225                }
226            } catch ( XMLParsingException e ) {
227                throw new SecurityConfigurationException( e.getMessage() );
228            }
229    
230            // } catch ( Exception e ) {
231            // LOG.logError( e.getMessage(), e );
232            // throw new SecurityConfigurationException( StringTools.stackTraceToString( e ) );
233            // }
234            return registryConfig;
235        }
236    
237        /**
238         * returns the settings for accessing the authentification authority
239         * 
240         * @return the settings for accessing the authentification authority
241         * @throws SecurityConfigurationException
242         */
243        private AuthentificationSettings getAuthentificationSettings()
244                                throws SecurityConfigurationException {
245            AuthentificationSettings authSet = null;
246    
247            StringBuffer xpath = new StringBuffer( "/dgsec:OWSPolicy/dgsec:Security/" );
248            xpath.append( "dgsec:AuthentificationSettings/dgsec:AuthentificationService" );
249            xpath.append( "/dgsec:OnlineResource/@xlink:href" );
250            try {
251                String onlineRes = XMLTools.getNodeAsString( doc, xpath.toString(), nsContext, null );
252                if ( onlineRes != null ) {
253                    BaseURL baseURL = new BaseURL( null, new URL( onlineRes ) );
254                    authSet = new AuthentificationSettings( baseURL );
255                }
256            } catch ( XMLParsingException e ) {
257                throw new SecurityConfigurationException( e.getMessage() );
258            } catch ( MalformedURLException e ) {
259                throw new SecurityConfigurationException( e.getMessage() );
260            }
261    
262            // } catch ( Exception e ) {
263            // LOG.logError( e.getMessage(), e );
264            // throw new SecurityConfigurationException( StringTools.stackTraceToString( e ) );
265            // }
266    
267            return authSet;
268        }
269    
270        /**
271         * @return returns the requests described by the policy document
272         */
273        private Request[] getRequests()
274                                throws SecurityConfigurationException {
275            Request[] requests = null;
276            // try {
277            List<Node> nl = null;
278            try {
279                nl = XMLTools.getNodes( doc, "/dgsec:OWSPolicy/dgsec:Requests/*", nsContext );
280            } catch ( XMLParsingException e ) {
281                throw new SecurityConfigurationException( e.getMessage() );
282            }
283            if ( nl != null ) {
284                requests = new Request[nl.size()];
285                for ( int i = 0; i < requests.length; i++ ) {
286                    requests[i] = getRequest( (Element) nl.get( i ) );
287                }
288            }
289            // } catch ( Exception e ) {
290            // LOG.logError( e.getMessage(), e );
291            // throw new SecurityConfigurationException( StringTools.stackTraceToString( e ) );
292            // }
293            return requests;
294        }
295    
296        /**
297         * returns the requests described by the passed <tt>Element</tt>
298         * 
299         * @param element
300         * @return created <tt>Request</tt>
301         * @throws SecurityConfigurationException
302         */
303        private Request getRequest( Element element )
304                                throws SecurityConfigurationException {
305            String name = element.getLocalName();
306            Request request = null;
307            Condition preCon = null;
308            Condition postCon = null;
309    
310            try {
311                boolean any = XMLTools.getNode( element, "./dgsec:PreConditions/dgsec:Any", nsContext ) != null;
312                if ( any ) {
313                    preCon = new Condition( true );
314                } else {
315                    List<Node> nl = XMLTools.getNodes( element, "./dgsec:PreConditions/dgsec:Parameter", nsContext );
316                    OperationParameter[] op = new OperationParameter[nl.size()];
317                    for ( int i = 0; i < nl.size(); i++ ) {
318                        op[i] = getOperationParameter( (Element) nl.get( i ) );
319                    }
320                    preCon = new Condition( op );
321                }
322    
323                any = XMLTools.getNode( element, "./dgsec:PostConditions/dgsec:Any", nsContext ) != null;
324                if ( any ) {
325                    postCon = new Condition( true );
326                } else {
327                    List<Node> nl = XMLTools.getNodes( element, "./dgsec:PostConditions/dgsec:Parameter", nsContext );
328                    OperationParameter[] op = new OperationParameter[nl.size()];
329                    for ( int i = 0; i < nl.size(); i++ ) {
330                        op[i] = getOperationParameter( (Element) nl.get( i ) );
331                    }
332                    postCon = new Condition( op );
333                }
334                request = new Request( service, name, preCon, postCon );
335            } catch ( XMLParsingException e ) {
336                LOG.logError( e.getMessage(), e );
337                throw new SecurityConfigurationException( e.getMessage() );
338            }
339    
340            // } catch ( Exception e ) {
341            // LOG.logError( e.getMessage(), e );
342            // throw new SecurityConfigurationException( StringTools.stackTraceToString( e ) );
343            // }
344    
345            return request;
346        }
347    
348        /**
349         * creates an <tt>OperationParameter</tt> with the passed name from the also passed root XPath. A root XPath is an
350         * expression to the desired parameter node.
351         * 
352         * @param name
353         *            name of the OperationParameter
354         * @param xpathRoot
355         * @return the parameter
356         * @throws SecurityConfigurationException
357         */
358        private OperationParameter getOperationParameter( String name, String xpathRoot )
359                                throws SecurityConfigurationException {
360            OperationParameter op = null;
361            // try {
362            try {
363                if ( XMLTools.getNodes( doc, xpathRoot, nsContext ).size() == 0 ) {
364                    // return OperationParameter that denies any access
365                    return new OperationParameter( name, false );
366                }
367                // is parameter coupled to user specific rights
368                String tmp = XMLTools.getRequiredNodeAsString( doc, xpathRoot + "/@userCoupled", nsContext ).toLowerCase();
369                boolean userCoupled = tmp.equals( "true" ) || tmp.equals( "1" );
370    
371                // is any? -> no restrictions
372                tmp = XMLTools.getNodeAsString( doc, xpathRoot + "/dgsec:Any", nsContext, "false" );
373                boolean any = !tmp.equals( "false" );
374    
375                if ( !any ) {
376                    // get values if not 'any'
377                    List<Element> list = XMLTools.getElements( doc, xpathRoot + "/dgsec:Value", nsContext );
378                    List<String> valueList = null;
379                    if ( list != null ) {
380                        valueList = new ArrayList<String>( list.size() );
381                        for ( int j = 0; j < list.size(); j++ ) {
382                            valueList.add( XMLTools.getStringValue( list.get( j ) ) );
383                        }
384                    }
385                    list = XMLTools.getElements( doc, xpathRoot + "/dgsec:ComplexValue/*", nsContext );
386                    op = new OperationParameter( name, valueList, list, userCoupled );
387                } else {
388                    op = new OperationParameter( name, any );
389                }
390            } catch ( XMLParsingException e ) {
391                LOG.logError( e.getMessage(), e );
392                throw new SecurityConfigurationException( e.getMessage() );
393            }
394    
395            // } catch ( Exception e ) {
396            // LOG.logError( e.getMessage(), e );
397            // throw new SecurityConfigurationException( StringTools.stackTraceToString( e ) );
398            // }
399            return op;
400        }
401    
402        /**
403         * creates an <tt>OperationParameter</tt> from the passed element.
404         * 
405         * @param element
406         *            encapsulating a parameter
407         * @return created <tt>OperationParameter</tt>
408         * @throws XMLParsingException
409         */
410        private OperationParameter getOperationParameter( Element element )
411                                throws XMLParsingException {
412            OperationParameter op = null;
413            String name = XMLTools.getRequiredAttrValue( "name", null, element );
414            String uc = XMLTools.getAttrValue( element, null, "userCoupled", "false" );
415            boolean userCoupled = uc.equals( "true" ) || uc.equals( "1" );
416            boolean any = XMLTools.getNode( element, "dgsec:Any", nsContext ) != null;
417            if ( !any ) {
418                List<Element> list = XMLTools.getElements( element, "dgsec:Value", nsContext );
419                List<String> valueList = null;
420                if ( list != null ) {
421                    valueList = new ArrayList<String>( list.size() );
422                    for ( int j = 0; j < list.size(); j++ ) {
423                        valueList.add( XMLTools.getStringValue( list.get( j ) ) );
424                    }
425                }
426                list = XMLTools.getElements( element, "dgsec:ComplexValue/*", nsContext );
427                op = new OperationParameter( name, valueList, list, userCoupled );
428            } else {
429                op = new OperationParameter( name, any );
430            }
431    
432            return op;
433        }
434    
435    }